diff options
| -rw-r--r-- | ldebug.c | 35 | ||||
| -rw-r--r-- | ldo.c | 215 | ||||
| -rw-r--r-- | ldo.h | 12 | ||||
| -rw-r--r-- | lgc.c | 24 | ||||
| -rw-r--r-- | llimits.h | 5 | ||||
| -rw-r--r-- | lstate.c | 24 | ||||
| -rw-r--r-- | lstate.h | 15 | ||||
| -rw-r--r-- | ltests.c | 12 | ||||
| -rw-r--r-- | lvm.c | 83 |
9 files changed, 250 insertions, 175 deletions
| @@ -25,8 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | static const char *getfuncname (lua_State *L, CallInfo *ci, | 28 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); |
| 29 | const char **name); | ||
| 30 | 29 | ||
| 31 | 30 | ||
| 32 | 31 | ||
| @@ -57,7 +56,7 @@ LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func) { | |||
| 57 | 56 | ||
| 58 | static CallInfo *ci_stack (lua_State *L, StkId obj) { | 57 | static CallInfo *ci_stack (lua_State *L, StkId obj) { |
| 59 | CallInfo *ci = L->ci; | 58 | CallInfo *ci = L->ci; |
| 60 | while (ci->base > obj) ci--; | 59 | while (ci->base > obj && ci > L->base_ci) ci--; |
| 61 | return ci; | 60 | return ci; |
| 62 | } | 61 | } |
| 63 | 62 | ||
| @@ -105,22 +104,22 @@ int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) { | |||
| 105 | } | 104 | } |
| 106 | 105 | ||
| 107 | 106 | ||
| 108 | static int currentpc (CallInfo *ci) { | 107 | static int currentpc (lua_State *L, CallInfo *ci) { |
| 109 | lua_assert(isLmark(ci)); | 108 | lua_assert(isLmark(ci)); |
| 110 | if (ci->savedpc) | 109 | if (ci->pc == NULL) return 0; /* function is not active */ |
| 111 | return (ci->savedpc - ci_func(ci)->l.p->code) - 1; | 110 | if (ci == L->ci || ci->pc != (ci+1)->pc) /* no other function using `pc'? */ |
| 112 | else if (ci->pc) | ||
| 113 | return (*ci->pc - ci_func(ci)->l.p->code) - 1; | 111 | return (*ci->pc - ci_func(ci)->l.p->code) - 1; |
| 114 | else return 0; | 112 | else /* function's pc is saved */ |
| 113 | return (ci->savedpc - ci_func(ci)->l.p->code) - 1; | ||
| 115 | } | 114 | } |
| 116 | 115 | ||
| 117 | 116 | ||
| 118 | static int currentline (CallInfo *ci) { | 117 | static int currentline (lua_State *L, CallInfo *ci) { |
| 119 | if (!isLmark(ci)) | 118 | if (!isLmark(ci)) |
| 120 | return -1; /* only active lua functions have current-line information */ | 119 | return -1; /* only active lua functions have current-line information */ |
| 121 | else { | 120 | else { |
| 122 | int *lineinfo = ci_func(ci)->l.p->lineinfo; | 121 | int *lineinfo = ci_func(ci)->l.p->lineinfo; |
| 123 | return luaG_getline(lineinfo, currentpc(ci), 1, NULL); | 122 | return luaG_getline(lineinfo, currentpc(L, ci), 1, NULL); |
| 124 | } | 123 | } |
| 125 | } | 124 | } |
| 126 | 125 | ||
| @@ -140,7 +139,7 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { | |||
| 140 | ci = L->base_ci + ar->_ci; | 139 | ci = L->base_ci + ar->_ci; |
| 141 | fp = getluaproto(ci); | 140 | fp = getluaproto(ci); |
| 142 | if (fp) { /* is a Lua function? */ | 141 | if (fp) { /* is a Lua function? */ |
| 143 | name = luaF_getlocalname(fp, n, currentpc(ci)); | 142 | name = luaF_getlocalname(fp, n, currentpc(L, ci)); |
| 144 | if (name) | 143 | if (name) |
| 145 | luaA_pushobject(L, ci->base+(n-1)); /* push value */ | 144 | luaA_pushobject(L, ci->base+(n-1)); /* push value */ |
| 146 | } | 145 | } |
| @@ -159,7 +158,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { | |||
| 159 | fp = getluaproto(ci); | 158 | fp = getluaproto(ci); |
| 160 | L->top--; /* pop new value */ | 159 | L->top--; /* pop new value */ |
| 161 | if (fp) { /* is a Lua function? */ | 160 | if (fp) { /* is a Lua function? */ |
| 162 | name = luaF_getlocalname(fp, n, currentpc(ci)); | 161 | name = luaF_getlocalname(fp, n, currentpc(L, ci)); |
| 163 | if (!name || name[0] == '(') /* `(' starts private locals */ | 162 | if (!name || name[0] == '(') /* `(' starts private locals */ |
| 164 | name = NULL; | 163 | name = NULL; |
| 165 | else | 164 | else |
| @@ -239,7 +238,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |||
| 239 | break; | 238 | break; |
| 240 | } | 239 | } |
| 241 | case 'l': { | 240 | case 'l': { |
| 242 | ar->currentline = (ci) ? currentline(ci) : -1; | 241 | ar->currentline = (ci) ? currentline(L, ci) : -1; |
| 243 | break; | 242 | break; |
| 244 | } | 243 | } |
| 245 | case 'u': { | 244 | case 'u': { |
| @@ -254,13 +253,14 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |||
| 254 | } | 253 | } |
| 255 | case 'f': { | 254 | case 'f': { |
| 256 | setobj(L->top, f); | 255 | setobj(L->top, f); |
| 257 | incr_top; /* push function */ | 256 | status = 2; |
| 258 | break; | 257 | break; |
| 259 | } | 258 | } |
| 260 | default: status = 0; /* invalid option */ | 259 | default: status = 0; /* invalid option */ |
| 261 | } | 260 | } |
| 262 | } | 261 | } |
| 263 | if (!ci) L->top--; /* pop function */ | 262 | if (!ci) L->top--; /* pop function */ |
| 263 | if (status == 2) incr_top(L); | ||
| 264 | lua_unlock(L); | 264 | lua_unlock(L); |
| 265 | return status; | 265 | return status; |
| 266 | } | 266 | } |
| @@ -449,7 +449,7 @@ static const char *getobjname (lua_State *L, StkId obj, const char **name) { | |||
| 449 | CallInfo *ci = ci_stack(L, obj); | 449 | CallInfo *ci = ci_stack(L, obj); |
| 450 | if (isLmark(ci)) { /* an active Lua function? */ | 450 | if (isLmark(ci)) { /* an active Lua function? */ |
| 451 | Proto *p = ci_func(ci)->l.p; | 451 | Proto *p = ci_func(ci)->l.p; |
| 452 | int pc = currentpc(ci); | 452 | int pc = currentpc(L, ci); |
| 453 | int stackpos = obj - ci->base; | 453 | int stackpos = obj - ci->base; |
| 454 | Instruction i; | 454 | Instruction i; |
| 455 | *name = luaF_getlocalname(p, stackpos+1, pc); | 455 | *name = luaF_getlocalname(p, stackpos+1, pc); |
| @@ -486,14 +486,13 @@ static const char *getobjname (lua_State *L, StkId obj, const char **name) { | |||
| 486 | } | 486 | } |
| 487 | 487 | ||
| 488 | 488 | ||
| 489 | static const char *getfuncname (lua_State *L, CallInfo *ci, | 489 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { |
| 490 | const char **name) { | ||
| 491 | ci--; /* calling function */ | 490 | ci--; /* calling function */ |
| 492 | if (ci == L->base_ci || !isLmark(ci)) | 491 | if (ci == L->base_ci || !isLmark(ci)) |
| 493 | return NULL; /* not an active Lua function */ | 492 | return NULL; /* not an active Lua function */ |
| 494 | else { | 493 | else { |
| 495 | Proto *p = ci_func(ci)->l.p; | 494 | Proto *p = ci_func(ci)->l.p; |
| 496 | int pc = currentpc(ci); | 495 | int pc = currentpc(L, ci); |
| 497 | Instruction i; | 496 | Instruction i; |
| 498 | i = p->code[pc]; | 497 | i = p->code[pc]; |
| 499 | return (GET_OPCODE(i) == OP_CALL | 498 | return (GET_OPCODE(i) == OP_CALL |
| @@ -30,22 +30,72 @@ | |||
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | /* chain list of long jump buffers */ | ||
| 34 | struct lua_longjmp { | ||
| 35 | jmp_buf b; | ||
| 36 | struct lua_longjmp *previous; | ||
| 37 | CallInfo *ci; /* index of call info of active function that set protection */ | ||
| 38 | StkId top; /* top stack when protection was set */ | ||
| 39 | TObject *stack; /* active stack for this entry */ | ||
| 40 | int allowhooks; /* `allowhook' state when protection was set */ | ||
| 41 | volatile int status; /* error code */ | ||
| 42 | }; | ||
| 43 | |||
| 44 | |||
| 45 | static void correctstack (lua_State *L, TObject *oldstack) { | ||
| 46 | struct lua_longjmp *lj; | ||
| 47 | CallInfo *ci; | ||
| 48 | UpVal *up; | ||
| 49 | L->top = (L->top - oldstack) + L->stack; | ||
| 50 | for (lj = L->errorJmp; lj && lj->stack == oldstack; lj = lj->previous) { | ||
| 51 | lj->top = (lj->top - oldstack) + L->stack; | ||
| 52 | lj->stack = L->stack; | ||
| 53 | } | ||
| 54 | for (up = L->openupval; up != NULL; up = up->next) | ||
| 55 | up->v = (up->v - oldstack) + L->stack; | ||
| 56 | for (ci = L->base_ci; ci <= L->ci; ci++) { | ||
| 57 | ci->base = (ci->base - oldstack) + L->stack; | ||
| 58 | ci->top = (ci->top - oldstack) + L->stack; | ||
| 59 | if (ci->pc) { /* entry is of an active Lua function? */ | ||
| 60 | if (ci->pc != (ci-1)->pc) | ||
| 61 | *ci->pb = (*ci->pb - oldstack) + L->stack; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | |||
| 67 | void luaD_reallocstack (lua_State *L, int newsize) { | ||
| 68 | TObject *oldstack = L->stack; | ||
| 69 | luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject); | ||
| 70 | L->stacksize = newsize; | ||
| 71 | L->stack_last = L->stack+(newsize-EXTRA_STACK)-1; | ||
| 72 | correctstack(L, oldstack); | ||
| 73 | } | ||
| 74 | |||
| 75 | |||
| 33 | static void restore_stack_limit (lua_State *L) { | 76 | static void restore_stack_limit (lua_State *L) { |
| 34 | StkId limit = L->stack+(L->stacksize-EXTRA_STACK)-1; | 77 | if (L->stacksize > L->maxstacksize) { /* there was an overflow? */ |
| 35 | if (L->top < limit) | 78 | int inuse = (L->top - L->stack); |
| 36 | L->stack_last = limit; | 79 | if (inuse + MAXSTACK < L->maxstacksize) /* can `undo' overflow? */ |
| 80 | luaD_reallocstack(L, L->maxstacksize); | ||
| 81 | } | ||
| 37 | } | 82 | } |
| 38 | 83 | ||
| 39 | 84 | ||
| 40 | void luaD_stackerror (lua_State *L) { | 85 | void luaD_growstack (lua_State *L, int n) { |
| 41 | if (L->stack_last == L->stack+L->stacksize-1) { | 86 | if (L->stacksize > L->maxstacksize) { /* overflow while handling overflow? */ |
| 42 | /* overflow while handling overflow */ | ||
| 43 | luaD_breakrun(L, LUA_ERRERR); /* break run without error message */ | 87 | luaD_breakrun(L, LUA_ERRERR); /* break run without error message */ |
| 44 | } | 88 | } |
| 45 | else { | 89 | else { |
| 46 | L->stack_last += EXTRA_STACK; /* to be used by error message */ | 90 | if (n <= L->stacksize && 2*L->stacksize < L->maxstacksize) /* can double? */ |
| 47 | lua_assert(L->stack_last == L->stack+L->stacksize-1); | 91 | luaD_reallocstack(L, 2*L->stacksize); |
| 48 | luaD_error(L, "stack overflow"); | 92 | else if (L->stacksize+n <= L->maxstacksize) /* no overflow? */ |
| 93 | luaD_reallocstack(L, L->maxstacksize); | ||
| 94 | else { | ||
| 95 | /* resize to maximum + some extra space to handle error */ | ||
| 96 | luaD_reallocstack(L, L->maxstacksize+4*LUA_MINSTACK); | ||
| 97 | luaD_error(L, "stack overflow"); | ||
| 98 | } | ||
| 49 | } | 99 | } |
| 50 | } | 100 | } |
| 51 | 101 | ||
| @@ -56,12 +106,12 @@ void luaD_stackerror (lua_State *L) { | |||
| 56 | static void luaD_openstack (lua_State *L, StkId pos) { | 106 | static void luaD_openstack (lua_State *L, StkId pos) { |
| 57 | int i = L->top-pos; | 107 | int i = L->top-pos; |
| 58 | while (i--) setobj(pos+i+1, pos+i); | 108 | while (i--) setobj(pos+i+1, pos+i); |
| 59 | incr_top; | 109 | incr_top(L); |
| 60 | } | 110 | } |
| 61 | 111 | ||
| 62 | 112 | ||
| 63 | static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) { | 113 | static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) { |
| 64 | StkId old_top = L->top; | 114 | L->ci->top = L->top; |
| 65 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 115 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
| 66 | L->allowhooks = 0; /* cannot call hooks inside a hook */ | 116 | L->allowhooks = 0; /* cannot call hooks inside a hook */ |
| 67 | lua_unlock(L); | 117 | lua_unlock(L); |
| @@ -69,7 +119,7 @@ static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) { | |||
| 69 | lua_lock(L); | 119 | lua_lock(L); |
| 70 | lua_assert(L->allowhooks == 0); | 120 | lua_assert(L->allowhooks == 0); |
| 71 | L->allowhooks = 1; | 121 | L->allowhooks = 1; |
| 72 | L->top = old_top; | 122 | L->top = L->ci->top; |
| 73 | } | 123 | } |
| 74 | 124 | ||
| 75 | 125 | ||
| @@ -95,66 +145,82 @@ void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event) { | |||
| 95 | } | 145 | } |
| 96 | 146 | ||
| 97 | 147 | ||
| 98 | static CallInfo *growci (lua_State *L) { | 148 | static void correctCI (lua_State *L, CallInfo *oldci) { |
| 99 | lua_assert(L->ci == L->end_ci); | 149 | struct lua_longjmp *lj; |
| 100 | luaM_reallocvector(L, L->base_ci, L->size_ci, 2*L->size_ci, CallInfo); | 150 | for (lj = L->errorJmp; lj && lj->stack == L->stack; lj = lj->previous) { |
| 101 | L->ci = L->base_ci + L->size_ci; | 151 | lj->ci = (lj->ci - oldci) + L->base_ci; |
| 102 | L->size_ci *= 2; | 152 | } |
| 103 | L->end_ci = L->base_ci + L->size_ci; | ||
| 104 | return L->ci; | ||
| 105 | } | 153 | } |
| 106 | 154 | ||
| 107 | 155 | ||
| 108 | static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { | 156 | void luaD_reallocCI (lua_State *L, int newsize) { |
| 157 | CallInfo *oldci = L->base_ci; | ||
| 158 | luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); | ||
| 159 | L->size_ci = newsize; | ||
| 160 | if (oldci != L->ci) { | ||
| 161 | L->ci = (L->ci - oldci) + L->base_ci; | ||
| 162 | L->end_ci = L->base_ci + L->size_ci; | ||
| 163 | correctCI(L, oldci); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | |||
| 168 | static void adjust_varargs (lua_State *L, int nfixargs) { | ||
| 109 | int i; | 169 | int i; |
| 110 | Table *htab; | 170 | Table *htab; |
| 111 | TObject n, nname; | 171 | TObject n, nname; |
| 112 | StkId firstvar = base + nfixargs; /* position of first vararg */ | 172 | int actual = L->top - L->ci->base; /* actual number of arguments */ |
| 113 | if (L->top < firstvar) { | 173 | if (actual < nfixargs) { |
| 114 | luaD_checkstack(L, firstvar - L->top); | 174 | luaD_checkstack(L, nfixargs - actual); |
| 115 | while (L->top < firstvar) | 175 | for (; actual < nfixargs; ++actual) |
| 116 | setnilvalue(L->top++); | 176 | setnilvalue(L->top++); |
| 117 | } | 177 | } |
| 118 | htab = luaH_new(L, 0, 0); | 178 | actual -= nfixargs; /* number of extra arguments */ |
| 119 | for (i=0; firstvar+i<L->top; i++) | 179 | htab = luaH_new(L, 0, 0); /* create `arg' table */ |
| 120 | luaH_setnum(L, htab, i+1, firstvar+i); | 180 | for (i=0; i<actual; i++) /* put extra arguments into `arg' table */ |
| 181 | luaH_setnum(L, htab, i+1, L->top - actual + i); | ||
| 121 | /* store counter in field `n' */ | 182 | /* store counter in field `n' */ |
| 122 | setnvalue(&n, i); | 183 | setnvalue(&n, actual); |
| 123 | setsvalue(&nname, luaS_newliteral(L, "n")); | 184 | setsvalue(&nname, luaS_newliteral(L, "n")); |
| 124 | luaH_set(L, htab, &nname, &n); | 185 | luaH_set(L, htab, &nname, &n); |
| 125 | L->top = firstvar; /* remove elements from the stack */ | 186 | L->top -= actual; /* remove extra elements from the stack */ |
| 126 | sethvalue(L->top, htab); | 187 | sethvalue(L->top, htab); |
| 127 | incr_top; | 188 | incr_top(L); |
| 128 | } | 189 | } |
| 129 | 190 | ||
| 130 | 191 | ||
| 131 | StkId luaD_precall (lua_State *L, StkId func) { | 192 | StkId luaD_precall (lua_State *L, StkId func) { |
| 132 | CallInfo *ci; | 193 | CallInfo *ci; |
| 133 | LClosure *cl; | 194 | LClosure *cl; |
| 195 | if (++L->ci == L->end_ci) luaD_reallocCI(L, 2*L->size_ci); | ||
| 196 | ci = L->ci; | ||
| 197 | ci->base = func+1; | ||
| 198 | ci->pc = NULL; | ||
| 134 | if (ttype(func) != LUA_TFUNCTION) { | 199 | if (ttype(func) != LUA_TFUNCTION) { |
| 135 | /* `func' is not a function; check the `function' tag method */ | 200 | /* `func' is not a function; check the `function' tag method */ |
| 136 | const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); | 201 | const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); |
| 137 | if (ttype(tm) != LUA_TFUNCTION) | 202 | if (ttype(tm) != LUA_TFUNCTION) { |
| 203 | L->ci--; /* undo increment (no function here) */ | ||
| 138 | luaG_typeerror(L, func, "call"); | 204 | luaG_typeerror(L, func, "call"); |
| 205 | } | ||
| 139 | luaD_openstack(L, func); | 206 | luaD_openstack(L, func); |
| 207 | func = ci->base - 1; /* previous call may change stack */ | ||
| 140 | setobj(func, tm); /* tag method is the new function to be called */ | 208 | setobj(func, tm); /* tag method is the new function to be called */ |
| 141 | } | 209 | } |
| 142 | ci = ++L->ci; | ||
| 143 | if (L->ci == L->end_ci) ci = growci(L); | ||
| 144 | ci->base = func+1; | ||
| 145 | if (L->callhook) | ||
| 146 | luaD_callHook(L, L->callhook, "call"); | ||
| 147 | cl = &clvalue(func)->l; | 210 | cl = &clvalue(func)->l; |
| 211 | if (L->callhook) { | ||
| 212 | luaD_callHook(L, L->callhook, "call"); | ||
| 213 | ci = L->ci; /* previous call may realocate `ci' */ | ||
| 214 | } | ||
| 148 | if (!cl->isC) { /* Lua function? prepare its call */ | 215 | if (!cl->isC) { /* Lua function? prepare its call */ |
| 149 | StkId base = func+1; | ||
| 150 | Proto *p = cl->p; | 216 | Proto *p = cl->p; |
| 151 | ci->savedpc = p->code; /* starting point */ | 217 | ci->savedpc = p->code; /* starting point */ |
| 152 | if (p->is_vararg) /* varargs? */ | 218 | if (p->is_vararg) /* varargs? */ |
| 153 | adjust_varargs(L, base, p->numparams); | 219 | adjust_varargs(L, p->numparams); |
| 154 | if (base > L->stack_last - p->maxstacksize) | 220 | if (ci->base > L->stack_last - p->maxstacksize) |
| 155 | luaD_stackerror(L); | 221 | luaD_growstack(L, p->maxstacksize); |
| 156 | ci->line = 0; | 222 | ci->line = 0; |
| 157 | ci->top = base + p->maxstacksize; | 223 | ci->top = ci->base + p->maxstacksize; |
| 158 | while (L->top < ci->top) | 224 | while (L->top < ci->top) |
| 159 | setnilvalue(L->top++); | 225 | setnilvalue(L->top++); |
| 160 | L->top = ci->top; | 226 | L->top = ci->top; |
| @@ -162,13 +228,12 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
| 162 | } | 228 | } |
| 163 | else { /* if is a C function, call it */ | 229 | else { /* if is a C function, call it */ |
| 164 | int n; | 230 | int n; |
| 165 | ci->savedpc = NULL; | ||
| 166 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 231 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
| 167 | lua_unlock(L); | 232 | lua_unlock(L); |
| 168 | #if LUA_COMPATUPVALUES | 233 | #if LUA_COMPATUPVALUES |
| 169 | lua_pushupvalues(L); | 234 | lua_pushupvalues(L); |
| 170 | #endif | 235 | #endif |
| 171 | n = (*clvalue(func)->c.f)(L); /* do the actual call */ | 236 | n = (*clvalue(ci->base-1)->c.f)(L); /* do the actual call */ |
| 172 | lua_lock(L); | 237 | lua_lock(L); |
| 173 | return L->top - n; | 238 | return L->top - n; |
| 174 | } | 239 | } |
| @@ -177,9 +242,12 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
| 177 | 242 | ||
| 178 | void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { | 243 | void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { |
| 179 | StkId res; | 244 | StkId res; |
| 180 | if (L->callhook) | 245 | if (L->callhook) { |
| 246 | StkId stack = L->stack; /* next call may change stack */ | ||
| 181 | luaD_callHook(L, L->callhook, "return"); | 247 | luaD_callHook(L, L->callhook, "return"); |
| 182 | res = L->ci->base - 1; /* `func' = final position of 1st result */ | 248 | firstResult = (firstResult - stack) + L->stack; |
| 249 | } | ||
| 250 | res = L->ci->base - 1; /* func == final position of 1st result */ | ||
| 183 | L->ci--; | 251 | L->ci--; |
| 184 | /* move results to correct place */ | 252 | /* move results to correct place */ |
| 185 | while (wanted != 0 && firstResult < L->top) { | 253 | while (wanted != 0 && firstResult < L->top) { |
| @@ -223,7 +291,7 @@ static void resume_results (lua_State *L, lua_State *from, int numresults) { | |||
| 223 | while (numresults) { | 291 | while (numresults) { |
| 224 | setobj(L->top, from->top - numresults); | 292 | setobj(L->top, from->top - numresults); |
| 225 | numresults--; | 293 | numresults--; |
| 226 | incr_top; | 294 | incr_top(L); |
| 227 | } | 295 | } |
| 228 | } | 296 | } |
| 229 | 297 | ||
| @@ -231,7 +299,7 @@ static void resume_results (lua_State *L, lua_State *from, int numresults) { | |||
| 231 | LUA_API void lua_resume (lua_State *L, lua_State *co) { | 299 | LUA_API void lua_resume (lua_State *L, lua_State *co) { |
| 232 | StkId firstResult; | 300 | StkId firstResult; |
| 233 | lua_lock(L); | 301 | lua_lock(L); |
| 234 | if (co->ci->savedpc == NULL) /* no activation record? */ | 302 | if (co->ci == co->base_ci) /* no activation record? ?? */ |
| 235 | luaD_error(L, "thread is dead - cannot be resumed"); | 303 | luaD_error(L, "thread is dead - cannot be resumed"); |
| 236 | lua_assert(co->errorJmp == NULL); | 304 | lua_assert(co->errorJmp == NULL); |
| 237 | co->errorJmp = L->errorJmp; | 305 | co->errorJmp = L->errorJmp; |
| @@ -253,15 +321,13 @@ LUA_API void lua_resume (lua_State *L, lua_State *co) { | |||
| 253 | 321 | ||
| 254 | LUA_API int lua_yield (lua_State *L, int nresults) { | 322 | LUA_API int lua_yield (lua_State *L, int nresults) { |
| 255 | CallInfo *ci; | 323 | CallInfo *ci; |
| 256 | int ibase; | ||
| 257 | lua_lock(L); | 324 | lua_lock(L); |
| 258 | ci = L->ci; | 325 | ci = L->ci; |
| 259 | if (ci_func(ci-1)->c.isC) | 326 | if (ci_func(ci-1)->c.isC) |
| 260 | luaD_error(L, "cannot `yield' a C function"); | 327 | luaD_error(L, "cannot `yield' a C function"); |
| 261 | ci->yield_results = nresults; /* very dirty trick! */ | 328 | ci->yield_results = nresults; |
| 262 | ibase = L->top - (ci-1)->base; | ||
| 263 | lua_unlock(L); | 329 | lua_unlock(L); |
| 264 | return ibase; | 330 | return -1; |
| 265 | } | 331 | } |
| 266 | 332 | ||
| 267 | 333 | ||
| @@ -280,16 +346,15 @@ static void f_call (lua_State *L, void *ud) { | |||
| 280 | 346 | ||
| 281 | 347 | ||
| 282 | LUA_API int lua_call (lua_State *L, int nargs, int nresults) { | 348 | LUA_API int lua_call (lua_State *L, int nargs, int nresults) { |
| 283 | StkId func; | ||
| 284 | struct CallS c; | 349 | struct CallS c; |
| 285 | int status; | 350 | int status; |
| 286 | lua_lock(L); | 351 | lua_lock(L); |
| 287 | func = L->top - (nargs+1); /* function to be called */ | 352 | c.func = L->top - (nargs+1); /* function to be called */ |
| 288 | c.func = func; c.nresults = nresults; | 353 | c.nresults = nresults; |
| 289 | status = luaD_runprotected(L, f_call, &c); | 354 | status = luaD_runprotected(L, f_call, &c); |
| 290 | if (status != 0) { /* an error occurred? */ | 355 | if (status != 0) { /* an error occurred? */ |
| 291 | luaF_close(L, func); /* close eventual pending closures */ | 356 | L->top -= nargs+1; /* remove parameters and func from the stack */ |
| 292 | L->top = func; /* remove parameters from the stack */ | 357 | luaF_close(L, L->top); /* close eventual pending closures */ |
| 293 | } | 358 | } |
| 294 | lua_unlock(L); | 359 | lua_unlock(L); |
| 295 | return status; | 360 | return status; |
| @@ -310,7 +375,7 @@ static void f_parser (lua_State *L, void *ud) { | |||
| 310 | Closure *cl = luaF_newLclosure(L, 0); | 375 | Closure *cl = luaF_newLclosure(L, 0); |
| 311 | cl->l.p = tf; | 376 | cl->l.p = tf; |
| 312 | setclvalue(L->top, cl); | 377 | setclvalue(L->top, cl); |
| 313 | incr_top; | 378 | incr_top(L); |
| 314 | } | 379 | } |
| 315 | 380 | ||
| 316 | 381 | ||
| @@ -351,7 +416,7 @@ LUA_API int lua_loadfile (lua_State *L, const char *filename) { | |||
| 351 | if (f == NULL) return LUA_ERRFILE; /* unable to reopen file */ | 416 | if (f == NULL) return LUA_ERRFILE; /* unable to reopen file */ |
| 352 | } | 417 | } |
| 353 | lua_pushliteral(L, "@"); | 418 | lua_pushliteral(L, "@"); |
| 354 | lua_pushstring(L, (filename == NULL) ? "(stdin)" : filename); | 419 | lua_pushstring(L, (filename == NULL) ? "=stdin" : filename); |
| 355 | lua_concat(L, 2); | 420 | lua_concat(L, 2); |
| 356 | nlevel = lua_gettop(L); | 421 | nlevel = lua_gettop(L); |
| 357 | filename = lua_tostring(L, -1); /* filename = `@'..filename */ | 422 | filename = lua_tostring(L, -1); /* filename = `@'..filename */ |
| @@ -380,28 +445,17 @@ LUA_API int lua_loadbuffer (lua_State *L, const char *buff, size_t size, | |||
| 380 | ** ======================================================= | 445 | ** ======================================================= |
| 381 | */ | 446 | */ |
| 382 | 447 | ||
| 383 | /* chain list of long jump buffers */ | ||
| 384 | struct lua_longjmp { | ||
| 385 | jmp_buf b; | ||
| 386 | struct lua_longjmp *previous; | ||
| 387 | volatile int status; /* error code */ | ||
| 388 | int ci; /* index of call info of active function that set protection */ | ||
| 389 | StkId top; /* top stack when protection was set */ | ||
| 390 | int allowhooks; /* `allowhook' state when protection was set */ | ||
| 391 | }; | ||
| 392 | |||
| 393 | 448 | ||
| 394 | static void message (lua_State *L, const char *s) { | 449 | static void message (lua_State *L, const char *s) { |
| 395 | TObject o, m; | 450 | TObject o, m; |
| 396 | setsvalue(&o, luaS_newliteral(L, LUA_ERRORMESSAGE)); | 451 | setsvalue(&o, luaS_newliteral(L, LUA_ERRORMESSAGE)); |
| 397 | luaV_gettable(L, gt(L), &o, &m); | 452 | luaV_gettable(L, gt(L), &o, &m); |
| 398 | if (ttype(&m) == LUA_TFUNCTION) { | 453 | if (ttype(&m) == LUA_TFUNCTION) { |
| 399 | StkId top = L->top; | 454 | setobj(L->top, &m); |
| 400 | setobj(top, &m); | 455 | incr_top(L); |
| 401 | incr_top; | 456 | setsvalue(L->top, luaS_new(L, s)); |
| 402 | setsvalue(top+1, luaS_new(L, s)); | 457 | incr_top(L); |
| 403 | incr_top; | 458 | luaD_call(L, L->top-2, 0); |
| 404 | luaD_call(L, top, 0); | ||
| 405 | } | 459 | } |
| 406 | } | 460 | } |
| 407 | 461 | ||
| @@ -410,13 +464,7 @@ static void message (lua_State *L, const char *s) { | |||
| 410 | ** Reports an error, and jumps up to the available recovery label | 464 | ** Reports an error, and jumps up to the available recovery label |
| 411 | */ | 465 | */ |
| 412 | void luaD_error (lua_State *L, const char *s) { | 466 | void luaD_error (lua_State *L, const char *s) { |
| 413 | if (s) { | 467 | if (s) message(L, s); |
| 414 | if (L->ci->savedpc) { /* error in Lua function preamble? */ | ||
| 415 | L->ci->savedpc = NULL; /* pretend function was already running */ | ||
| 416 | L->ci->pc = NULL; | ||
| 417 | } | ||
| 418 | message(L, s); | ||
| 419 | } | ||
| 420 | luaD_breakrun(L, LUA_ERRRUN); | 468 | luaD_breakrun(L, LUA_ERRRUN); |
| 421 | } | 469 | } |
| 422 | 470 | ||
| @@ -436,8 +484,9 @@ void luaD_breakrun (lua_State *L, int errcode) { | |||
| 436 | 484 | ||
| 437 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | 485 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { |
| 438 | struct lua_longjmp lj; | 486 | struct lua_longjmp lj; |
| 439 | lj.ci = L->ci - L->base_ci; | 487 | lj.ci = L->ci; |
| 440 | lj.top = L->top; | 488 | lj.top = L->top; |
| 489 | lj.stack = L->stack; | ||
| 441 | lj.allowhooks = L->allowhooks; | 490 | lj.allowhooks = L->allowhooks; |
| 442 | lj.status = 0; | 491 | lj.status = 0; |
| 443 | lj.previous = L->errorJmp; /* chain new error handler */ | 492 | lj.previous = L->errorJmp; /* chain new error handler */ |
| @@ -445,7 +494,7 @@ int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | |||
| 445 | if (setjmp(lj.b) == 0) | 494 | if (setjmp(lj.b) == 0) |
| 446 | (*f)(L, ud); | 495 | (*f)(L, ud); |
| 447 | else { /* an error occurred: restore the state */ | 496 | else { /* an error occurred: restore the state */ |
| 448 | L->ci = L->base_ci + lj.ci; | 497 | L->ci = lj.ci; |
| 449 | L->top = lj.top; | 498 | L->top = lj.top; |
| 450 | L->allowhooks = lj.allowhooks; | 499 | L->allowhooks = lj.allowhooks; |
| 451 | restore_stack_limit(L); | 500 | restore_stack_limit(L); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.h,v 1.38 2002/01/11 20:24:39 roberto Exp $ | 2 | ** $Id: ldo.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
| 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 | */ |
| @@ -16,10 +16,10 @@ | |||
| 16 | ** macro to increment stack top. | 16 | ** macro to increment stack top. |
| 17 | ** There must be always an empty slot at the L->stack.top | 17 | ** There must be always an empty slot at the L->stack.top |
| 18 | */ | 18 | */ |
| 19 | #define incr_top {if (L->top == L->stack_last) luaD_checkstack(L, 1); L->top++;} | 19 | #define incr_top(L) \ |
| 20 | {if (L->top >= L->stack_last) luaD_growstack(L, 1); L->top++;} | ||
| 20 | 21 | ||
| 21 | 22 | #define luaD_checkstack(L,n) if (L->stack_last-(n)<=L->top) luaD_growstack(L, n) | |
| 22 | #define luaD_checkstack(L,n) if (L->stack_last-(n)<=L->top) luaD_stackerror(L) | ||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | void luaD_lineHook (lua_State *L, int line, lua_Hook linehook); | 25 | void luaD_lineHook (lua_State *L, int line, lua_Hook linehook); |
| @@ -27,7 +27,9 @@ void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event); | |||
| 27 | StkId luaD_precall (lua_State *L, StkId func); | 27 | StkId luaD_precall (lua_State *L, StkId func); |
| 28 | void luaD_call (lua_State *L, StkId func, int nResults); | 28 | void luaD_call (lua_State *L, StkId func, int nResults); |
| 29 | void luaD_poscall (lua_State *L, int wanted, StkId firstResult); | 29 | void luaD_poscall (lua_State *L, int wanted, StkId firstResult); |
| 30 | void luaD_stackerror (lua_State *L); | 30 | void luaD_reallocCI (lua_State *L, int newsize); |
| 31 | void luaD_reallocstack (lua_State *L, int newsize); | ||
| 32 | void luaD_growstack (lua_State *L, int n); | ||
| 31 | 33 | ||
| 32 | void luaD_error (lua_State *L, const char *s); | 34 | void luaD_error (lua_State *L, const char *s); |
| 33 | void luaD_breakrun (lua_State *L, int errcode); | 35 | void luaD_breakrun (lua_State *L, int errcode); |
| @@ -20,7 +20,6 @@ | |||
| 20 | #include "ltm.h" | 20 | #include "ltm.h" |
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | |||
| 24 | typedef struct GCState { | 23 | typedef struct GCState { |
| 25 | Table *tmark; /* list of marked tables to be visited */ | 24 | Table *tmark; /* list of marked tables to be visited */ |
| 26 | Table *toclear; /* list of visited weak tables (to be cleared after GC) */ | 25 | Table *toclear; /* list of visited weak tables (to be cleared after GC) */ |
| @@ -36,13 +35,14 @@ typedef struct GCState { | |||
| 36 | /* mark tricks for userdata */ | 35 | /* mark tricks for userdata */ |
| 37 | #define isudmarked(u) (u->uv.len & 1) | 36 | #define isudmarked(u) (u->uv.len & 1) |
| 38 | #define markud(u) (u->uv.len |= 1) | 37 | #define markud(u) (u->uv.len |= 1) |
| 39 | #define unmarkud(u) (u->uv.len--) | 38 | #define unmarkud(u) (u->uv.len &= (~(size_t)1)) |
| 40 | 39 | ||
| 41 | 40 | ||
| 42 | /* mark tricks for upvalues (assume that open upvalues are always marked) */ | 41 | /* mark tricks for upvalues (assume that open upvalues are always marked) */ |
| 43 | #define isupvalmarked(uv) ((uv)->v != &(uv)->value) | 42 | #define isupvalmarked(uv) ((uv)->v != &(uv)->value) |
| 44 | 43 | ||
| 45 | 44 | ||
| 45 | |||
| 46 | static void markobject (GCState *st, TObject *o); | 46 | static void markobject (GCState *st, TObject *o); |
| 47 | 47 | ||
| 48 | 48 | ||
| @@ -122,6 +122,17 @@ static void markobject (GCState *st, TObject *o) { | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | 124 | ||
| 125 | static void checkstacksizes (lua_State *L, StkId lim) { | ||
| 126 | int used = L->ci - L->base_ci; /* number of `ci' in use */ | ||
| 127 | if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) | ||
| 128 | luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ | ||
| 129 | if (lim < L->top) lim = L->top; | ||
| 130 | used = lim - L->stack; /* part of stack in use */ | ||
| 131 | if (3*used < L->stacksize && 2*BASIC_STACK_SIZE < L->stacksize) | ||
| 132 | luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ | ||
| 133 | } | ||
| 134 | |||
| 135 | |||
| 125 | static void markstacks (GCState *st) { | 136 | static void markstacks (GCState *st) { |
| 126 | lua_State *L1 = st->L; | 137 | lua_State *L1 = st->L; |
| 127 | do { /* for each thread */ | 138 | do { /* for each thread */ |
| @@ -137,6 +148,7 @@ static void markstacks (GCState *st) { | |||
| 137 | lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK | 148 | lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK |
| 138 | : L1->stack_last; | 149 | : L1->stack_last; |
| 139 | for (; o<=lim; o++) setnilvalue(o); | 150 | for (; o<=lim; o++) setnilvalue(o); |
| 151 | checkstacksizes(L1, lim); | ||
| 140 | lua_assert(L1->previous->next == L1 && L1->next->previous == L1); | 152 | lua_assert(L1->previous->next == L1 && L1->next->previous == L1); |
| 141 | L1 = L1->next; | 153 | L1 = L1->next; |
| 142 | } while (L1 != st->L); | 154 | } while (L1 != st->L); |
| @@ -374,11 +386,10 @@ static void checkMbuffer (lua_State *L) { | |||
| 374 | static void do1gcTM (lua_State *L, Udata *udata) { | 386 | static void do1gcTM (lua_State *L, Udata *udata) { |
| 375 | const TObject *tm = fasttm(L, udata->uv.eventtable, TM_GC); | 387 | const TObject *tm = fasttm(L, udata->uv.eventtable, TM_GC); |
| 376 | if (tm != NULL) { | 388 | if (tm != NULL) { |
| 377 | StkId top = L->top; | 389 | setobj(L->top, tm); |
| 378 | setobj(top, tm); | 390 | setuvalue(L->top+1, udata); |
| 379 | setuvalue(top+1, udata); | ||
| 380 | L->top += 2; | 391 | L->top += 2; |
| 381 | luaD_call(L, top, 0); | 392 | luaD_call(L, L->top - 2, 0); |
| 382 | } | 393 | } |
| 383 | } | 394 | } |
| 384 | 395 | ||
| @@ -396,6 +407,7 @@ static void unprotectedcallGCTM (lua_State *L, void *pu) { | |||
| 396 | do1gcTM(L, udata); | 407 | do1gcTM(L, udata); |
| 397 | /* mark udata as finalized (default event table) */ | 408 | /* mark udata as finalized (default event table) */ |
| 398 | uvalue(L->top-1)->uv.eventtable = hvalue(defaultet(L)); | 409 | uvalue(L->top-1)->uv.eventtable = hvalue(defaultet(L)); |
| 410 | unmarkud(uvalue(L->top-1)); | ||
| 399 | } | 411 | } |
| 400 | L->top--; | 412 | L->top--; |
| 401 | } | 413 | } |
| @@ -72,11 +72,6 @@ typedef unsigned char lu_byte; | |||
| 72 | 72 | ||
| 73 | 73 | ||
| 74 | 74 | ||
| 75 | #ifndef DEFAULT_STACK_SIZE | ||
| 76 | #define DEFAULT_STACK_SIZE 1024 | ||
| 77 | #endif | ||
| 78 | |||
| 79 | |||
| 80 | 75 | ||
| 81 | /* type to ensure maximum alignment */ | 76 | /* type to ensure maximum alignment */ |
| 82 | #ifndef LUSER_ALIGNMENT_T | 77 | #ifndef LUSER_ALIGNMENT_T |
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "ltm.h" | 20 | #include "ltm.h" |
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | |||
| 23 | struct Sopen { | 24 | struct Sopen { |
| 24 | int stacksize; | 25 | int stacksize; |
| 25 | lua_State *L; | 26 | lua_State *L; |
| @@ -29,21 +30,21 @@ struct Sopen { | |||
| 29 | static void close_state (lua_State *L); | 30 | static void close_state (lua_State *L); |
| 30 | 31 | ||
| 31 | 32 | ||
| 32 | static void stack_init (lua_State *L, lua_State *OL, int stacksize) { | 33 | static void stack_init (lua_State *L, lua_State *OL, int maxstacksize) { |
| 33 | if (stacksize == 0) | 34 | if (maxstacksize == 0) |
| 34 | stacksize = DEFAULT_STACK_SIZE; | 35 | maxstacksize = DEFAULT_MAXSTACK; |
| 35 | else | 36 | else |
| 36 | stacksize += LUA_MINSTACK; | 37 | maxstacksize += 2*LUA_MINSTACK; |
| 37 | stacksize += EXTRA_STACK; | 38 | L->stack = luaM_newvector(OL, BASIC_STACK_SIZE, TObject); |
| 38 | L->stack = luaM_newvector(OL, stacksize, TObject); | 39 | L->maxstacksize = maxstacksize; |
| 39 | L->stacksize = stacksize; | 40 | L->stacksize = BASIC_STACK_SIZE; |
| 40 | L->top = L->stack + RESERVED_STACK_PREFIX; | 41 | L->top = L->stack + RESERVED_STACK_PREFIX; |
| 41 | L->stack_last = L->stack+(L->stacksize-EXTRA_STACK)-1; | 42 | L->stack_last = L->stack+(BASIC_STACK_SIZE-EXTRA_STACK)-1; |
| 42 | L->base_ci = luaM_newvector(OL, 10, CallInfo); | 43 | L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo); |
| 43 | L->ci = L->base_ci; | 44 | L->ci = L->base_ci; |
| 44 | L->ci->base = L->top; | 45 | L->ci->base = L->top; |
| 45 | L->ci->savedpc = NULL; | 46 | L->ci->pc = NULL; |
| 46 | L->size_ci = 10; | 47 | L->size_ci = BASIC_CI_SIZE; |
| 47 | L->end_ci = L->base_ci + L->size_ci; | 48 | L->end_ci = L->base_ci + L->size_ci; |
| 48 | } | 49 | } |
| 49 | 50 | ||
| @@ -84,6 +85,7 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
| 84 | static void preinit_state (lua_State *L) { | 85 | static void preinit_state (lua_State *L) { |
| 85 | L->stack = NULL; | 86 | L->stack = NULL; |
| 86 | L->stacksize = 0; | 87 | L->stacksize = 0; |
| 88 | L->maxstacksize = 1; | ||
| 87 | L->errorJmp = NULL; | 89 | L->errorJmp = NULL; |
| 88 | L->callhook = NULL; | 90 | L->callhook = NULL; |
| 89 | L->linehook = NULL; | 91 | L->linehook = NULL; |
| @@ -64,8 +64,17 @@ struct lua_longjmp; /* defined in ldo.c */ | |||
| 64 | 64 | ||
| 65 | #define RESERVED_STACK_PREFIX 3 | 65 | #define RESERVED_STACK_PREFIX 3 |
| 66 | 66 | ||
| 67 | /* space to handle stack overflow errors */ | 67 | |
| 68 | #define EXTRA_STACK (2*LUA_MINSTACK) | 68 | /* space to handle TM calls */ |
| 69 | #define EXTRA_STACK 4 | ||
| 70 | |||
| 71 | |||
| 72 | #define BASIC_CI_SIZE 6 | ||
| 73 | |||
| 74 | #define BASIC_STACK_SIZE (2*LUA_MINSTACK) | ||
| 75 | |||
| 76 | #define DEFAULT_MAXSTACK 12000 | ||
| 77 | |||
| 69 | 78 | ||
| 70 | 79 | ||
| 71 | 80 | ||
| @@ -84,6 +93,7 @@ typedef struct CallInfo { | |||
| 84 | const Instruction *savedpc; | 93 | const Instruction *savedpc; |
| 85 | StkId top; /* top for this function (when it's a Lua function) */ | 94 | StkId top; /* top for this function (when it's a Lua function) */ |
| 86 | const Instruction **pc; | 95 | const Instruction **pc; |
| 96 | StkId *pb; | ||
| 87 | /* extra information for line tracing */ | 97 | /* extra information for line tracing */ |
| 88 | int lastpc; /* last pc traced */ | 98 | int lastpc; /* last pc traced */ |
| 89 | int line; /* current line */ | 99 | int line; /* current line */ |
| @@ -124,6 +134,7 @@ struct lua_State { | |||
| 124 | StkId stack_last; /* last free slot in the stack */ | 134 | StkId stack_last; /* last free slot in the stack */ |
| 125 | StkId stack; /* stack base */ | 135 | StkId stack; /* stack base */ |
| 126 | int stacksize; | 136 | int stacksize; |
| 137 | int maxstacksize; | ||
| 127 | CallInfo *end_ci; /* points after end of ci array*/ | 138 | CallInfo *end_ci; /* points after end of ci array*/ |
| 128 | CallInfo *base_ci; /* array of CallInfo's */ | 139 | CallInfo *base_ci; /* array of CallInfo's */ |
| 129 | int size_ci; /* size of array `base_ci' */ | 140 | int size_ci; /* size of array `base_ci' */ |
| @@ -254,10 +254,14 @@ static int hash_query (lua_State *L) { | |||
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | 256 | ||
| 257 | static int Cstacklevel (lua_State *L) { | 257 | static int stacklevel (lua_State *L) { |
| 258 | unsigned long a = 0; | 258 | unsigned long a = 0; |
| 259 | lua_pushnumber(L, (int)(L->top - L->stack)); | ||
| 260 | lua_pushnumber(L, (int)(L->stack_last - L->stack)); | ||
| 261 | lua_pushnumber(L, (int)(L->ci - L->base_ci)); | ||
| 262 | lua_pushnumber(L, (int)(L->end_ci - L->base_ci)); | ||
| 259 | lua_pushnumber(L, (unsigned long)&a); | 263 | lua_pushnumber(L, (unsigned long)&a); |
| 260 | return 1; | 264 | return 5; |
| 261 | } | 265 | } |
| 262 | 266 | ||
| 263 | 267 | ||
| @@ -307,7 +311,7 @@ static int string_query (lua_State *L) { | |||
| 307 | int n = 0; | 311 | int n = 0; |
| 308 | for (ts = tb->hash[s]; ts; ts = ts->tsv.nexthash) { | 312 | for (ts = tb->hash[s]; ts; ts = ts->tsv.nexthash) { |
| 309 | setsvalue(L->top, ts); | 313 | setsvalue(L->top, ts); |
| 310 | incr_top; | 314 | incr_top(L); |
| 311 | n++; | 315 | n++; |
| 312 | } | 316 | } |
| 313 | return n; | 317 | return n; |
| @@ -629,7 +633,7 @@ static const struct luaL_reg tests_funcs[] = { | |||
| 629 | {"listk", listk}, | 633 | {"listk", listk}, |
| 630 | {"listlocals", listlocals}, | 634 | {"listlocals", listlocals}, |
| 631 | {"loadlib", loadlib}, | 635 | {"loadlib", loadlib}, |
| 632 | {"Cstacklevel", Cstacklevel}, | 636 | {"stacklevel", stacklevel}, |
| 633 | {"querystr", string_query}, | 637 | {"querystr", string_query}, |
| 634 | {"querytab", table_query}, | 638 | {"querytab", table_query}, |
| 635 | {"testC", testC}, | 639 | {"testC", testC}, |
| @@ -29,10 +29,9 @@ | |||
| 29 | 29 | ||
| 30 | static void luaV_checkGC (lua_State *L, StkId top) { | 30 | static void luaV_checkGC (lua_State *L, StkId top) { |
| 31 | if (G(L)->nblocks >= G(L)->GCthreshold) { | 31 | if (G(L)->nblocks >= G(L)->GCthreshold) { |
| 32 | StkId temp = L->top; | 32 | L->top = top; /* limit for active registers */ |
| 33 | L->top = top; | ||
| 34 | luaC_collectgarbage(L); | 33 | luaC_collectgarbage(L); |
| 35 | L->top = temp; /* restore old top position */ | 34 | L->top = L->ci->top; /* restore old top position */ |
| 36 | } | 35 | } |
| 37 | } | 36 | } |
| 38 | 37 | ||
| @@ -83,32 +82,37 @@ static void traceexec (lua_State *L, lua_Hook linehook) { | |||
| 83 | if (newline != ci->line || pc <= ci->lastpc) { | 82 | if (newline != ci->line || pc <= ci->lastpc) { |
| 84 | ci->line = newline; | 83 | ci->line = newline; |
| 85 | luaD_lineHook(L, newline, linehook); | 84 | luaD_lineHook(L, newline, linehook); |
| 85 | ci = L->ci; /* previous call may realocate `ci' */ | ||
| 86 | } | 86 | } |
| 87 | ci->lastpc = pc; | 87 | ci->lastpc = pc; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | 90 | ||
| 91 | static void callTMres (lua_State *L, const TObject *f, | ||
| 92 | const TObject *p1, const TObject *p2, TObject *result ) { | ||
| 93 | StkId stack = L->stack; | ||
| 94 | setobj(L->top, f); /* push function */ | ||
| 95 | setobj(L->top+1, p1); /* 1st argument */ | ||
| 96 | setobj(L->top+2, p2); /* 2nd argument */ | ||
| 97 | luaD_checkstack(L, 3); /* cannot check before (could invalidate p1, p2) */ | ||
| 98 | L->top += 3; | ||
| 99 | luaD_call(L, L->top - 3, 1); | ||
| 100 | if (stack != L->stack) /* stack changed? */ | ||
| 101 | result = (result - stack) + L->stack; /* correct pointer */ | ||
| 102 | setobj(result, --L->top); /* get result */ | ||
| 103 | } | ||
| 104 | |||
| 91 | 105 | ||
| 92 | /* maximum stack used by a call to a tag method (func + args) */ | ||
| 93 | #define MAXSTACK_TM 4 | ||
| 94 | 106 | ||
| 95 | static void callTM (lua_State *L, const TObject *f, | 107 | static void callTM (lua_State *L, const TObject *f, |
| 96 | const TObject *p1, const TObject *p2, const TObject *p3, TObject *result ) { | 108 | const TObject *p1, const TObject *p2, const TObject *p3) { |
| 97 | StkId base = L->top; | 109 | setobj(L->top, f); /* push function */ |
| 98 | luaD_checkstack(L, MAXSTACK_TM); | 110 | setobj(L->top+1, p1); /* 1st argument */ |
| 99 | setobj(base, f); /* push function */ | 111 | setobj(L->top+2, p2); /* 2nd argument */ |
| 100 | setobj(base+1, p1); /* 1st argument */ | 112 | setobj(L->top+3, p3); /* 3th argument */ |
| 101 | setobj(base+2, p2); /* 2nd argument */ | 113 | luaD_checkstack(L, 4); /* cannot check before (could invalidate p1...p3) */ |
| 102 | L->top += 3; | 114 | L->top += 4; |
| 103 | if (p3) { | 115 | luaD_call(L, L->top - 4, 0); |
| 104 | setobj(base+3, p3); /* 3th argument */ | ||
| 105 | L->top++; | ||
| 106 | } | ||
| 107 | luaD_call(L, base, 1); | ||
| 108 | if (result) { /* need a result? */ | ||
| 109 | setobj(result, base); /* get it */ | ||
| 110 | } | ||
| 111 | L->top = base; /* restore top */ | ||
| 112 | } | 116 | } |
| 113 | 117 | ||
| 114 | 118 | ||
| @@ -139,7 +143,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { | |||
| 139 | } | 143 | } |
| 140 | } | 144 | } |
| 141 | if (ttype(tm) == LUA_TFUNCTION) | 145 | if (ttype(tm) == LUA_TFUNCTION) |
| 142 | callTM(L, tm, t, key, NULL, res); | 146 | callTMres(L, tm, t, key, res); |
| 143 | else { | 147 | else { |
| 144 | t = (StkId)tm; /* ?? */ | 148 | t = (StkId)tm; /* ?? */ |
| 145 | goto init; /* return luaV_gettable(L, tm, key, res); */ | 149 | goto init; /* return luaV_gettable(L, tm, key, res); */ |
| @@ -167,7 +171,7 @@ void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) { | |||
| 167 | } | 171 | } |
| 168 | } | 172 | } |
| 169 | if (ttype(tm) == LUA_TFUNCTION) | 173 | if (ttype(tm) == LUA_TFUNCTION) |
| 170 | callTM(L, tm, t, key, val, NULL); | 174 | callTM(L, tm, t, key, val); |
| 171 | else { | 175 | else { |
| 172 | t = (StkId)tm; /* ?? */ | 176 | t = (StkId)tm; /* ?? */ |
| 173 | goto init; /* luaV_settable(L, tm, key, val); */ | 177 | goto init; /* luaV_settable(L, tm, key, val); */ |
| @@ -181,7 +185,7 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, | |||
| 181 | if (ttype(tm) == LUA_TNIL) | 185 | if (ttype(tm) == LUA_TNIL) |
| 182 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ | 186 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ |
| 183 | if (ttype(tm) != LUA_TFUNCTION) return 0; | 187 | if (ttype(tm) != LUA_TFUNCTION) return 0; |
| 184 | callTM(L, tm, p1, p2, NULL, res); | 188 | callTMres(L, tm, p1, p2, res); |
| 185 | return 1; | 189 | return 1; |
| 186 | } | 190 | } |
| 187 | 191 | ||
| @@ -229,7 +233,6 @@ int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { | |||
| 229 | 233 | ||
| 230 | 234 | ||
| 231 | void luaV_strconc (lua_State *L, int total, int last) { | 235 | void luaV_strconc (lua_State *L, int total, int last) { |
| 232 | luaV_checkGC(L, L->ci->base + last + 1); | ||
| 233 | do { | 236 | do { |
| 234 | StkId top = L->ci->base + last + 1; | 237 | StkId top = L->ci->base + last + 1; |
| 235 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 238 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
| @@ -273,7 +276,7 @@ static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) { | |||
| 273 | luaV_gettable(L, gt(L), &o, &f); | 276 | luaV_gettable(L, gt(L), &o, &f); |
| 274 | if (ttype(&f) != LUA_TFUNCTION) | 277 | if (ttype(&f) != LUA_TFUNCTION) |
| 275 | luaD_error(L, "`pow' (for `^' operator) is not a function"); | 278 | luaD_error(L, "`pow' (for `^' operator) is not a function"); |
| 276 | callTM(L, &f, b, c, NULL, ra); | 279 | callTMres(L, &f, b, c, ra); |
| 277 | } | 280 | } |
| 278 | else | 281 | else |
| 279 | call_arith(L, rb, rc, ra, TM_POW); | 282 | call_arith(L, rb, rc, ra, TM_POW); |
| @@ -324,17 +327,18 @@ StkId luaV_execute (lua_State *L) { | |||
| 324 | k = cl->p->k; | 327 | k = cl->p->k; |
| 325 | linehook = L->linehook; | 328 | linehook = L->linehook; |
| 326 | L->ci->pc = &pc; | 329 | L->ci->pc = &pc; |
| 330 | L->ci->pb = &base; | ||
| 327 | pc = L->ci->savedpc; | 331 | pc = L->ci->savedpc; |
| 328 | L->ci->savedpc = NULL; | ||
| 329 | /* main loop of interpreter */ | 332 | /* main loop of interpreter */ |
| 330 | for (;;) { | 333 | for (;;) { |
| 331 | const Instruction i = *pc++; | 334 | const Instruction i = *pc++; |
| 332 | const StkId ra = RA(i); | 335 | StkId ra; |
| 333 | if (linehook) | 336 | if (linehook) |
| 334 | traceexec(L, linehook); | 337 | traceexec(L, linehook); |
| 338 | ra = RA(i); | ||
| 339 | lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base); | ||
| 335 | lua_assert(L->top == L->ci->top || GET_OPCODE(i) == OP_CALL || | 340 | lua_assert(L->top == L->ci->top || GET_OPCODE(i) == OP_CALL || |
| 336 | GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO); | 341 | GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO); |
| 337 | lua_assert(L->ci->savedpc == NULL); | ||
| 338 | switch (GET_OPCODE(i)) { | 342 | switch (GET_OPCODE(i)) { |
| 339 | case OP_MOVE: { | 343 | case OP_MOVE: { |
| 340 | setobj(ra, RB(i)); | 344 | setobj(ra, RB(i)); |
| @@ -344,10 +348,6 @@ StkId luaV_execute (lua_State *L) { | |||
| 344 | setobj(ra, KBc(i)); | 348 | setobj(ra, KBc(i)); |
| 345 | break; | 349 | break; |
| 346 | } | 350 | } |
| 347 | case OP_LOADINT: { | ||
| 348 | setnvalue(ra, (lua_Number)GETARG_sBc(i)); | ||
| 349 | break; | ||
| 350 | } | ||
| 351 | case OP_LOADBOOL: { | 351 | case OP_LOADBOOL: { |
| 352 | setbvalue(ra, GETARG_B(i)); | 352 | setbvalue(ra, GETARG_B(i)); |
| 353 | if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ | 353 | if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ |
| @@ -441,8 +441,9 @@ StkId luaV_execute (lua_State *L) { | |||
| 441 | case OP_CONCAT: { | 441 | case OP_CONCAT: { |
| 442 | int b = GETARG_B(i); | 442 | int b = GETARG_B(i); |
| 443 | int c = GETARG_C(i); | 443 | int c = GETARG_C(i); |
| 444 | luaV_strconc(L, c-b+1, c); | 444 | luaV_strconc(L, c-b+1, c); /* this call may change `base' (and `ra') */ |
| 445 | setobj(ra, base+b); | 445 | setobj(base+GETARG_A(i), base+b); |
| 446 | luaV_checkGC(L, base+c+1); | ||
| 446 | break; | 447 | break; |
| 447 | } | 448 | } |
| 448 | case OP_JMP: { | 449 | case OP_JMP: { |
| @@ -493,7 +494,7 @@ StkId luaV_execute (lua_State *L) { | |||
| 493 | nresults = GETARG_C(i) - 1; | 494 | nresults = GETARG_C(i) - 1; |
| 494 | firstResult = luaD_precall(L, ra); | 495 | firstResult = luaD_precall(L, ra); |
| 495 | if (firstResult) { | 496 | if (firstResult) { |
| 496 | if (firstResult == base) { /* yield?? */ | 497 | if (firstResult > L->top) { /* yield? */ |
| 497 | (L->ci-1)->savedpc = pc; | 498 | (L->ci-1)->savedpc = pc; |
| 498 | return NULL; | 499 | return NULL; |
| 499 | } | 500 | } |
| @@ -514,16 +515,16 @@ StkId luaV_execute (lua_State *L) { | |||
| 514 | b = GETARG_B(i); | 515 | b = GETARG_B(i); |
| 515 | if (b != 0) L->top = ra+b-1; | 516 | if (b != 0) L->top = ra+b-1; |
| 516 | ci = L->ci - 1; | 517 | ci = L->ci - 1; |
| 517 | if (ci->savedpc == NULL) | 518 | lua_assert((ci+1)->pc == &pc); |
| 518 | return ra; | 519 | if (ci->pc != &pc) /* previous function was running `here'? */ |
| 519 | else { /* previous function is Lua: continue its execution */ | 520 | return ra; /* no: return */ |
| 521 | else { /* yes: continue its execution */ | ||
| 520 | int nresults; | 522 | int nresults; |
| 521 | lua_assert(ttype(ci->base-1) == LUA_TFUNCTION); | 523 | lua_assert(ttype(ci->base-1) == LUA_TFUNCTION); |
| 522 | base = ci->base; /* restore previous values */ | 524 | base = ci->base; /* restore previous values */ |
| 523 | cl = &clvalue(base - 1)->l; | 525 | cl = &clvalue(base - 1)->l; |
| 524 | k = cl->p->k; | 526 | k = cl->p->k; |
| 525 | pc = ci->savedpc; | 527 | pc = ci->savedpc; |
| 526 | ci->savedpc = NULL; | ||
| 527 | lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL); | 528 | lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL); |
| 528 | nresults = GETARG_C(*(pc-1)) - 1; | 529 | nresults = GETARG_C(*(pc-1)) - 1; |
| 529 | luaD_poscall(L, nresults, ra); | 530 | luaD_poscall(L, nresults, ra); |
| @@ -607,7 +608,6 @@ StkId luaV_execute (lua_State *L) { | |||
| 607 | Proto *p; | 608 | Proto *p; |
| 608 | Closure *ncl; | 609 | Closure *ncl; |
| 609 | int nup, j; | 610 | int nup, j; |
| 610 | luaV_checkGC(L, L->top); | ||
| 611 | p = cl->p->p[GETARG_Bc(i)]; | 611 | p = cl->p->p[GETARG_Bc(i)]; |
| 612 | nup = p->nupvalues; | 612 | nup = p->nupvalues; |
| 613 | ncl = luaF_newLclosure(L, nup); | 613 | ncl = luaF_newLclosure(L, nup); |
| @@ -621,6 +621,7 @@ StkId luaV_execute (lua_State *L) { | |||
| 621 | } | 621 | } |
| 622 | } | 622 | } |
| 623 | setclvalue(ra, ncl); | 623 | setclvalue(ra, ncl); |
| 624 | luaV_checkGC(L, L->top); | ||
| 624 | break; | 625 | break; |
| 625 | } | 626 | } |
| 626 | } | 627 | } |
