Skip to main content

luaur_vm/functions/
lua_f_recordhit.rs

1//! `luaF_recordhit` — record a call-target hit in the caller's feedback vector.
2//! C++ source: `VM/src/lfunc.cpp:225`
3//!
4//! Returns `true` if the inline threshold has not yet been reached for this
5//! slot (caller should continue speculation), `false` otherwise.
6
7use crate::enums::feedback_vector_slot_kind::FeedbackVectorSlotKind;
8use crate::records::closure::Closure;
9use crate::records::lua_state::lua_State;
10use luaur_common::macros::luau_assert::LUAU_ASSERT;
11
12#[no_mangle]
13#[allow(non_snake_case)]
14pub unsafe fn luaF_recordhit(
15    l: *mut lua_State,
16    caller: *mut Closure,
17    target: *mut Closure,
18    slotid: u32,
19) -> bool {
20    if (*(*l).global).ecb.inlinefunction.is_none() {
21        return false;
22    }
23
24    LUAU_ASSERT!((*caller).isC == 0);
25    let callerp =
26        (*(core::ptr::addr_of!((*caller).inner.l) as *const crate::records::closure::LClosure)).p;
27
28    if (*target).isC != 0 {
29        return false;
30    }
31    let targetp =
32        (*(core::ptr::addr_of!((*target).inner.l) as *const crate::records::closure::LClosure)).p;
33
34    LUAU_ASSERT!(slotid < (*callerp).feedbackvecsize);
35    let slot = (*callerp).feedbackvec.add(slotid as usize);
36    LUAU_ASSERT!((*slot).kind == FeedbackVectorSlotKind::CALL_TARGET);
37
38    if (*slot).data.call_target.proto == 0 {
39        (*slot).data.call_target.proto = (*targetp).funid;
40    }
41
42    if (*slot).data.call_target.proto != (*targetp).funid {
43        return false;
44    }
45
46    (*slot).data.call_target.hits += 1;
47
48    if (*slot).data.call_target.hits as i32 >= luaur_common::FInt::LuauInlineHitsThreshold.get() {
49        if let Some(inline_fn) = (*(*l).global).ecb.inlinefunction {
50            inline_fn(l, caller, target, (*slot).data.call_target.pc);
51        }
52        return false;
53    }
54
55    true
56}