luaur_vm/functions/
lua_c_step.rs1use 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}