Skip to main content

luaur_repl_cli/functions/
lua_callgrind.rs

1use core::ffi::CStr;
2
3use luaur_vm::functions::lua_l_checklstring::lua_l_checklstring;
4use luaur_vm::functions::lua_pushboolean::lua_pushboolean;
5use luaur_vm::macros::lua_l_error::luaL_error;
6use luaur_vm::type_aliases::lua_state::lua_State;
7
8// Faithful port of the `#ifdef CALLGRIND` `lua_callgrind` in Repl.cpp.
9//
10// The valgrind client-request macros (RUNNING_ON_VALGRIND, CALLGRIND_ZERO_STATS,
11// CALLGRIND_DUMP_STATS_AT) are inline assembly sequences that valgrind's
12// instrumentation intercepts. When the process is NOT running under valgrind
13// (the only situation a normal build encounters), they evaluate to:
14//   - RUNNING_ON_VALGRIND  -> 0
15//   - CALLGRIND_ZERO_STATS -> no observable effect
16//   - CALLGRIND_DUMP_STATS_AT(name) -> no observable effect
17// We reproduce exactly that runtime behavior here.
18pub unsafe fn lua_callgrind(l: *mut lua_State) -> i32 {
19    let mut len: usize = 0;
20    let option = lua_l_checklstring(l, 1, &mut len as *mut usize);
21    let option = CStr::from_ptr(option);
22
23    if option.to_bytes() == b"running" {
24        let r = running_on_valgrind();
25        lua_pushboolean(l, r);
26        return 1;
27    }
28
29    if option.to_bytes() == b"zero" {
30        callgrind_zero_stats();
31        return 0;
32    }
33
34    if option.to_bytes() == b"dump" {
35        let mut name_len: usize = 0;
36        let name = lua_l_checklstring(l, 2, &mut name_len as *mut usize);
37
38        callgrind_dump_stats_at(name);
39        return 0;
40    }
41
42    luaL_error!(
43        l,
44        "callgrind must be called with one of 'running', 'zero', 'dump'"
45    );
46    0
47}
48
49#[inline]
50fn running_on_valgrind() -> core::ffi::c_int {
51    // No valgrind instrumentation present: RUNNING_ON_VALGRIND evaluates to 0.
52    0
53}
54
55#[inline]
56fn callgrind_zero_stats() {
57    // CALLGRIND_ZERO_STATS is a no-op outside valgrind.
58}
59
60#[inline]
61unsafe fn callgrind_dump_stats_at(_name: *const core::ffi::c_char) {
62    // CALLGRIND_DUMP_STATS_AT is a no-op outside valgrind.
63}