luaur_vm/functions/
lua_v_call_tm.rs1use crate::macros::clvalue::clvalue;
2use crate::macros::incr_ci::incr_ci;
3use crate::macros::lua_d_checkstack::luaD_checkstack;
4use crate::macros::lua_minstack::LUA_MINSTACK;
5use crate::macros::luai_maxccalls::LUAI_MAXCCALLS;
6use crate::macros::setnilvalue::setnilvalue;
7use crate::macros::setobj_2_s::setobj2s;
8use crate::macros::ttisfunction::ttisfunction;
9use crate::records::call_info::CallInfo;
10use crate::records::closure::Closure;
11use crate::records::lua_state::lua_State;
12use crate::type_aliases::lua_c_function::lua_CFunction;
13use crate::type_aliases::stk_id::StkId;
14use crate::type_aliases::t_value::TValue;
15use luaur_common::macros::luau_assert::LUAU_ASSERT;
16use luaur_common::FFlag;
17
18#[allow(non_snake_case)]
20pub unsafe fn lua_v_call_tm(L: *mut lua_State, nparams: i32, res: i32) {
21 (*L).nCcalls += 1;
23
24 if (*L).nCcalls >= LUAI_MAXCCALLS as u16 {
25 crate::functions::lua_d_check_cstack::luaD_checkCstack(L);
26 }
27
28 luaD_checkstack!(L, LUA_MINSTACK);
29
30 let top = (*L).top;
31 let fun = top.sub(nparams as usize).sub(1);
32
33 let ci = incr_ci!(L);
34 (*ci).func = fun;
35 (*ci).base = fun.add(1);
36 (*ci).top = top.add(LUA_MINSTACK as usize);
37 (*ci).savedpc = std::ptr::null_mut();
38 (*ci).flags = 0;
39 (*ci).nresults = if res >= 0 { 1 } else { 0 };
40 LUAU_ASSERT!((*ci).top <= (*L).stack_last);
41
42 let mut ccl: *mut Closure = std::ptr::null_mut();
43 if FFlag::LuauClosureUsageCounter.get() {
44 ccl = clvalue!(fun) as *mut Closure;
45 (*ccl).usage += 1;
46 }
47
48 LUAU_ASSERT!(ttisfunction!((*ci).func));
49 LUAU_ASSERT!((clvalue!((*ci).func) as *mut Closure).is_null() == false);
50 LUAU_ASSERT!((clvalue!((*ci).func) as *mut Closure).is_null() == false);
51 LUAU_ASSERT!((*clvalue!((*ci).func)).isC != 0);
52
53 (*L).base = fun.add(1);
54 LUAU_ASSERT!((*L).top == (*L).base.add(nparams as usize));
55
56 let cl = clvalue!(fun);
57 let c = core::ptr::addr_of!((*cl).inner.c).cast::<crate::records::closure::CClosure>();
58 let func = (*c).f;
59 let n = func.unwrap()(L);
60 LUAU_ASSERT!(n >= 0); let cip = (*L).ci.sub(1);
65
66 if FFlag::LuauClosureUsageCounter.get() {
67 LUAU_ASSERT!((*ccl).usage > 0);
68 (*ccl).usage -= 1;
69 }
70
71 if res >= 0 {
73 if n > 0 {
74 setobj2s!(
75 L,
76 (*cip).base.add(res as usize),
77 (*L).top.sub(n as usize) as *const TValue
78 );
79 } else {
80 setnilvalue!((*cip).base.add(res as usize));
81 }
82 }
83
84 (*L).ci = cip;
85 (*L).base = (*cip).base;
86 (*L).top = (*cip).top;
87
88 (*L).nCcalls -= 1;
89}