Skip to main content

luaur_vm/functions/
lua_c_step.rs

1use crate::functions::finish_gc_cycle_metrics::finish_gc_cycle_metrics;
2use crate::functions::gcstep::gcstep;
3use crate::functions::getheaptrigger::getheaptrigger;
4use crate::functions::lua_clock::lua_clock;
5use crate::functions::record_gc_state_step::record_gc_state_step;
6use crate::functions::start_gc_cycle_metrics::start_gc_cycle_metrics;
7use crate::type_aliases::lua_state::lua_State;
8use core::ffi::c_int;
9use luaur_common::macros::luau_assert::LUAU_ASSERT;
10
11#[inline]
12unsafe fn gc_interrupt(l: *mut lua_State, state: c_int) {
13    let g = &*(*l).global;
14    if let Some(interrupt) = g.cb.interrupt {
15        interrupt(l, state);
16    }
17}
18
19#[allow(non_snake_case)]
20pub unsafe fn luaC_step(l: *mut lua_State, assist: bool) -> usize {
21    let g = (*l).global;
22
23    let lim = ((*g).gcstepsize as usize * (*g).gcstepmul as usize) / 100;
24    LUAU_ASSERT!((*g).totalbytes >= (*g).GCthreshold);
25    let debt = (*g).totalbytes - (*g).GCthreshold;
26
27    gc_interrupt(l, 0);
28
29    if (*g).gcstate == 0 {
30        (*g).gcstats.starttimestamp = lua_clock();
31    }
32
33    #[cfg(feature = "luai_gcmetrics")]
34    {
35        if (*g).gcstate == 0 {
36            start_gc_cycle_metrics(g);
37        }
38        let _lasttimestamp = lua_clock();
39    }
40
41    let lastgcstate = (*g).gcstate as i32;
42
43    let work = gcstep(l, lim);
44
45    #[cfg(feature = "luai_gcmetrics")]
46    {
47        record_gc_state_step(g, lastgcstate, lua_clock() - _lasttimestamp, assist, work);
48    }
49
50    let actualstepsize = (work * 100) / (*g).gcstepmul as usize;
51
52    if (*g).gcstate == 0 {
53        let heapgoal = ((*g).totalbytes / 100) * (*g).gcgoal as usize;
54        let heaptrigger = getheaptrigger(g, heapgoal);
55
56        (*g).GCthreshold = heaptrigger;
57
58        (*g).gcstats.heapgoalsizebytes = heapgoal;
59        (*g).gcstats.endtimestamp = lua_clock();
60        (*g).gcstats.endtotalsizebytes = (*g).totalbytes;
61
62        #[cfg(feature = "luai_gcmetrics")]
63        {
64            finish_gc_cycle_metrics(g);
65        }
66    } else {
67        (*g).GCthreshold = (*g).totalbytes + actualstepsize;
68
69        if (*g).GCthreshold >= debt {
70            (*g).GCthreshold -= debt;
71        }
72    }
73
74    gc_interrupt(l, lastgcstate);
75
76    actualstepsize
77}
78
79#[export_name = "luaC_step"]
80pub unsafe extern "C" fn lua_c_step_export(l: *mut lua_State, assist: bool) -> usize {
81    luaC_step(l, assist)
82}