diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-12-01 17:50:08 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-12-01 17:50:08 -0200 |
| commit | fe237ad8085f34e89fcd3610a9771215af63f03f (patch) | |
| tree | f7ee5d8f7d1ffb74e94f049aa6f31eb03606cdf6 /ldo.c | |
| parent | 3181dfefee40b9a424b80aa779c671f5f458904c (diff) | |
| download | lua-fe237ad8085f34e89fcd3610a9771215af63f03f.tar.gz lua-fe237ad8085f34e89fcd3610a9771215af63f03f.tar.bz2 lua-fe237ad8085f34e89fcd3610a9771215af63f03f.zip | |
fixed stack; first version.
Diffstat (limited to 'ldo.c')
| -rw-r--r-- | ldo.c | 171 |
1 files changed, 88 insertions, 83 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 1.52 1999/11/22 13:12:07 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.53 1999/11/25 18:58: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 | */ |
| @@ -28,39 +28,40 @@ | |||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | #ifndef STACK_LIMIT | 31 | #ifndef DEFAULT_STACK_SIZE |
| 32 | #define STACK_LIMIT 6000 /* arbitrary limit */ | 32 | #define DEFAULT_STACK_SIZE 1024 |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | #define EXTRA_STACK 32 /* space to handle stack overflow errors */ | ||
| 35 | 36 | ||
| 36 | 37 | /* | |
| 37 | #define STACK_UNIT 128 | 38 | ** typical numer of recursive calls that fit in the stack |
| 38 | 39 | ** (only for error messages) | |
| 39 | 40 | */ | |
| 40 | #ifdef DEBUG | 41 | #define REC_DEEP (DEFAULT_STACK_SIZE/20) |
| 41 | #undef STACK_UNIT | ||
| 42 | #define STACK_UNIT 2 | ||
| 43 | #endif | ||
| 44 | 42 | ||
| 45 | 43 | ||
| 46 | void luaD_init (lua_State *L) { | 44 | void luaD_init (lua_State *L) { |
| 47 | L->stack.stack = luaM_newvector(L, STACK_UNIT, TObject); | 45 | L->stack = luaM_newvector(L, DEFAULT_STACK_SIZE+EXTRA_STACK, TObject); |
| 48 | L->stack.top = L->stack.stack; | 46 | L->stack_last = L->stack+(DEFAULT_STACK_SIZE-1); |
| 49 | L->stack.last = L->stack.stack+(STACK_UNIT-1); | 47 | L->Cstack.base = L->Cstack.lua2C = L->top = L->stack; |
| 48 | L->Cstack.num = 0; | ||
| 50 | } | 49 | } |
| 51 | 50 | ||
| 52 | 51 | ||
| 53 | void luaD_checkstack (lua_State *L, int n) { | 52 | void luaD_checkstack (lua_State *L, int n) { |
| 54 | struct Stack *S = &L->stack; | 53 | if (L->stack_last-L->top <= n) { /* stack overflow? */ |
| 55 | if (S->last-S->top <= n) { | 54 | if (L->stack_last-L->stack > (DEFAULT_STACK_SIZE-1)) { |
| 56 | StkId top = S->top-S->stack; | 55 | /* overflow while handling overflow: do what?? */ |
| 57 | int stacksize = (S->last-S->stack)+STACK_UNIT+n; | 56 | L->top -= EXTRA_STACK; |
| 58 | luaM_reallocvector(L, S->stack, stacksize, TObject); | 57 | lua_error(L, "BAD STACK OVERFLOW! DATA CORRUPTED!!"); |
| 59 | S->last = S->stack+(stacksize-1); | 58 | } |
| 60 | S->top = S->stack + top; | 59 | else { |
| 61 | if (stacksize >= STACK_LIMIT) { /* stack overflow? */ | 60 | L->stack_last += EXTRA_STACK; /* to be used by error message */ |
| 62 | if (lua_stackedfunction(L, 100) == LUA_NOOBJECT) /* 100 funcs on stack? */ | 61 | if (lua_stackedfunction(L, REC_DEEP) == LUA_NOOBJECT) { |
| 63 | lua_error(L, "Lua2C - C2Lua overflow"); /* doesn't look like a rec. loop */ | 62 | /* less than REC_DEEP funcs on stack: doesn't look like a rec. loop */ |
| 63 | lua_error(L, "Lua2C - C2Lua overflow"); | ||
| 64 | } | ||
| 64 | else | 65 | else |
| 65 | lua_error(L, "stack size overflow"); | 66 | lua_error(L, "stack size overflow"); |
| 66 | } | 67 | } |
| @@ -68,54 +69,62 @@ void luaD_checkstack (lua_State *L, int n) { | |||
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | 71 | ||
| 72 | static void restore_stack_limit (lua_State *L) { | ||
| 73 | if (L->top-L->stack < DEFAULT_STACK_SIZE-1) | ||
| 74 | L->stack_last = L->stack+(DEFAULT_STACK_SIZE-1); | ||
| 75 | } | ||
| 76 | |||
| 77 | |||
| 71 | /* | 78 | /* |
| 72 | ** Adjust stack. Set top to the given value, pushing NILs if needed. | 79 | ** Adjust stack. Set top to base+extra, pushing NILs if needed. |
| 80 | ** (we cannot add base+extra unless we are sure it fits in the stack; | ||
| 81 | ** otherwise the result of such operation on pointers is undefined) | ||
| 73 | */ | 82 | */ |
| 74 | void luaD_adjusttop (lua_State *L, StkId newtop) { | 83 | void luaD_adjusttop (lua_State *L, StkId base, int extra) { |
| 75 | int diff = newtop-(L->stack.top-L->stack.stack); | 84 | int diff = extra-(L->top-base); |
| 76 | if (diff <= 0) | 85 | if (diff <= 0) |
| 77 | L->stack.top += diff; | 86 | L->top = base+extra; |
| 78 | else { | 87 | else { |
| 79 | luaD_checkstack(L, diff); | 88 | luaD_checkstack(L, diff); |
| 80 | while (diff--) | 89 | while (diff--) |
| 81 | ttype(L->stack.top++) = LUA_T_NIL; | 90 | ttype(L->top++) = LUA_T_NIL; |
| 82 | } | 91 | } |
| 83 | } | 92 | } |
| 84 | 93 | ||
| 85 | 94 | ||
| 86 | /* | 95 | /* |
| 87 | ** Open a hole below "nelems" from the L->stack.top. | 96 | ** Open a hole inside the stack at `pos' |
| 88 | */ | 97 | */ |
| 89 | void luaD_openstack (lua_State *L, int nelems) { | 98 | void luaD_openstack (lua_State *L, StkId pos) { |
| 90 | luaO_memup(L->stack.top-nelems+1, L->stack.top-nelems, | 99 | luaO_memup(pos+1, pos, (L->top-pos)*sizeof(TObject)); |
| 91 | nelems*sizeof(TObject)); | ||
| 92 | incr_top; | 100 | incr_top; |
| 93 | } | 101 | } |
| 94 | 102 | ||
| 95 | 103 | ||
| 96 | void luaD_lineHook (lua_State *L, int line) { | 104 | void luaD_lineHook (lua_State *L, int line) { |
| 97 | struct C_Lua_Stack oldCLS = L->Cstack; | 105 | struct C_Lua_Stack oldCLS = L->Cstack; |
| 98 | StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack; | 106 | StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->top; |
| 99 | L->Cstack.num = 0; | 107 | L->Cstack.num = 0; |
| 100 | (*L->linehook)(L, line); | 108 | (*L->linehook)(L, line); |
| 101 | L->stack.top = L->stack.stack+old_top; | 109 | L->top = old_top; |
| 102 | L->Cstack = oldCLS; | 110 | L->Cstack = oldCLS; |
| 103 | } | 111 | } |
| 104 | 112 | ||
| 105 | 113 | ||
| 106 | void luaD_callHook (lua_State *L, StkId base, const TProtoFunc *tf, int isreturn) { | 114 | void luaD_callHook (lua_State *L, StkId base, const TProtoFunc *tf, |
| 115 | int isreturn) { | ||
| 107 | struct C_Lua_Stack oldCLS = L->Cstack; | 116 | struct C_Lua_Stack oldCLS = L->Cstack; |
| 108 | StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->stack.top-L->stack.stack; | 117 | StkId old_top = L->Cstack.lua2C = L->Cstack.base = L->top; |
| 109 | L->Cstack.num = 0; | 118 | L->Cstack.num = 0; |
| 110 | if (isreturn) | 119 | if (isreturn) |
| 111 | (*L->callhook)(L, LUA_NOOBJECT, "(return)", 0); | 120 | (*L->callhook)(L, LUA_NOOBJECT, "(return)", 0); |
| 112 | else { | 121 | else { |
| 113 | TObject *f = L->stack.stack+base-1; | 122 | TObject *f = base-1; |
| 114 | if (tf) | 123 | if (tf) |
| 115 | (*L->callhook)(L, Ref(L, f), tf->source->str, tf->lineDefined); | 124 | (*L->callhook)(L, Ref(L, f), tf->source->str, tf->lineDefined); |
| 116 | else (*L->callhook)(L, Ref(L, f), "(C)", -1); | 125 | else (*L->callhook)(L, Ref(L, f), "(C)", -1); |
| 117 | } | 126 | } |
| 118 | L->stack.top = L->stack.stack+old_top; | 127 | L->top = old_top; |
| 119 | L->Cstack = oldCLS; | 128 | L->Cstack = oldCLS; |
| 120 | } | 129 | } |
| 121 | 130 | ||
| @@ -126,43 +135,41 @@ void luaD_callHook (lua_State *L, StkId base, const TProtoFunc *tf, int isreturn | |||
| 126 | ** first argument. Returns an index to the first result from C. | 135 | ** first argument. Returns an index to the first result from C. |
| 127 | */ | 136 | */ |
| 128 | static StkId callC (lua_State *L, lua_CFunction f, StkId base) { | 137 | static StkId callC (lua_State *L, lua_CFunction f, StkId base) { |
| 129 | struct C_Lua_Stack *cls = &L->Cstack; | 138 | struct C_Lua_Stack oldCLS = L->Cstack; |
| 130 | struct C_Lua_Stack oldCLS = *cls; | ||
| 131 | StkId firstResult; | 139 | StkId firstResult; |
| 132 | int numarg = (L->stack.top-L->stack.stack) - base; | 140 | int numarg = L->top - base; |
| 133 | cls->num = numarg; | 141 | L->Cstack.num = numarg; |
| 134 | cls->lua2C = base; | 142 | L->Cstack.lua2C = base; |
| 135 | cls->base = base+numarg; /* == top-stack */ | 143 | L->Cstack.base = L->top; |
| 136 | if (L->callhook) | 144 | if (L->callhook) |
| 137 | luaD_callHook(L, base, NULL, 0); | 145 | luaD_callHook(L, base, NULL, 0); |
| 138 | (*f)(L); /* do the actual call */ | 146 | (*f)(L); /* do the actual call */ |
| 139 | if (L->callhook) /* func may have changed callhook */ | 147 | if (L->callhook) /* test again: `func' may have changed callhook */ |
| 140 | luaD_callHook(L, base, NULL, 1); | 148 | luaD_callHook(L, base, NULL, 1); |
| 141 | firstResult = cls->base; | 149 | firstResult = L->Cstack.base; |
| 142 | *cls = oldCLS; | 150 | L->Cstack = oldCLS; |
| 143 | return firstResult; | 151 | return firstResult; |
| 144 | } | 152 | } |
| 145 | 153 | ||
| 146 | 154 | ||
| 147 | static StkId callCclosure (lua_State *L, const struct Closure *cl, | 155 | static StkId callCclosure (lua_State *L, const struct Closure *cl, |
| 148 | lua_CFunction f, StkId base) { | 156 | lua_CFunction f, StkId base) { |
| 149 | TObject *pbase; | ||
| 150 | int nup = cl->nelems; /* number of upvalues */ | 157 | int nup = cl->nelems; /* number of upvalues */ |
| 151 | luaD_checkstack(L, nup); | 158 | luaD_checkstack(L, nup); |
| 152 | pbase = L->stack.stack+base; /* care: previous call may change this */ | ||
| 153 | /* open space for upvalues as extra arguments */ | 159 | /* open space for upvalues as extra arguments */ |
| 154 | luaO_memup(pbase+nup, pbase, (L->stack.top-pbase)*sizeof(TObject)); | 160 | luaO_memup(base+nup, base, (L->top-base)*sizeof(TObject)); |
| 155 | /* copy upvalues into stack */ | 161 | /* copy upvalues into stack */ |
| 156 | memcpy(pbase, cl->consts+1, nup*sizeof(TObject)); | 162 | memcpy(base, cl->consts+1, nup*sizeof(TObject)); |
| 157 | L->stack.top += nup; | 163 | L->top += nup; |
| 158 | return callC(L, f, base); | 164 | return callC(L, f, base); |
| 159 | } | 165 | } |
| 160 | 166 | ||
| 161 | 167 | ||
| 162 | void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults) { | 168 | void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults) { |
| 163 | luaD_openstack(L, nParams); | 169 | StkId base = L->top - nParams; |
| 164 | *(L->stack.top-nParams-1) = *f; | 170 | luaD_openstack(L, base); |
| 165 | luaD_call(L, L->stack.top-nParams-1, nResults); | 171 | *base = *f; |
| 172 | luaD_call(L, base, nResults); | ||
| 166 | } | 173 | } |
| 167 | 174 | ||
| 168 | 175 | ||
| @@ -173,26 +180,24 @@ void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults) { | |||
| 173 | ** function position. | 180 | ** function position. |
| 174 | ** The number of results is nResults, unless nResults=MULT_RET. | 181 | ** The number of results is nResults, unless nResults=MULT_RET. |
| 175 | */ | 182 | */ |
| 176 | void luaD_call (lua_State *L, TObject *func, int nResults) { | 183 | void luaD_call (lua_State *L, StkId func, int nResults) { |
| 177 | struct Stack *S = &L->stack; /* to optimize */ | ||
| 178 | StkId base = func - S->stack + 1; /* where is first argument */ | ||
| 179 | StkId firstResult; | 184 | StkId firstResult; |
| 180 | switch (ttype(func)) { | 185 | switch (ttype(func)) { |
| 181 | case LUA_T_CPROTO: | 186 | case LUA_T_CPROTO: |
| 182 | ttype(func) = LUA_T_CMARK; | 187 | ttype(func) = LUA_T_CMARK; |
| 183 | firstResult = callC(L, fvalue(func), base); | 188 | firstResult = callC(L, fvalue(func), func+1); |
| 184 | break; | 189 | break; |
| 185 | case LUA_T_PROTO: | 190 | case LUA_T_PROTO: |
| 186 | ttype(func) = LUA_T_PMARK; | 191 | ttype(func) = LUA_T_PMARK; |
| 187 | firstResult = luaV_execute(L, NULL, tfvalue(func), base); | 192 | firstResult = luaV_execute(L, NULL, tfvalue(func), func+1); |
| 188 | break; | 193 | break; |
| 189 | case LUA_T_CLOSURE: { | 194 | case LUA_T_CLOSURE: { |
| 190 | Closure *c = clvalue(func); | 195 | Closure *c = clvalue(func); |
| 191 | TObject *proto = c->consts; | 196 | TObject *proto = c->consts; |
| 192 | ttype(func) = LUA_T_CLMARK; | 197 | ttype(func) = LUA_T_CLMARK; |
| 193 | firstResult = (ttype(proto) == LUA_T_CPROTO) ? | 198 | firstResult = (ttype(proto) == LUA_T_CPROTO) ? |
| 194 | callCclosure(L, c, fvalue(proto), base) : | 199 | callCclosure(L, c, fvalue(proto), func+1) : |
| 195 | luaV_execute(L, c, tfvalue(proto), base); | 200 | luaV_execute(L, c, tfvalue(proto), func+1); |
| 196 | break; | 201 | break; |
| 197 | } | 202 | } |
| 198 | default: { /* func is not a function */ | 203 | default: { /* func is not a function */ |
| @@ -200,19 +205,18 @@ void luaD_call (lua_State *L, TObject *func, int nResults) { | |||
| 200 | const TObject *im = luaT_getimbyObj(L, func, IM_FUNCTION); | 205 | const TObject *im = luaT_getimbyObj(L, func, IM_FUNCTION); |
| 201 | if (ttype(im) == LUA_T_NIL) | 206 | if (ttype(im) == LUA_T_NIL) |
| 202 | lua_error(L, "call expression not a function"); | 207 | lua_error(L, "call expression not a function"); |
| 203 | luaD_callTM(L, im, (S->top-S->stack)-(base-1), nResults); | 208 | luaD_callTM(L, im, L->top-func, nResults); |
| 204 | return; | 209 | return; |
| 205 | } | 210 | } |
| 206 | } | 211 | } |
| 207 | /* adjust the number of results */ | 212 | /* adjust the number of results */ |
| 208 | if (nResults == MULT_RET) | 213 | if (nResults == MULT_RET) |
| 209 | nResults = (S->top-S->stack)-firstResult; | 214 | nResults = L->top - firstResult; |
| 210 | else | 215 | else |
| 211 | luaD_adjusttop(L, firstResult+nResults); | 216 | luaD_adjusttop(L, firstResult, nResults); |
| 212 | /* move results to base-1 (to erase parameters and function) */ | 217 | /* move results to func (to erase parameters and function) */ |
| 213 | base--; | 218 | luaO_memdown(func, firstResult, nResults*sizeof(TObject)); |
| 214 | luaO_memdown(S->stack+base, S->stack+firstResult, nResults*sizeof(TObject)); | 219 | L->top = func+nResults; |
| 215 | S->top -= firstResult-base; | ||
| 216 | } | 220 | } |
| 217 | 221 | ||
| 218 | 222 | ||
| @@ -220,10 +224,10 @@ static void message (lua_State *L, const char *s) { | |||
| 220 | const TObject *em = &(luaS_assertglobalbyname(L, "_ERRORMESSAGE")->value); | 224 | const TObject *em = &(luaS_assertglobalbyname(L, "_ERRORMESSAGE")->value); |
| 221 | if (ttype(em) == LUA_T_PROTO || ttype(em) == LUA_T_CPROTO || | 225 | if (ttype(em) == LUA_T_PROTO || ttype(em) == LUA_T_CPROTO || |
| 222 | ttype(em) == LUA_T_CLOSURE) { | 226 | ttype(em) == LUA_T_CLOSURE) { |
| 223 | *L->stack.top = *em; | 227 | *L->top = *em; |
| 224 | incr_top; | 228 | incr_top; |
| 225 | lua_pushstring(L, s); | 229 | lua_pushstring(L, s); |
| 226 | luaD_call(L, L->stack.top-2, 0); | 230 | luaD_call(L, L->top-2, 0); |
| 227 | } | 231 | } |
| 228 | } | 232 | } |
| 229 | 233 | ||
| @@ -253,15 +257,16 @@ int luaD_protectedrun (lua_State *L) { | |||
| 253 | L->errorJmp = &myErrorJmp; | 257 | L->errorJmp = &myErrorJmp; |
| 254 | if (setjmp(myErrorJmp.b) == 0) { | 258 | if (setjmp(myErrorJmp.b) == 0) { |
| 255 | StkId base = L->Cstack.base; | 259 | StkId base = L->Cstack.base; |
| 256 | luaD_call(L, L->stack.stack+base, MULT_RET); | 260 | luaD_call(L, base, MULT_RET); |
| 257 | L->Cstack.lua2C = base; /* position of the new results */ | 261 | L->Cstack.lua2C = base; /* position of the new results */ |
| 258 | L->Cstack.num = (L->stack.top-L->stack.stack) - base; | 262 | L->Cstack.num = L->top - base; |
| 259 | L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */ | 263 | L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */ |
| 260 | status = 0; | 264 | status = 0; |
| 261 | } | 265 | } |
| 262 | else { /* an error occurred: restore L->Cstack and L->stack.top */ | 266 | else { /* an error occurred: restore the stack */ |
| 263 | L->Cstack = oldCLS; | 267 | L->Cstack = oldCLS; |
| 264 | L->stack.top = L->stack.stack+L->Cstack.base; | 268 | L->top = L->Cstack.base; |
| 269 | restore_stack_limit(L); | ||
| 265 | status = 1; | 270 | status = 1; |
| 266 | } | 271 | } |
| 267 | L->errorJmp = oldErr; | 272 | L->errorJmp = oldErr; |
| @@ -283,18 +288,18 @@ static int protectedparser (lua_State *L, ZIO *z, int bin) { | |||
| 283 | tf = bin ? luaU_undump1(L, z) : luaY_parser(L, z); | 288 | tf = bin ? luaU_undump1(L, z) : luaY_parser(L, z); |
| 284 | status = 0; | 289 | status = 0; |
| 285 | } | 290 | } |
| 286 | else { /* an error occurred: restore L->Cstack and L->stack.top */ | 291 | else { /* an error occurred: restore L->Cstack and L->top */ |
| 287 | L->Cstack = oldCLS; | 292 | L->Cstack = oldCLS; |
| 288 | L->stack.top = L->stack.stack+L->Cstack.base; | 293 | L->top = L->Cstack.base; |
| 289 | tf = NULL; | 294 | tf = NULL; |
| 290 | status = 1; | 295 | status = 1; |
| 291 | } | 296 | } |
| 292 | L->errorJmp = oldErr; | 297 | L->errorJmp = oldErr; |
| 293 | if (status) return 1; /* error code */ | 298 | if (status) return 1; /* error code */ |
| 294 | if (tf == NULL) return 2; /* 'natural' end */ | 299 | if (tf == NULL) return 2; /* `natural' end */ |
| 295 | luaD_adjusttop(L, L->Cstack.base+1); /* one slot for the pseudo-function */ | 300 | luaD_adjusttop(L, L->Cstack.base, 1); /* one slot for the pseudo-function */ |
| 296 | L->stack.stack[L->Cstack.base].ttype = LUA_T_PROTO; | 301 | L->Cstack.base->ttype = LUA_T_PROTO; |
| 297 | L->stack.stack[L->Cstack.base].value.tf = tf; | 302 | L->Cstack.base->value.tf = tf; |
| 298 | luaV_closure(L, 0); | 303 | luaV_closure(L, 0); |
| 299 | return 0; | 304 | return 0; |
| 300 | } | 305 | } |
| @@ -323,7 +328,7 @@ static int do_main (lua_State *L, ZIO *z, int bin) { | |||
| 323 | void luaD_gcIM (lua_State *L, const TObject *o) { | 328 | void luaD_gcIM (lua_State *L, const TObject *o) { |
| 324 | const TObject *im = luaT_getimbyObj(L, o, IM_GC); | 329 | const TObject *im = luaT_getimbyObj(L, o, IM_GC); |
| 325 | if (ttype(im) != LUA_T_NIL) { | 330 | if (ttype(im) != LUA_T_NIL) { |
| 326 | *L->stack.top = *o; | 331 | *L->top = *o; |
| 327 | incr_top; | 332 | incr_top; |
| 328 | luaD_callTM(L, im, 1, 0); | 333 | luaD_callTM(L, im, 1, 0); |
| 329 | } | 334 | } |
