Skip to main content

luaur_code_gen/functions/
on_disable.rs

1//! Node: `cxx:Function:Luau.CodeGen:CodeGen/src/CodeGen.cpp:100:on_disable`
2//!
3//! Disable native code for a proto: point its entry back at bytecode, clear the
4//! exec target, and walk every thread's Lua call stack clearing the
5//! `LUA_CALLINFO_NATIVE` flag on any frame still pointing at this proto.
6
7use core::ffi::c_void;
8use luaur_vm::enums::lua_type::lua_Type;
9use luaur_vm::functions::lua_m_visitgco::lua_m_visitgco;
10use luaur_vm::macros::clvalue::clvalue;
11use luaur_vm::macros::gco_2_th::gco2th;
12use luaur_vm::macros::is_lua::isLua;
13use luaur_vm::macros::lua_callinfo_native::LUA_CALLINFO_NATIVE;
14use luaur_vm::records::gc_object::GCObject;
15use luaur_vm::records::lua_page::lua_Page;
16use luaur_vm::records::proto::Proto;
17use luaur_vm::type_aliases::lua_state::lua_State;
18
19unsafe fn on_disable_visitor(
20    context: *mut c_void,
21    _page: *mut lua_Page,
22    gco: *mut GCObject,
23) -> bool {
24    let proto = context as *mut Proto;
25
26    if (*gco).gch.tt as i32 != lua_Type::LUA_TTHREAD as i32 {
27        return false;
28    }
29
30    let th = gco2th!(gco);
31
32    let mut ci = (*th).ci;
33    while ci > (*th).base_ci {
34        if isLua!(ci) {
35            let f = &*clvalue!((*ci).func);
36            let p = f.inner.l.p;
37
38            if p == proto {
39                (*ci).flags &= !(LUA_CALLINFO_NATIVE as u32);
40            }
41        }
42        ci = ci.sub(1);
43    }
44
45    false
46}
47
48pub unsafe fn on_disable(L: *mut lua_State, proto: *mut Proto) {
49    // do nothing if proto already uses bytecode
50    if (*proto).codeentry == (*proto).code as *const _ {
51        return;
52    }
53
54    // ensure that VM does not call native code for this proto
55    (*proto).codeentry = (*proto).code as *const _;
56
57    // prevent native code from entering proto with breakpoints
58    (*proto).exectarget = 0;
59
60    lua_m_visitgco(L, proto as *mut c_void, on_disable_visitor as *mut c_void);
61}
62
63#[export_name = "on_disable"]
64pub unsafe extern "C" fn on_disable_export(L: *mut lua_State, proto: *mut Proto) {
65    on_disable(L, proto);
66}