diff options
| -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; |
