Skip to main content

luaur_vm/functions/
shrinkstack.rs

1use crate::functions::lua_d_realloc_ci::lua_d_realloc_ci;
2use crate::functions::lua_d_reallocstack::lua_d_reallocstack;
3use crate::macros::basic_ci_size::BASIC_CI_SIZE;
4use crate::macros::basic_stack_size::BASIC_STACK_SIZE;
5use crate::macros::cast_int::cast_int;
6use crate::macros::condhardstacktests::condhardstacktests;
7use crate::macros::extra_stack::EXTRA_STACK;
8use crate::macros::luai_maxcalls::LUAI_MAXCALLS;
9use crate::records::call_info::CallInfo;
10use crate::type_aliases::lua_state::lua_State;
11use crate::type_aliases::stk_id::StkId;
12use luaur_common::macros::luau_assert::LUAU_ASSERT;
13
14#[allow(non_snake_case)]
15pub unsafe fn shrinkstack(L: *mut lua_State) {
16    // compute used stack - note that we can't use th->top if we're in the middle of vararg call
17    let mut lim: StkId = (*L).top;
18    let mut ci: *mut CallInfo = (*L).base_ci;
19    while ci <= (*L).ci {
20        LUAU_ASSERT!((*ci).top <= (*L).stack_last);
21        if lim < (*ci).top {
22            lim = (*ci).top;
23        }
24        ci = ci.add(1);
25    }
26
27    // shrink stack and callinfo arrays if we aren't using most of the space
28    let ci_used = cast_int!((*L).ci.offset_from((*L).base_ci));
29    let s_used = cast_int!(lim.offset_from((*L).stack));
30    if (*L).size_ci > LUAI_MAXCALLS {
31        // handling overflow?
32        return;
33    }
34
35    if 3 * (ci_used as usize) < (*L).size_ci as usize && 2 * BASIC_CI_SIZE < (*L).size_ci {
36        lua_d_realloc_ci(L, (*L).size_ci / 2); // still big enough...
37    }
38
39    condhardstacktests!(lua_d_realloc_ci(L, ci_used + 1));
40
41    if 3 * (s_used as usize) < (*L).stacksize as usize
42        && 2 * (BASIC_STACK_SIZE + EXTRA_STACK) < (*L).stacksize
43    {
44        lua_d_reallocstack(L, (*L).stacksize / 2, 0); // still big enough...
45    }
46
47    condhardstacktests!(lua_d_reallocstack(L, s_used, 0));
48}