|
@@ -96,27 +96,45 @@ void lj_state_shrinkstack(lua_State *L, MSize used)
|
|
|
/* Try to grow stack. */
|
|
|
void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need)
|
|
|
{
|
|
|
- MSize n;
|
|
|
- if (L->stacksize >= LJ_STACK_MAXEX) {
|
|
|
- /* 4. Throw 'error in error handling' when we are _over_ the limit. */
|
|
|
- if (L->stacksize > LJ_STACK_MAXEX)
|
|
|
+ MSize n = L->stacksize + need;
|
|
|
+ if (LJ_LIKELY(n < LJ_STACK_MAX)) { /* The stack can grow as requested. */
|
|
|
+ if (n < 2 * L->stacksize) { /* Try to double the size. */
|
|
|
+ n = 2 * L->stacksize;
|
|
|
+ if (n > LJ_STACK_MAX)
|
|
|
+ n = LJ_STACK_MAX;
|
|
|
+ }
|
|
|
+ resizestack(L, n);
|
|
|
+ } else { /* Request would overflow. Raise a stack overflow error. */
|
|
|
+ if (curr_funcisL(L)) {
|
|
|
+ L->top = curr_topL(L);
|
|
|
+ if (L->top > tvref(L->maxstack)) {
|
|
|
+ /* The current Lua frame violates the stack, so replace it with a
|
|
|
+ ** dummy. This can happen when BC_IFUNCF is trying to grow the stack.
|
|
|
+ */
|
|
|
+ L->top = L->base;
|
|
|
+ setframe_gc(L->base - 1, obj2gco(L));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (L->stacksize <= LJ_STACK_MAXEX) {
|
|
|
+ /* An error handler might want to inspect the stack overflow error, but
|
|
|
+ ** will need some stack space to run in. We give it a stack size beyond
|
|
|
+ ** the normal limit in order to do so, then rely on lj_state_relimitstack
|
|
|
+ ** calls during unwinding to bring us back to a convential stack size.
|
|
|
+ ** The + 1 is space for the error message, and 2 * LUA_MINSTACK is for
|
|
|
+ ** the lj_state_checkstack() call in lj_err_run().
|
|
|
+ */
|
|
|
+ resizestack(L, LJ_STACK_MAX + 1 + 2 * LUA_MINSTACK);
|
|
|
+ lj_err_stkov(L); /* May invoke an error handler. */
|
|
|
+ } else {
|
|
|
+ /* If we're here, then the stack overflow error handler is requesting
|
|
|
+ ** to grow the stack even further. We have no choice but to abort the
|
|
|
+ ** error handler.
|
|
|
+ */
|
|
|
+ GCstr *em = lj_err_str(L, LJ_ERR_STKOV); /* Might OOM. */
|
|
|
+ setstrV(L, L->top++, em); /* There is always space to push an error. */
|
|
|
lj_err_throw(L, LUA_ERRERR); /* Does not invoke an error handler. */
|
|
|
- /* 1. We are _at_ the limit after the last growth. */
|
|
|
- if (L->status < LUA_ERRRUN) { /* 2. Throw 'stack overflow'. */
|
|
|
- L->status = LUA_ERRRUN; /* Prevent ending here again for pushed msg. */
|
|
|
- lj_err_msg(L, LJ_ERR_STKOV); /* May invoke an error handler. */
|
|
|
}
|
|
|
- /* 3. Add space (over the limit) for pushed message and error handler. */
|
|
|
- }
|
|
|
- n = L->stacksize + need;
|
|
|
- if (n > LJ_STACK_MAX) {
|
|
|
- n += 2*LUA_MINSTACK;
|
|
|
- } else if (n < 2*L->stacksize) {
|
|
|
- n = 2*L->stacksize;
|
|
|
- if (n >= LJ_STACK_MAX)
|
|
|
- n = LJ_STACK_MAX;
|
|
|
}
|
|
|
- resizestack(L, n);
|
|
|
}
|
|
|
|
|
|
void LJ_FASTCALL lj_state_growstack1(lua_State *L)
|