diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_state.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/src/lj_state.c b/src/lj_state.c index c2f0b115..adedb66c 100644 --- a/src/lj_state.c +++ b/src/lj_state.c | |||
@@ -96,27 +96,45 @@ void lj_state_shrinkstack(lua_State *L, MSize used) | |||
96 | /* Try to grow stack. */ | 96 | /* Try to grow stack. */ |
97 | void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need) | 97 | void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need) |
98 | { | 98 | { |
99 | MSize n; | 99 | MSize n = L->stacksize + need; |
100 | if (L->stacksize >= LJ_STACK_MAXEX) { | 100 | if (LJ_LIKELY(n < LJ_STACK_MAX)) { /* The stack can grow as requested. */ |
101 | /* 4. Throw 'error in error handling' when we are _over_ the limit. */ | 101 | if (n < 2 * L->stacksize) { /* Try to double the size. */ |
102 | if (L->stacksize > LJ_STACK_MAXEX) | 102 | n = 2 * L->stacksize; |
103 | if (n > LJ_STACK_MAX) | ||
104 | n = LJ_STACK_MAX; | ||
105 | } | ||
106 | resizestack(L, n); | ||
107 | } else { /* Request would overflow. Raise a stack overflow error. */ | ||
108 | if (curr_funcisL(L)) { | ||
109 | L->top = curr_topL(L); | ||
110 | if (L->top > tvref(L->maxstack)) { | ||
111 | /* The current Lua frame violates the stack, so replace it with a | ||
112 | ** dummy. This can happen when BC_IFUNCF is trying to grow the stack. | ||
113 | */ | ||
114 | L->top = L->base; | ||
115 | setframe_gc(L->base - 1, obj2gco(L)); | ||
116 | } | ||
117 | } | ||
118 | if (L->stacksize <= LJ_STACK_MAXEX) { | ||
119 | /* An error handler might want to inspect the stack overflow error, but | ||
120 | ** will need some stack space to run in. We give it a stack size beyond | ||
121 | ** the normal limit in order to do so, then rely on lj_state_relimitstack | ||
122 | ** calls during unwinding to bring us back to a convential stack size. | ||
123 | ** The + 1 is space for the error message, and 2 * LUA_MINSTACK is for | ||
124 | ** the lj_state_checkstack() call in lj_err_run(). | ||
125 | */ | ||
126 | resizestack(L, LJ_STACK_MAX + 1 + 2 * LUA_MINSTACK); | ||
127 | lj_err_stkov(L); /* May invoke an error handler. */ | ||
128 | } else { | ||
129 | /* If we're here, then the stack overflow error handler is requesting | ||
130 | ** to grow the stack even further. We have no choice but to abort the | ||
131 | ** error handler. | ||
132 | */ | ||
133 | GCstr *em = lj_err_str(L, LJ_ERR_STKOV); /* Might OOM. */ | ||
134 | setstrV(L, L->top++, em); /* There is always space to push an error. */ | ||
103 | lj_err_throw(L, LUA_ERRERR); /* Does not invoke an error handler. */ | 135 | lj_err_throw(L, LUA_ERRERR); /* Does not invoke an error handler. */ |
104 | /* 1. We are _at_ the limit after the last growth. */ | ||
105 | if (L->status < LUA_ERRRUN) { /* 2. Throw 'stack overflow'. */ | ||
106 | L->status = LUA_ERRRUN; /* Prevent ending here again for pushed msg. */ | ||
107 | lj_err_msg(L, LJ_ERR_STKOV); /* May invoke an error handler. */ | ||
108 | } | 136 | } |
109 | /* 3. Add space (over the limit) for pushed message and error handler. */ | ||
110 | } | ||
111 | n = L->stacksize + need; | ||
112 | if (n > LJ_STACK_MAX) { | ||
113 | n += 2*LUA_MINSTACK; | ||
114 | } else if (n < 2*L->stacksize) { | ||
115 | n = 2*L->stacksize; | ||
116 | if (n >= LJ_STACK_MAX) | ||
117 | n = LJ_STACK_MAX; | ||
118 | } | 137 | } |
119 | resizestack(L, n); | ||
120 | } | 138 | } |
121 | 139 | ||
122 | void LJ_FASTCALL lj_state_growstack1(lua_State *L) | 140 | void LJ_FASTCALL lj_state_growstack1(lua_State *L) |