diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-12-06 09:43:58 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-12-06 09:43:58 -0200 |
commit | f356eb010b6785cf22e8d5f1d4f7761e0789ae51 (patch) | |
tree | 0afc8ffc0f1e7337ce995e4d7bc78c92fb938329 | |
parent | 3e38fd24639bc7cd8afe063619d5ab4637db696f (diff) | |
download | lua-f356eb010b6785cf22e8d5f1d4f7761e0789ae51.tar.gz lua-f356eb010b6785cf22e8d5f1d4f7761e0789ae51.tar.bz2 lua-f356eb010b6785cf22e8d5f1d4f7761e0789ae51.zip |
configurable stack size + some corrections in error recovery in
`protectedrun'
-rw-r--r-- | ldo.c | 59 |
1 files changed, 27 insertions, 32 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.55 1999/12/02 16:24:45 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.56 1999/12/02 16:41:29 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 | */ |
@@ -28,23 +28,19 @@ | |||
28 | #include "lzio.h" | 28 | #include "lzio.h" |
29 | 29 | ||
30 | 30 | ||
31 | |||
32 | #ifndef DEFAULT_STACK_SIZE | ||
33 | #define DEFAULT_STACK_SIZE 1024 | ||
34 | #endif | ||
35 | |||
36 | #define EXTRA_STACK 32 /* space to handle stack overflow errors */ | 31 | #define EXTRA_STACK 32 /* space to handle stack overflow errors */ |
37 | 32 | ||
38 | /* | 33 | /* |
39 | ** typical numer of recursive calls that fit in the stack | 34 | ** typical numer of stack slots used by a (big) function |
40 | ** (only for error messages) | 35 | ** (this constant is used only for choosing error messages) |
41 | */ | 36 | */ |
42 | #define REC_DEEP (DEFAULT_STACK_SIZE/20) | 37 | #define SLOTS_PER_F 20 |
43 | 38 | ||
44 | 39 | ||
45 | void luaD_init (lua_State *L) { | 40 | void luaD_init (lua_State *L, int stacksize) { |
46 | L->stack = luaM_newvector(L, DEFAULT_STACK_SIZE+EXTRA_STACK, TObject); | 41 | L->stack = luaM_newvector(L, stacksize+EXTRA_STACK, TObject); |
47 | L->stack_last = L->stack+(DEFAULT_STACK_SIZE-1); | 42 | L->stack_last = L->stack+(stacksize-1); |
43 | L->stacksize = stacksize; | ||
48 | L->Cstack.base = L->Cstack.lua2C = L->top = L->stack; | 44 | L->Cstack.base = L->Cstack.lua2C = L->top = L->stack; |
49 | L->Cstack.num = 0; | 45 | L->Cstack.num = 0; |
50 | } | 46 | } |
@@ -52,15 +48,15 @@ void luaD_init (lua_State *L) { | |||
52 | 48 | ||
53 | void luaD_checkstack (lua_State *L, int n) { | 49 | void luaD_checkstack (lua_State *L, int n) { |
54 | if (L->stack_last-L->top <= n) { /* stack overflow? */ | 50 | if (L->stack_last-L->top <= n) { /* stack overflow? */ |
55 | if (L->stack_last-L->stack > (DEFAULT_STACK_SIZE-1)) { | 51 | if (L->stack_last-L->stack > (L->stacksize-1)) { |
56 | /* overflow while handling overflow: do what?? */ | 52 | /* overflow while handling overflow: do what?? */ |
57 | L->top -= EXTRA_STACK; | 53 | L->top -= EXTRA_STACK; |
58 | lua_error(L, "BAD STACK OVERFLOW! DATA CORRUPTED!!"); | 54 | lua_error(L, "BAD STACK OVERFLOW! DATA CORRUPTED!!"); |
59 | } | 55 | } |
60 | else { | 56 | else { |
61 | L->stack_last += EXTRA_STACK; /* to be used by error message */ | 57 | L->stack_last += EXTRA_STACK; /* to be used by error message */ |
62 | if (lua_stackedfunction(L, REC_DEEP) == LUA_NOOBJECT) { | 58 | if (lua_stackedfunction(L, L->stacksize/SLOTS_PER_F) == LUA_NOOBJECT) { |
63 | /* less than REC_DEEP funcs on stack: doesn't look like a rec. loop */ | 59 | /* too few funcs on stack: doesn't look like a rec. loop */ |
64 | lua_error(L, "Lua2C - C2Lua overflow"); | 60 | lua_error(L, "Lua2C - C2Lua overflow"); |
65 | } | 61 | } |
66 | else | 62 | else |
@@ -71,8 +67,8 @@ void luaD_checkstack (lua_State *L, int n) { | |||
71 | 67 | ||
72 | 68 | ||
73 | static void restore_stack_limit (lua_State *L) { | 69 | static void restore_stack_limit (lua_State *L) { |
74 | if (L->top-L->stack < DEFAULT_STACK_SIZE-1) | 70 | if (L->top-L->stack < L->stacksize-1) |
75 | L->stack_last = L->stack+(DEFAULT_STACK_SIZE-1); | 71 | L->stack_last = L->stack+(L->stacksize-1); |
76 | } | 72 | } |
77 | 73 | ||
78 | 74 | ||
@@ -145,7 +141,7 @@ static StkId callC (lua_State *L, lua_CFunction f, StkId base) { | |||
145 | if (L->callhook) | 141 | if (L->callhook) |
146 | luaD_callHook(L, base, NULL, 0); | 142 | luaD_callHook(L, base, NULL, 0); |
147 | (*f)(L); /* do the actual call */ | 143 | (*f)(L); /* do the actual call */ |
148 | if (L->callhook) /* test again: `func' may have changed callhook */ | 144 | if (L->callhook) /* test again: `func' may change callhook */ |
149 | luaD_callHook(L, base, NULL, 1); | 145 | luaD_callHook(L, base, NULL, 1); |
150 | firstResult = L->Cstack.base; | 146 | firstResult = L->Cstack.base; |
151 | L->Cstack = oldCLS; | 147 | L->Cstack = oldCLS; |
@@ -201,7 +197,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
201 | luaV_execute(L, c, tfvalue(proto), func+1); | 197 | luaV_execute(L, c, tfvalue(proto), func+1); |
202 | break; | 198 | break; |
203 | } | 199 | } |
204 | default: { /* func is not a function */ | 200 | default: { /* `func' is not a function */ |
205 | /* Check the tag method for invalid functions */ | 201 | /* Check the tag method for invalid functions */ |
206 | const TObject *im = luaT_getimbyObj(L, func, IM_FUNCTION); | 202 | const TObject *im = luaT_getimbyObj(L, func, IM_FUNCTION); |
207 | if (ttype(im) == LUA_T_NIL) | 203 | if (ttype(im) == LUA_T_NIL) |
@@ -251,13 +247,12 @@ void lua_error (lua_State *L, const char *s) { | |||
251 | ** parameters are on top of it. Leave nResults on the stack. | 247 | ** parameters are on top of it. Leave nResults on the stack. |
252 | */ | 248 | */ |
253 | int luaD_protectedrun (lua_State *L) { | 249 | int luaD_protectedrun (lua_State *L) { |
254 | volatile struct C_Lua_Stack oldCLS = L->Cstack; | ||
255 | struct lua_longjmp myErrorJmp; | 250 | struct lua_longjmp myErrorJmp; |
251 | volatile StkId base = L->Cstack.base; | ||
256 | volatile int status; | 252 | volatile int status; |
257 | struct lua_longjmp *volatile oldErr = L->errorJmp; | 253 | struct lua_longjmp *volatile oldErr = L->errorJmp; |
258 | L->errorJmp = &myErrorJmp; | 254 | L->errorJmp = &myErrorJmp; |
259 | if (setjmp(myErrorJmp.b) == 0) { | 255 | if (setjmp(myErrorJmp.b) == 0) { |
260 | StkId base = L->Cstack.base; | ||
261 | luaD_call(L, base, MULT_RET); | 256 | luaD_call(L, base, MULT_RET); |
262 | L->Cstack.lua2C = base; /* position of the new results */ | 257 | L->Cstack.lua2C = base; /* position of the new results */ |
263 | L->Cstack.num = L->top - base; | 258 | L->Cstack.num = L->top - base; |
@@ -265,8 +260,8 @@ int luaD_protectedrun (lua_State *L) { | |||
265 | status = 0; | 260 | status = 0; |
266 | } | 261 | } |
267 | else { /* an error occurred: restore the stack */ | 262 | else { /* an error occurred: restore the stack */ |
268 | L->Cstack = oldCLS; | 263 | L->Cstack.num = 0; /* no results */ |
269 | L->top = L->Cstack.base; | 264 | L->top = L->Cstack.base = L->Cstack.lua2C = base; |
270 | restore_stack_limit(L); | 265 | restore_stack_limit(L); |
271 | status = 1; | 266 | status = 1; |
272 | } | 267 | } |
@@ -279,29 +274,29 @@ int luaD_protectedrun (lua_State *L) { | |||
279 | ** returns 0 = chunk loaded; 1 = error; 2 = no more chunks to load | 274 | ** returns 0 = chunk loaded; 1 = error; 2 = no more chunks to load |
280 | */ | 275 | */ |
281 | static int protectedparser (lua_State *L, ZIO *z, int bin) { | 276 | static int protectedparser (lua_State *L, ZIO *z, int bin) { |
282 | volatile struct C_Lua_Stack oldCLS = L->Cstack; | ||
283 | struct lua_longjmp myErrorJmp; | 277 | struct lua_longjmp myErrorJmp; |
278 | volatile StkId base = L->Cstack.base; | ||
284 | volatile int status; | 279 | volatile int status; |
285 | TProtoFunc *volatile tf; | 280 | TProtoFunc *volatile tf; |
286 | struct lua_longjmp *volatile oldErr = L->errorJmp; | 281 | struct lua_longjmp *volatile oldErr = L->errorJmp; |
287 | L->errorJmp = &myErrorJmp; | 282 | L->errorJmp = &myErrorJmp; |
283 | L->top = base; /* erase C2Lua */ | ||
288 | if (setjmp(myErrorJmp.b) == 0) { | 284 | if (setjmp(myErrorJmp.b) == 0) { |
289 | tf = bin ? luaU_undump1(L, z) : luaY_parser(L, z); | 285 | tf = bin ? luaU_undump1(L, z) : luaY_parser(L, z); |
290 | status = 0; | 286 | status = 0; |
291 | } | 287 | } |
292 | else { /* an error occurred: restore L->Cstack and L->top */ | 288 | else { /* an error occurred: restore Cstack and top */ |
293 | L->Cstack = oldCLS; | 289 | L->Cstack.num = 0; /* no results */ |
294 | L->top = L->Cstack.base; | 290 | L->top = L->Cstack.base = L->Cstack.lua2C = base; |
295 | tf = NULL; | 291 | tf = NULL; |
296 | status = 1; | 292 | status = 1; |
297 | } | 293 | } |
298 | L->errorJmp = oldErr; | 294 | L->errorJmp = oldErr; |
299 | if (status) return 1; /* error code */ | 295 | if (status) return 1; /* error code */ |
300 | if (tf == NULL) return 2; /* `natural' end */ | 296 | if (tf == NULL) return 2; /* `natural' end */ |
301 | luaD_adjusttop(L, L->Cstack.base, 1); /* one slot for the pseudo-function */ | 297 | L->top->ttype = LUA_T_PROTO; /* push new function on the stack */ |
302 | L->Cstack.base->ttype = LUA_T_PROTO; | 298 | L->top->value.tf = tf; |
303 | L->Cstack.base->value.tf = tf; | 299 | incr_top; |
304 | luaV_closure(L, 0); | ||
305 | return 0; | 300 | return 0; |
306 | } | 301 | } |
307 | 302 | ||
@@ -313,7 +308,7 @@ static int do_main (lua_State *L, ZIO *z, int bin) { | |||
313 | long old_blocks = (luaC_checkGC(L), L->nblocks); | 308 | long old_blocks = (luaC_checkGC(L), L->nblocks); |
314 | status = protectedparser(L, z, bin); | 309 | status = protectedparser(L, z, bin); |
315 | if (status == 1) return 1; /* error */ | 310 | if (status == 1) return 1; /* error */ |
316 | else if (status == 2) return 0; /* 'natural' end */ | 311 | else if (status == 2) return 0; /* `natural' end */ |
317 | else { | 312 | else { |
318 | unsigned long newelems2 = 2*(L->nblocks-old_blocks); | 313 | unsigned long newelems2 = 2*(L->nblocks-old_blocks); |
319 | L->GCthreshold += newelems2; | 314 | L->GCthreshold += newelems2; |