diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-01-25 20:14:54 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-01-25 20:14:54 -0200 |
commit | 50e29525936be4891f9db090f293432913b5f7c0 (patch) | |
tree | 8e487b87f82761e15cd096ac345354f57f38fedc | |
parent | b217ae644e3a83def93be2fe742e2cd0970e1a5f (diff) | |
download | lua-50e29525936be4891f9db090f293432913b5f7c0.tar.gz lua-50e29525936be4891f9db090f293432913b5f7c0.tar.bz2 lua-50e29525936be4891f9db090f293432913b5f7c0.zip |
first version of dynamic stack
-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 | } |