Skip to main content

luaur_vm/functions/
lua_c_validate.rs

1use crate::enums::lua_type::lua_Type;
2use crate::functions::lua_m_visitgco::lua_m_visitgco;
3use crate::functions::validategco::validategco;
4use crate::functions::validategraylist::validategraylist;
5use crate::macros::checkliveness::checkliveness;
6use crate::macros::isblack::isblack;
7use crate::macros::isdead::isdead;
8use crate::macros::obj_2_gco::obj2gco;
9use crate::macros::upisopen::upisopen;
10use crate::records::gc_object::GCObject;
11use crate::records::global_state::global_State;
12use crate::records::lua_page::lua_Page;
13use crate::records::lua_state::lua_State;
14use crate::type_aliases::up_val::UpVal;
15use core::ffi::c_void;
16use luaur_common::macros::luau_assert::LUAU_ASSERT;
17
18#[allow(non_snake_case)]
19pub unsafe fn lua_c_validate(L: *mut lua_State) {
20    let g: *mut global_State = (*L).global;
21
22    // The obj2gco! macro relies on ttype!, which expects a .tt() method.
23    // Since the Rust records for lua_State, LuaTable, and UpVal use a field hdr.tt instead of a method,
24    // we must cast these pointers to *mut GCObject (which is what obj2gco! effectively does via cast_to!)
25    // to bypass the ttype! check on the specific record types.
26    LUAU_ASSERT!(!isdead!(g, (*g).mainthread as *mut GCObject));
27    checkliveness!(g, &(*g).registry);
28
29    for i in 0..(crate::enums::lua_type::LUA_T_COUNT as i32) {
30        let mt = (*g).mt[i as usize];
31        if !mt.is_null() {
32            LUAU_ASSERT!(!isdead!(g, mt as *mut GCObject));
33        }
34    }
35
36    validategraylist(g, (*g).weak as *mut GCObject);
37    validategraylist(g, (*g).gray as *mut GCObject);
38    validategraylist(g, (*g).grayagain as *mut GCObject);
39
40    validategco(
41        L as *mut c_void,
42        core::ptr::null_mut::<lua_Page>(),
43        (*g).mainthread as *mut GCObject,
44    );
45
46    lua_m_visitgco(L, L as *mut c_void, validategco as *mut c_void);
47
48    let mut uv: *mut UpVal = (*g).uvhead.u.open.next;
49    while uv != &mut (*g).uvhead {
50        LUAU_ASSERT!((*uv).hdr.tt == lua_Type::LUA_TUPVAL as u8);
51        LUAU_ASSERT!(upisopen!(uv));
52        LUAU_ASSERT!(
53            (*(*uv).u.open.next).u.open.prev == uv && (*(*uv).u.open.prev).u.open.next == uv
54        );
55        // open upvalues are never black
56        LUAU_ASSERT!(!isblack!(uv as *mut GCObject));
57        uv = (*uv).u.open.next;
58    }
59}