diff options
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 227 |
1 files changed, 100 insertions, 127 deletions
@@ -1,10 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.164 2001/02/02 15:13:05 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.165 2001/02/06 16:01:29 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | #include <stdarg.h> | ||
8 | #include <stdio.h> | 9 | #include <stdio.h> |
9 | #include <stdlib.h> | 10 | #include <stdlib.h> |
10 | #include <string.h> | 11 | #include <string.h> |
@@ -26,14 +27,6 @@ | |||
26 | 27 | ||
27 | 28 | ||
28 | 29 | ||
29 | /* | ||
30 | ** Extra stack size to run a function: | ||
31 | ** TAG_LINE(1), NAME(1), TM calls(3) (plus some extra...) | ||
32 | */ | ||
33 | #define EXTRA_FSTACK 8 | ||
34 | |||
35 | |||
36 | |||
37 | int luaV_tonumber (TObject *obj) { | 30 | int luaV_tonumber (TObject *obj) { |
38 | if (ttype(obj) != LUA_TSTRING) | 31 | if (ttype(obj) != LUA_TSTRING) |
39 | return 1; | 32 | return 1; |
@@ -58,7 +51,7 @@ int luaV_tostring (lua_State *L, TObject *obj) { /* LUA_NUMBER */ | |||
58 | } | 51 | } |
59 | 52 | ||
60 | 53 | ||
61 | static void traceexec (lua_State *L, StkId base, StkId top, lua_Hook linehook) { | 54 | static void traceexec (lua_State *L, StkId base, lua_Hook linehook) { |
62 | CallInfo *ci = infovalue(base-1); | 55 | CallInfo *ci = infovalue(base-1); |
63 | int *lineinfo = ci->func->f.l->lineinfo; | 56 | int *lineinfo = ci->func->f.l->lineinfo; |
64 | int pc = (*ci->pc - ci->func->f.l->code) - 1; | 57 | int pc = (*ci->pc - ci->func->f.l->code) - 1; |
@@ -72,7 +65,6 @@ static void traceexec (lua_State *L, StkId base, StkId top, lua_Hook linehook) { | |||
72 | /* calls linehook when enters a new line or jumps back (loop) */ | 65 | /* calls linehook when enters a new line or jumps back (loop) */ |
73 | if (newline != ci->line || pc <= ci->lastpc) { | 66 | if (newline != ci->line || pc <= ci->lastpc) { |
74 | ci->line = newline; | 67 | ci->line = newline; |
75 | L->top = top; | ||
76 | luaD_lineHook(L, base-2, newline, linehook); | 68 | luaD_lineHook(L, base-2, newline, linehook); |
77 | } | 69 | } |
78 | ci->lastpc = pc; | 70 | ci->lastpc = pc; |
@@ -104,19 +96,52 @@ void luaV_Lclosure (lua_State *L, Proto *l, int nelems) { | |||
104 | } | 96 | } |
105 | 97 | ||
106 | 98 | ||
99 | static void callTM (lua_State *L, const char *fmt, ...) { | ||
100 | va_list argp; | ||
101 | StkId base = L->top; | ||
102 | int has_result = 0; | ||
103 | va_start(argp, fmt); | ||
104 | for (;;) { | ||
105 | switch (*fmt++) { | ||
106 | case 'c': | ||
107 | setclvalue(L->top, va_arg(argp, Closure *)); | ||
108 | break; | ||
109 | case 'o': | ||
110 | setobj(L->top, va_arg(argp, TObject *)); | ||
111 | break; | ||
112 | case 's': | ||
113 | setsvalue(L->top, va_arg(argp, TString *)); | ||
114 | break; | ||
115 | case 'r': | ||
116 | has_result = 1; | ||
117 | /* go through */ | ||
118 | default: | ||
119 | goto endloop; | ||
120 | } | ||
121 | incr_top; | ||
122 | } endloop: | ||
123 | luaD_call(L, base, has_result); | ||
124 | if (has_result) { | ||
125 | L->top--; | ||
126 | setobj(va_arg(argp, TObject *), L->top); | ||
127 | } | ||
128 | va_end(argp); | ||
129 | } | ||
130 | |||
131 | |||
107 | /* | 132 | /* |
108 | ** Function to index a table. | 133 | ** Function to index a table. |
109 | ** Receives the table at `t' and the key at the top (`top'-1), | 134 | ** Receives the table at `t' and the key at the `key'. |
110 | ** leaves the result at `res'. | 135 | ** leaves the result at `res'. |
111 | */ | 136 | */ |
112 | void luaV_gettable (lua_State *L, StkId t, StkId top, StkId res) { | 137 | void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { |
113 | Closure *tm; | 138 | Closure *tm; |
114 | int tg; | 139 | int tg; |
115 | if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ | 140 | if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ |
116 | ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ | 141 | ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ |
117 | luaT_gettm(G(L), tg, TM_GETTABLE) == NULL)) { /* or no TM? */ | 142 | luaT_gettm(G(L), tg, TM_GETTABLE) == NULL)) { /* or no TM? */ |
118 | /* do a primitive get */ | 143 | /* do a primitive get */ |
119 | const TObject *h = luaH_get(hvalue(t), top-1); | 144 | const TObject *h = luaH_get(hvalue(t), key); |
120 | /* result is no nil or there is no `index' tag method? */ | 145 | /* result is no nil or there is no `index' tag method? */ |
121 | if (ttype(h) != LUA_TNIL || ((tm=luaT_gettm(G(L), tg, TM_INDEX)) == NULL)) { | 146 | if (ttype(h) != LUA_TNIL || ((tm=luaT_gettm(G(L), tg, TM_INDEX)) == NULL)) { |
122 | setobj(res, h); | 147 | setobj(res, h); |
@@ -127,116 +152,79 @@ void luaV_gettable (lua_State *L, StkId t, StkId top, StkId res) { | |||
127 | else { /* try a `gettable' tag method */ | 152 | else { /* try a `gettable' tag method */ |
128 | tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE); | 153 | tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE); |
129 | } | 154 | } |
130 | L->top = top; | ||
131 | if (tm == NULL) /* no tag method? */ | 155 | if (tm == NULL) /* no tag method? */ |
132 | luaG_typeerror(L, t, "index"); | 156 | luaG_typeerror(L, t, "index"); |
133 | else { /* call tag method */ | 157 | else |
134 | luaD_checkstack(L, 2); | 158 | callTM(L, "coor", tm, t, key, res); |
135 | setobj(res+2, top-1); /* key */ | ||
136 | setobj(res+1, t); /* table */ | ||
137 | setclvalue(res, tm); /* tag method */ | ||
138 | L->top = res+3; | ||
139 | luaD_call(L, res, 1); | ||
140 | L->top = top; /* will be decremented by the callee */ | ||
141 | } | ||
142 | } | 159 | } |
143 | 160 | ||
144 | 161 | ||
162 | |||
145 | /* | 163 | /* |
146 | ** Receives table at `t', key at `key' and value at top. | 164 | ** Receives table at `t', key at `key' and value at `val'. |
147 | */ | 165 | */ |
148 | void luaV_settable (lua_State *L, StkId t, StkId key, StkId top) { | 166 | void luaV_settable (lua_State *L, StkId t, StkId key, StkId val) { |
149 | int tg; | 167 | int tg; |
150 | if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ | 168 | if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ |
151 | ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ | 169 | ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ |
152 | luaT_gettm(G(L), tg, TM_SETTABLE) == NULL)) { /* or no TM? */ | 170 | luaT_gettm(G(L), tg, TM_SETTABLE) == NULL)) { /* or no TM? */ |
153 | setobj(luaH_set(L, hvalue(t), key), top-1); /* do a primitive set */ | 171 | setobj(luaH_set(L, hvalue(t), key), val); /* do a primitive set */ |
154 | } | 172 | } |
155 | else { /* try a `settable' tag method */ | 173 | else { /* try a `settable' tag method */ |
156 | Closure *tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE); | 174 | Closure *tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE); |
157 | lua_assert(L->top == top); | ||
158 | if (tm == NULL) /* no tag method? */ | 175 | if (tm == NULL) /* no tag method? */ |
159 | luaG_typeerror(L, t, "index"); | 176 | luaG_typeerror(L, t, "index"); |
160 | else { | 177 | else |
161 | luaD_checkstack(L, 3); | 178 | callTM(L, "cooo", tm, t, key, val); |
162 | setobj(top+2, top-1); | ||
163 | setobj(top+1, key); | ||
164 | setobj(top, t); | ||
165 | setclvalue(top-1, tm); | ||
166 | L->top = top+3; | ||
167 | luaD_call(L, top-1, 0); /* call `settable' tag method */ | ||
168 | lua_assert(L->top == top-1); | ||
169 | L->top = top; /* will be decremented by the callee */ | ||
170 | } | ||
171 | } | 179 | } |
172 | } | 180 | } |
173 | 181 | ||
174 | 182 | ||
175 | void luaV_getglobal (lua_State *L, TString *s, StkId top) { | 183 | void luaV_getglobal (lua_State *L, TString *name, StkId res) { |
176 | const TObject *value = luaH_getstr(L->gt, s); | 184 | const TObject *value = luaH_getstr(L->gt, name); |
177 | Closure *tm; | 185 | Closure *tm; |
178 | if (!HAS_TM_GETGLOBAL(L, ttype(value)) || /* is there a tag method? */ | 186 | if (!HAS_TM_GETGLOBAL(L, ttype(value)) || /* is there a tag method? */ |
179 | (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) { | 187 | (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) { |
180 | setobj(top, value); /* default behavior */ | 188 | setobj(res, value); /* default behavior */ |
181 | } | ||
182 | else { /* call tag method */ | ||
183 | L->top = top; | ||
184 | luaD_checkstack(L, 3); | ||
185 | setclvalue(top, tm); | ||
186 | setsvalue(top+1, s); /* global name */ | ||
187 | setobj(top+2, value); | ||
188 | L->top = top+3; | ||
189 | luaD_call(L, top, 1); | ||
190 | lua_assert(L->top == top+1); | ||
191 | L->top = top; /* will be incremented by the callee */ | ||
192 | } | 189 | } |
190 | else | ||
191 | callTM(L, "csor", tm, name, value, res); | ||
193 | } | 192 | } |
194 | 193 | ||
195 | 194 | ||
196 | void luaV_setglobal (lua_State *L, TString *s, StkId top) { | 195 | void luaV_setglobal (lua_State *L, TString *name, StkId val) { |
197 | TObject *oldvalue = luaH_setstr(L, L->gt, s); | 196 | TObject *oldvalue = luaH_setstr(L, L->gt, name); |
198 | Closure *tm; | 197 | Closure *tm; |
199 | if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) || /* no tag methods? */ | 198 | if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) || /* no tag methods? */ |
200 | (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) { | 199 | (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) { |
201 | setobj(oldvalue, top-1); /* raw set */ | 200 | setobj(oldvalue, val); /* raw set */ |
202 | } | ||
203 | else { /* call tag method */ | ||
204 | lua_assert(L->top == top); | ||
205 | luaD_checkstack(L, 3); | ||
206 | setobj(top+2, top-1); /* new value */ | ||
207 | setobj(top+1, oldvalue); /* old value */ | ||
208 | setsvalue(top, s); /* var name */ | ||
209 | setclvalue(top-1, tm); /* tag method */ | ||
210 | L->top = top+3; | ||
211 | luaD_call(L, top-1, 0); | ||
212 | lua_assert(L->top == top-1); | ||
213 | L->top = top; /* will be decremented by the callee */ | ||
214 | } | 201 | } |
202 | else | ||
203 | callTM(L, "csoo", tm, name, oldvalue, val); | ||
215 | } | 204 | } |
216 | 205 | ||
217 | 206 | ||
218 | static int call_binTM (lua_State *L, StkId top, TMS event) { | 207 | static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, |
219 | /* try first operand */ | 208 | TObject *res, TMS event) { |
220 | Closure *tm = luaT_gettmbyObj(G(L), top-2, event); | 209 | TString *opname; |
221 | L->top = top; | 210 | Closure *tm = luaT_gettmbyObj(G(L), p1, event); /* try first operand */ |
222 | if (tm == NULL) { | 211 | if (tm == NULL) { |
223 | tm = luaT_gettmbyObj(G(L), top-1, event); /* try second operand */ | 212 | tm = luaT_gettmbyObj(G(L), p2, event); /* try second operand */ |
224 | if (tm == NULL) { | 213 | if (tm == NULL) { |
225 | tm = luaT_gettm(G(L), 0, event); /* try a `global' method */ | 214 | tm = luaT_gettm(G(L), 0, event); /* try a `global' method */ |
226 | if (tm == NULL) | 215 | if (tm == NULL) |
227 | return 0; /* error */ | 216 | return 0; /* no tag method */ |
228 | } | 217 | } |
229 | } | 218 | } |
230 | setsvalue(L->top, luaS_new(L, luaT_eventname[event])); | 219 | opname = luaS_new(L, luaT_eventname[event]); |
231 | incr_top; | 220 | callTM(L, "coosr", tm, p1, p2, opname, res); |
232 | luaD_callTM(L, tm, 3, 1); | ||
233 | return 1; | 221 | return 1; |
234 | } | 222 | } |
235 | 223 | ||
236 | 224 | ||
237 | static void call_arith (lua_State *L, StkId top, TMS event) { | 225 | static void call_arith (lua_State *L, StkId p1, TMS event) { |
238 | if (!call_binTM(L, top, event)) | 226 | if (!call_binTM(L, p1, p1+1, p1, event)) |
239 | luaG_binerror(L, top-2, LUA_TNUMBER, "perform arithmetic on"); | 227 | luaG_binerror(L, p1, LUA_TNUMBER, "perform arithmetic on"); |
240 | } | 228 | } |
241 | 229 | ||
242 | 230 | ||
@@ -262,19 +250,14 @@ static int luaV_strlessthan (const TString *ls, const TString *rs) { | |||
262 | } | 250 | } |
263 | 251 | ||
264 | 252 | ||
265 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r, StkId top) { | 253 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { |
266 | if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) | 254 | if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) |
267 | return (nvalue(l) < nvalue(r)); | 255 | return (nvalue(l) < nvalue(r)); |
268 | else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) | 256 | else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) |
269 | return luaV_strlessthan(tsvalue(l), tsvalue(r)); | 257 | return luaV_strlessthan(tsvalue(l), tsvalue(r)); |
270 | else { /* call TM */ | 258 | else { /* try TM */ |
271 | L->top = top; | 259 | if (!call_binTM(L, l, r, L->top, TM_LT)) |
272 | luaD_checkstack(L, 2); | 260 | luaG_ordererror(L, l, r); |
273 | setobj(top++, l); | ||
274 | setobj(top++, r); | ||
275 | if (!call_binTM(L, top, TM_LT)) | ||
276 | luaG_ordererror(L, top); | ||
277 | L->top--; | ||
278 | return (ttype(L->top) != LUA_TNIL); | 261 | return (ttype(L->top) != LUA_TNIL); |
279 | } | 262 | } |
280 | } | 263 | } |
@@ -284,7 +267,7 @@ void luaV_strconc (lua_State *L, int total, StkId top) { | |||
284 | do { | 267 | do { |
285 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 268 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
286 | if (tostring(L, top-2) || tostring(L, top-1)) { | 269 | if (tostring(L, top-2) || tostring(L, top-1)) { |
287 | if (!call_binTM(L, top, TM_CONCAT)) | 270 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) |
288 | luaG_binerror(L, top-2, LUA_TSTRING, "concat"); | 271 | luaG_binerror(L, top-2, LUA_TSTRING, "concat"); |
289 | } | 272 | } |
290 | else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ | 273 | else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ |
@@ -350,17 +333,16 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
350 | TString **const kstr = tf->kstr; | 333 | TString **const kstr = tf->kstr; |
351 | const lua_Hook linehook = L->linehook; | 334 | const lua_Hook linehook = L->linehook; |
352 | infovalue(base-1)->pc = &pc; | 335 | infovalue(base-1)->pc = &pc; |
353 | luaD_checkstack(L, tf->maxstacksize+EXTRA_FSTACK); | ||
354 | if (tf->is_vararg) /* varargs? */ | 336 | if (tf->is_vararg) /* varargs? */ |
355 | adjust_varargs(L, base, tf->numparams); | 337 | adjust_varargs(L, base, tf->numparams); |
356 | else | 338 | luaD_adjusttop(L, base, tf->maxstacksize); |
357 | luaD_adjusttop(L, base, tf->numparams); | 339 | top = base+tf->numparams+tf->is_vararg; |
358 | top = L->top; | ||
359 | /* main loop of interpreter */ | 340 | /* main loop of interpreter */ |
360 | for (;;) { | 341 | for (;;) { |
361 | const Instruction i = *pc++; | 342 | const Instruction i = *pc++; |
343 | lua_assert(L->top == base+tf->maxstacksize); | ||
362 | if (linehook) | 344 | if (linehook) |
363 | traceexec(L, base, top, linehook); | 345 | traceexec(L, base, linehook); |
364 | switch (GET_OPCODE(i)) { | 346 | switch (GET_OPCODE(i)) { |
365 | case OP_RETURN: { | 347 | case OP_RETURN: { |
366 | L->top = top; | 348 | L->top = top; |
@@ -372,6 +354,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
372 | L->top = top; | 354 | L->top = top; |
373 | luaD_call(L, base+GETARG_A(i), nres); | 355 | luaD_call(L, base+GETARG_A(i), nres); |
374 | top = L->top; | 356 | top = L->top; |
357 | L->top = base+tf->maxstacksize; | ||
375 | break; | 358 | break; |
376 | } | 359 | } |
377 | case OP_TAILCALL: { | 360 | case OP_TAILCALL: { |
@@ -425,31 +408,27 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
425 | break; | 408 | break; |
426 | } | 409 | } |
427 | case OP_GETTABLE: { | 410 | case OP_GETTABLE: { |
428 | luaV_gettable(L, top-2, top, top-2); | ||
429 | top--; | 411 | top--; |
412 | luaV_gettable(L, top-1, top, top-1); | ||
430 | break; | 413 | break; |
431 | } | 414 | } |
432 | case OP_GETDOTTED: { | 415 | case OP_GETDOTTED: { |
433 | setsvalue(top, kstr[GETARG_U(i)]); | 416 | setsvalue(top, kstr[GETARG_U(i)]); |
434 | luaV_gettable(L, top-1, top+1, top-1); | 417 | luaV_gettable(L, top-1, top, top-1); |
435 | break; | 418 | break; |
436 | } | 419 | } |
437 | case OP_GETINDEXED: { | 420 | case OP_GETINDEXED: { |
438 | setobj(top, base+GETARG_U(i)); | 421 | luaV_gettable(L, top-1, base+GETARG_U(i), top-1); |
439 | luaV_gettable(L, top-1, top+1, top-1); | ||
440 | break; | 422 | break; |
441 | } | 423 | } |
442 | case OP_PUSHSELF: { | 424 | case OP_PUSHSELF: { |
443 | TObject receiver; | 425 | setobj(top, top-1); |
444 | setobj(&receiver, top-1); | 426 | setsvalue(top+1, kstr[GETARG_U(i)]); |
445 | setsvalue(top, kstr[GETARG_U(i)]); | 427 | luaV_gettable(L, top-1, top+1, top-1); |
446 | top++; | 428 | top++; |
447 | luaV_gettable(L, top-2, top, top-2); | ||
448 | setobj(top-1, &receiver); | ||
449 | break; | 429 | break; |
450 | } | 430 | } |
451 | case OP_CREATETABLE: { | 431 | case OP_CREATETABLE: { |
452 | L->top = top; | ||
453 | luaC_checkGC(L); | 432 | luaC_checkGC(L); |
454 | sethvalue(top, luaH_new(L, GETARG_U(i))); | 433 | sethvalue(top, luaH_new(L, GETARG_U(i))); |
455 | top++; | 434 | top++; |
@@ -460,15 +439,13 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
460 | break; | 439 | break; |
461 | } | 440 | } |
462 | case OP_SETGLOBAL: { | 441 | case OP_SETGLOBAL: { |
463 | L->top = top; /* primitive set may generate an error */ | ||
464 | luaV_setglobal(L, kstr[GETARG_U(i)], top); | ||
465 | top--; | 442 | top--; |
443 | luaV_setglobal(L, kstr[GETARG_U(i)], top); | ||
466 | break; | 444 | break; |
467 | } | 445 | } |
468 | case OP_SETTABLE: { | 446 | case OP_SETTABLE: { |
469 | StkId t = top-GETARG_A(i); | 447 | StkId t = top-GETARG_A(i); |
470 | L->top = top; /* primitive set may generate an error */ | 448 | luaV_settable(L, t, t+1, top-1); |
471 | luaV_settable(L, t, t+1, top); | ||
472 | top -= GETARG_B(i); /* pop values */ | 449 | top -= GETARG_B(i); /* pop values */ |
473 | break; | 450 | break; |
474 | } | 451 | } |
@@ -476,16 +453,13 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
476 | int aux = GETARG_A(i) * LFIELDS_PER_FLUSH; | 453 | int aux = GETARG_A(i) * LFIELDS_PER_FLUSH; |
477 | int n = GETARG_B(i); | 454 | int n = GETARG_B(i); |
478 | Hash *arr = hvalue(top-n-1); | 455 | Hash *arr = hvalue(top-n-1); |
479 | L->top = top-n; | ||
480 | for (; n; n--) | 456 | for (; n; n--) |
481 | setobj(luaH_setnum(L, arr, n+aux), --top); | 457 | setobj(luaH_setnum(L, arr, n+aux), --top); |
482 | break; | 458 | break; |
483 | } | 459 | } |
484 | case OP_SETMAP: { | 460 | case OP_SETMAP: { |
485 | int n = GETARG_U(i); | 461 | int n = GETARG_U(i); |
486 | StkId finaltop = top-2*n; | 462 | Hash *arr = hvalue((top-2*n)-1); |
487 | Hash *arr = hvalue(finaltop-1); | ||
488 | L->top = finaltop; | ||
489 | for (; n; n--) { | 463 | for (; n; n--) { |
490 | top-=2; | 464 | top-=2; |
491 | setobj(luaH_set(L, arr, top), top+1); | 465 | setobj(luaH_set(L, arr, top), top+1); |
@@ -494,7 +468,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
494 | } | 468 | } |
495 | case OP_ADD: { | 469 | case OP_ADD: { |
496 | if (tonumber(top-2) || tonumber(top-1)) | 470 | if (tonumber(top-2) || tonumber(top-1)) |
497 | call_arith(L, top, TM_ADD); | 471 | call_arith(L, top-2, TM_ADD); |
498 | else | 472 | else |
499 | nvalue(top-2) += nvalue(top-1); | 473 | nvalue(top-2) += nvalue(top-1); |
500 | top--; | 474 | top--; |
@@ -503,7 +477,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
503 | case OP_ADDI: { | 477 | case OP_ADDI: { |
504 | if (tonumber(top-1)) { | 478 | if (tonumber(top-1)) { |
505 | setnvalue(top, (lua_Number)GETARG_S(i)); | 479 | setnvalue(top, (lua_Number)GETARG_S(i)); |
506 | call_arith(L, top+1, TM_ADD); | 480 | call_arith(L, top-1, TM_ADD); |
507 | } | 481 | } |
508 | else | 482 | else |
509 | nvalue(top-1) += (lua_Number)GETARG_S(i); | 483 | nvalue(top-1) += (lua_Number)GETARG_S(i); |
@@ -511,7 +485,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
511 | } | 485 | } |
512 | case OP_SUB: { | 486 | case OP_SUB: { |
513 | if (tonumber(top-2) || tonumber(top-1)) | 487 | if (tonumber(top-2) || tonumber(top-1)) |
514 | call_arith(L, top, TM_SUB); | 488 | call_arith(L, top-2, TM_SUB); |
515 | else | 489 | else |
516 | nvalue(top-2) -= nvalue(top-1); | 490 | nvalue(top-2) -= nvalue(top-1); |
517 | top--; | 491 | top--; |
@@ -519,7 +493,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
519 | } | 493 | } |
520 | case OP_MULT: { | 494 | case OP_MULT: { |
521 | if (tonumber(top-2) || tonumber(top-1)) | 495 | if (tonumber(top-2) || tonumber(top-1)) |
522 | call_arith(L, top, TM_MUL); | 496 | call_arith(L, top-2, TM_MUL); |
523 | else | 497 | else |
524 | nvalue(top-2) *= nvalue(top-1); | 498 | nvalue(top-2) *= nvalue(top-1); |
525 | top--; | 499 | top--; |
@@ -527,14 +501,14 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
527 | } | 501 | } |
528 | case OP_DIV: { | 502 | case OP_DIV: { |
529 | if (tonumber(top-2) || tonumber(top-1)) | 503 | if (tonumber(top-2) || tonumber(top-1)) |
530 | call_arith(L, top, TM_DIV); | 504 | call_arith(L, top-2, TM_DIV); |
531 | else | 505 | else |
532 | nvalue(top-2) /= nvalue(top-1); | 506 | nvalue(top-2) /= nvalue(top-1); |
533 | top--; | 507 | top--; |
534 | break; | 508 | break; |
535 | } | 509 | } |
536 | case OP_POW: { | 510 | case OP_POW: { |
537 | if (!call_binTM(L, top, TM_POW)) | 511 | if (!call_binTM(L, top-2, top-1, top-2, TM_POW)) |
538 | luaD_error(L, "undefined operation"); | 512 | luaD_error(L, "undefined operation"); |
539 | top--; | 513 | top--; |
540 | break; | 514 | break; |
@@ -543,14 +517,13 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
543 | int n = GETARG_U(i); | 517 | int n = GETARG_U(i); |
544 | luaV_strconc(L, n, top); | 518 | luaV_strconc(L, n, top); |
545 | top -= n-1; | 519 | top -= n-1; |
546 | L->top = top; | ||
547 | luaC_checkGC(L); | 520 | luaC_checkGC(L); |
548 | break; | 521 | break; |
549 | } | 522 | } |
550 | case OP_MINUS: { | 523 | case OP_MINUS: { |
551 | if (tonumber(top-1)) { | 524 | if (tonumber(top-1)) { |
552 | setnilvalue(top); | 525 | setnilvalue(top); |
553 | call_arith(L, top+1, TM_UNM); | 526 | call_arith(L, top-1, TM_UNM); |
554 | } | 527 | } |
555 | else | 528 | else |
556 | nvalue(top-1) = -nvalue(top-1); | 529 | nvalue(top-1) = -nvalue(top-1); |
@@ -574,22 +547,22 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
574 | } | 547 | } |
575 | case OP_JMPLT: { | 548 | case OP_JMPLT: { |
576 | top -= 2; | 549 | top -= 2; |
577 | if (luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i); | 550 | if (luaV_lessthan(L, top, top+1)) dojump(pc, i); |
578 | break; | 551 | break; |
579 | } | 552 | } |
580 | case OP_JMPLE: { /* a <= b === !(b<a) */ | 553 | case OP_JMPLE: { /* a <= b === !(b<a) */ |
581 | top -= 2; | 554 | top -= 2; |
582 | if (!luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i); | 555 | if (!luaV_lessthan(L, top+1, top)) dojump(pc, i); |
583 | break; | 556 | break; |
584 | } | 557 | } |
585 | case OP_JMPGT: { /* a > b === (b<a) */ | 558 | case OP_JMPGT: { /* a > b === (b<a) */ |
586 | top -= 2; | 559 | top -= 2; |
587 | if (luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i); | 560 | if (luaV_lessthan(L, top+1, top)) dojump(pc, i); |
588 | break; | 561 | break; |
589 | } | 562 | } |
590 | case OP_JMPGE: { /* a >= b === !(a<b) */ | 563 | case OP_JMPGE: { /* a >= b === !(a<b) */ |
591 | top -= 2; | 564 | top -= 2; |
592 | if (!luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i); | 565 | if (!luaV_lessthan(L, top, top+1)) dojump(pc, i); |
593 | break; | 566 | break; |
594 | } | 567 | } |
595 | case OP_JMPT: { | 568 | case OP_JMPT: { |
@@ -675,11 +648,11 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | |||
675 | } | 648 | } |
676 | case OP_CLOSURE: { | 649 | case OP_CLOSURE: { |
677 | int nup = GETARG_B(i); | 650 | int nup = GETARG_B(i); |
651 | luaC_checkGC(L); | ||
678 | L->top = top; | 652 | L->top = top; |
679 | luaV_Lclosure(L, tf->kproto[GETARG_A(i)], nup); | 653 | luaV_Lclosure(L, tf->kproto[GETARG_A(i)], nup); |
680 | top -= (nup-1); | 654 | top -= (nup-1); |
681 | lua_assert(top == L->top); | 655 | L->top = base+tf->maxstacksize; |
682 | luaC_checkGC(L); | ||
683 | break; | 656 | break; |
684 | } | 657 | } |
685 | } | 658 | } |