diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-12-08 15:28:25 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-12-08 15:28:25 -0200 |
commit | e663a24ab03a54fa221c20a793812e5c5ffdf94f (patch) | |
tree | 8fbd40f779f0eed29d46f26c07e1234fd5df8bae /ldo.c | |
parent | 40f823ec907fd725617e37199199b3ed424bd88c (diff) | |
download | lua-e663a24ab03a54fa221c20a793812e5c5ffdf94f.tar.gz lua-e663a24ab03a54fa221c20a793812e5c5ffdf94f.tar.bz2 lua-e663a24ab03a54fa221c20a793812e5c5ffdf94f.zip |
more freedom in handling memory-allocation errors (not all allocations
automatically raise an error), which allows fixing a bug when resizing
a table.
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 42 |
1 files changed, 23 insertions, 19 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.176 2017/11/29 13:02:17 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.177 2017/12/01 15:44:51 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -156,17 +156,17 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
156 | ** Stack reallocation | 156 | ** Stack reallocation |
157 | ** =================================================================== | 157 | ** =================================================================== |
158 | */ | 158 | */ |
159 | static void correctstack (lua_State *L, StkId oldstack) { | 159 | static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { |
160 | CallInfo *ci; | 160 | CallInfo *ci; |
161 | UpVal *up; | 161 | UpVal *up; |
162 | if (L->stack == oldstack) | 162 | if (oldstack == newstack) |
163 | return; /* stack address did not change */ | 163 | return; /* stack address did not change */ |
164 | L->top = (L->top - oldstack) + L->stack; | 164 | L->top = (L->top - oldstack) + newstack; |
165 | for (up = L->openupval; up != NULL; up = up->u.open.next) | 165 | for (up = L->openupval; up != NULL; up = up->u.open.next) |
166 | up->v = s2v((uplevel(up) - oldstack) + L->stack); | 166 | up->v = s2v((uplevel(up) - oldstack) + newstack); |
167 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 167 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
168 | ci->top = (ci->top - oldstack) + L->stack; | 168 | ci->top = (ci->top - oldstack) + newstack; |
169 | ci->func = (ci->func - oldstack) + L->stack; | 169 | ci->func = (ci->func - oldstack) + newstack; |
170 | if (isLua(ci)) | 170 | if (isLua(ci)) |
171 | ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ | 171 | ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ |
172 | } | 172 | } |
@@ -177,36 +177,40 @@ static void correctstack (lua_State *L, StkId oldstack) { | |||
177 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) | 177 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) |
178 | 178 | ||
179 | 179 | ||
180 | void luaD_reallocstack (lua_State *L, int newsize) { | 180 | int luaD_reallocstack (lua_State *L, int newsize, int safe) { |
181 | StkId oldstack = L->stack; | ||
182 | int lim = L->stacksize; | 181 | int lim = L->stacksize; |
182 | StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue); | ||
183 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); | 183 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); |
184 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); | 184 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); |
185 | luaM_reallocvector(L, L->stack, L->stacksize, newsize, StackValue); | 185 | if (newstack == NULL) { /* reallocation failed? */ |
186 | if (safe) luaM_error(L); | ||
187 | else return 0; /* no-safe mode: signal the error */ | ||
188 | } | ||
186 | for (; lim < newsize; lim++) | 189 | for (; lim < newsize; lim++) |
187 | setnilvalue(s2v(L->stack + lim)); /* erase new segment */ | 190 | setnilvalue(s2v(newstack + lim)); /* erase new segment */ |
191 | correctstack(L, L->stack, newstack); | ||
192 | L->stack = newstack; | ||
188 | L->stacksize = newsize; | 193 | L->stacksize = newsize; |
189 | L->stack_last = L->stack + newsize - EXTRA_STACK; | 194 | L->stack_last = L->stack + newsize - EXTRA_STACK; |
190 | correctstack(L, oldstack); | 195 | return 1; |
191 | } | 196 | } |
192 | 197 | ||
193 | 198 | ||
194 | void luaD_growstack (lua_State *L, int n) { | 199 | int luaD_growstack (lua_State *L, int n, int safe) { |
195 | int size = L->stacksize; | 200 | int size = L->stacksize; |
201 | int newsize = 2 * size; | ||
196 | if (size > LUAI_MAXSTACK) /* error after extra size? */ | 202 | if (size > LUAI_MAXSTACK) /* error after extra size? */ |
197 | luaD_throw(L, LUA_ERRERR); | 203 | luaD_throw(L, LUA_ERRERR); |
198 | else { | 204 | else { |
199 | int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; | 205 | int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; |
200 | int newsize = 2 * size; | ||
201 | if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; | 206 | if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; |
202 | if (newsize < needed) newsize = needed; | 207 | if (newsize < needed) newsize = needed; |
203 | if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ | 208 | if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ |
204 | luaD_reallocstack(L, ERRORSTACKSIZE); | 209 | luaD_reallocstack(L, ERRORSTACKSIZE, 1); |
205 | luaG_runerror(L, "stack overflow"); | 210 | luaG_runerror(L, "stack overflow"); |
206 | } | 211 | } |
207 | else | 212 | } /* else */ |
208 | luaD_reallocstack(L, newsize); | 213 | return luaD_reallocstack(L, newsize, safe); |
209 | } | ||
210 | } | 214 | } |
211 | 215 | ||
212 | 216 | ||
@@ -234,7 +238,7 @@ void luaD_shrinkstack (lua_State *L) { | |||
234 | good size is smaller than current size, shrink its stack */ | 238 | good size is smaller than current size, shrink its stack */ |
235 | if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && | 239 | if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && |
236 | goodsize < L->stacksize) | 240 | goodsize < L->stacksize) |
237 | luaD_reallocstack(L, goodsize); | 241 | luaD_reallocstack(L, goodsize, 0); /* ok if that fails */ |
238 | else /* don't change stack */ | 242 | else /* don't change stack */ |
239 | condmovestack(L,{},{}); /* (change only for debugging) */ | 243 | condmovestack(L,{},{}); /* (change only for debugging) */ |
240 | } | 244 | } |