diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-12-27 11:02:25 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-12-27 11:02:25 -0200 |
commit | f5ae26ec6c2eb69f03f316e59c1e1977c52c7c23 (patch) | |
tree | b4c761dac7648caea2cc20f8ebc2dd5b27a3fa1e /lvm.c | |
parent | 98194db4295726069137d13b8d24fca8cbf892b6 (diff) | |
download | lua-f5ae26ec6c2eb69f03f316e59c1e1977c52c7c23.tar.gz lua-f5ae26ec6c2eb69f03f316e59c1e1977c52c7c23.tar.bz2 lua-f5ae26ec6c2eb69f03f316e59c1e1977c52c7c23.zip |
official branch for Lua 5.1
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 763 |
1 files changed, 0 insertions, 763 deletions
@@ -1,763 +0,0 @@ | |||
1 | /* | ||
2 | ** $Id: lvm.c,v 2.62 2006/01/23 19:51:43 roberto Exp roberto $ | ||
3 | ** Lua virtual machine | ||
4 | ** See Copyright Notice in lua.h | ||
5 | */ | ||
6 | |||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <stdlib.h> | ||
10 | #include <string.h> | ||
11 | |||
12 | #define lvm_c | ||
13 | #define LUA_CORE | ||
14 | |||
15 | #include "lua.h" | ||
16 | |||
17 | #include "ldebug.h" | ||
18 | #include "ldo.h" | ||
19 | #include "lfunc.h" | ||
20 | #include "lgc.h" | ||
21 | #include "lobject.h" | ||
22 | #include "lopcodes.h" | ||
23 | #include "lstate.h" | ||
24 | #include "lstring.h" | ||
25 | #include "ltable.h" | ||
26 | #include "ltm.h" | ||
27 | #include "lvm.h" | ||
28 | |||
29 | |||
30 | |||
31 | /* limit for table tag-method chains (to avoid loops) */ | ||
32 | #define MAXTAGLOOP 100 | ||
33 | |||
34 | |||
35 | const TValue *luaV_tonumber (const TValue *obj, TValue *n) { | ||
36 | lua_Number num; | ||
37 | if (ttisnumber(obj)) return obj; | ||
38 | if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { | ||
39 | setnvalue(n, num); | ||
40 | return n; | ||
41 | } | ||
42 | else | ||
43 | return NULL; | ||
44 | } | ||
45 | |||
46 | |||
47 | int luaV_tostring (lua_State *L, StkId obj) { | ||
48 | if (!ttisnumber(obj)) | ||
49 | return 0; | ||
50 | else { | ||
51 | char s[LUAI_MAXNUMBER2STR]; | ||
52 | lua_Number n = nvalue(obj); | ||
53 | lua_number2str(s, n); | ||
54 | setsvalue2s(L, obj, luaS_new(L, s)); | ||
55 | return 1; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | |||
60 | static void traceexec (lua_State *L, const Instruction *pc) { | ||
61 | lu_byte mask = L->hookmask; | ||
62 | const Instruction *oldpc = L->savedpc; | ||
63 | L->savedpc = pc; | ||
64 | if (mask > LUA_MASKLINE) { /* instruction-hook set? */ | ||
65 | if (L->hookcount == 0) { | ||
66 | resethookcount(L); | ||
67 | luaD_callhook(L, LUA_HOOKCOUNT, -1); | ||
68 | } | ||
69 | } | ||
70 | if (mask & LUA_MASKLINE) { | ||
71 | Proto *p = ci_func(L->ci)->l.p; | ||
72 | int npc = pcRel(pc, p); | ||
73 | int newline = getline(p, npc); | ||
74 | /* call linehook when enter a new function, when jump back (loop), | ||
75 | or when enter a new line */ | ||
76 | if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) | ||
77 | luaD_callhook(L, LUA_HOOKLINE, newline); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | |||
82 | static void callTMres (lua_State *L, StkId res, const TValue *f, | ||
83 | const TValue *p1, const TValue *p2) { | ||
84 | ptrdiff_t result = savestack(L, res); | ||
85 | setobj2s(L, L->top, f); /* push function */ | ||
86 | setobj2s(L, L->top+1, p1); /* 1st argument */ | ||
87 | setobj2s(L, L->top+2, p2); /* 2nd argument */ | ||
88 | luaD_checkstack(L, 3); | ||
89 | L->top += 3; | ||
90 | luaD_call(L, L->top - 3, 1); | ||
91 | res = restorestack(L, result); | ||
92 | L->top--; | ||
93 | setobjs2s(L, res, L->top); | ||
94 | } | ||
95 | |||
96 | |||
97 | |||
98 | static void callTM (lua_State *L, const TValue *f, const TValue *p1, | ||
99 | const TValue *p2, const TValue *p3) { | ||
100 | setobj2s(L, L->top, f); /* push function */ | ||
101 | setobj2s(L, L->top+1, p1); /* 1st argument */ | ||
102 | setobj2s(L, L->top+2, p2); /* 2nd argument */ | ||
103 | setobj2s(L, L->top+3, p3); /* 3th argument */ | ||
104 | luaD_checkstack(L, 4); | ||
105 | L->top += 4; | ||
106 | luaD_call(L, L->top - 4, 0); | ||
107 | } | ||
108 | |||
109 | |||
110 | void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | ||
111 | int loop; | ||
112 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | ||
113 | const TValue *tm; | ||
114 | if (ttistable(t)) { /* `t' is a table? */ | ||
115 | Table *h = hvalue(t); | ||
116 | const TValue *res = luaH_get(h, key); /* do a primitive get */ | ||
117 | if (!ttisnil(res) || /* result is no nil? */ | ||
118 | (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ | ||
119 | setobj2s(L, val, res); | ||
120 | return; | ||
121 | } | ||
122 | /* else will try the tag method */ | ||
123 | } | ||
124 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) | ||
125 | luaG_typeerror(L, t, "index"); | ||
126 | if (ttisfunction(tm)) { | ||
127 | callTMres(L, val, tm, t, key); | ||
128 | return; | ||
129 | } | ||
130 | t = tm; /* else repeat with `tm' */ | ||
131 | } | ||
132 | luaG_runerror(L, "loop in gettable"); | ||
133 | } | ||
134 | |||
135 | |||
136 | void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | ||
137 | int loop; | ||
138 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | ||
139 | const TValue *tm; | ||
140 | if (ttistable(t)) { /* `t' is a table? */ | ||
141 | Table *h = hvalue(t); | ||
142 | TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ | ||
143 | if (!ttisnil(oldval) || /* result is no nil? */ | ||
144 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ | ||
145 | setobj2t(L, oldval, val); | ||
146 | luaC_barriert(L, h, val); | ||
147 | return; | ||
148 | } | ||
149 | /* else will try the tag method */ | ||
150 | } | ||
151 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) | ||
152 | luaG_typeerror(L, t, "index"); | ||
153 | if (ttisfunction(tm)) { | ||
154 | callTM(L, tm, t, key, val); | ||
155 | return; | ||
156 | } | ||
157 | t = tm; /* else repeat with `tm' */ | ||
158 | } | ||
159 | luaG_runerror(L, "loop in settable"); | ||
160 | } | ||
161 | |||
162 | |||
163 | static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, | ||
164 | StkId res, TMS event) { | ||
165 | const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ | ||
166 | if (ttisnil(tm)) | ||
167 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ | ||
168 | if (!ttisfunction(tm)) return 0; | ||
169 | callTMres(L, res, tm, p1, p2); | ||
170 | return 1; | ||
171 | } | ||
172 | |||
173 | |||
174 | static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, | ||
175 | TMS event) { | ||
176 | const TValue *tm1 = fasttm(L, mt1, event); | ||
177 | const TValue *tm2; | ||
178 | if (tm1 == NULL) return NULL; /* no metamethod */ | ||
179 | if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ | ||
180 | tm2 = fasttm(L, mt2, event); | ||
181 | if (tm2 == NULL) return NULL; /* no metamethod */ | ||
182 | if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ | ||
183 | return tm1; | ||
184 | return NULL; | ||
185 | } | ||
186 | |||
187 | |||
188 | static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, | ||
189 | TMS event) { | ||
190 | const TValue *tm1 = luaT_gettmbyobj(L, p1, event); | ||
191 | const TValue *tm2; | ||
192 | if (ttisnil(tm1)) return -1; /* no metamethod? */ | ||
193 | tm2 = luaT_gettmbyobj(L, p2, event); | ||
194 | if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ | ||
195 | return -1; | ||
196 | callTMres(L, L->top, tm1, p1, p2); | ||
197 | return !l_isfalse(L->top); | ||
198 | } | ||
199 | |||
200 | |||
201 | static int l_strcmp (const TString *ls, const TString *rs) { | ||
202 | const char *l = getstr(ls); | ||
203 | size_t ll = ls->tsv.len; | ||
204 | const char *r = getstr(rs); | ||
205 | size_t lr = rs->tsv.len; | ||
206 | for (;;) { | ||
207 | int temp = strcoll(l, r); | ||
208 | if (temp != 0) return temp; | ||
209 | else { /* strings are equal up to a `\0' */ | ||
210 | size_t len = strlen(l); /* index of first `\0' in both strings */ | ||
211 | if (len == lr) /* r is finished? */ | ||
212 | return (len == ll) ? 0 : 1; | ||
213 | else if (len == ll) /* l is finished? */ | ||
214 | return -1; /* l is smaller than r (because r is not finished) */ | ||
215 | /* both strings longer than `len'; go on comparing (after the `\0') */ | ||
216 | len++; | ||
217 | l += len; ll -= len; r += len; lr -= len; | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | |||
222 | |||
223 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { | ||
224 | int res; | ||
225 | if (ttype(l) != ttype(r)) | ||
226 | return luaG_ordererror(L, l, r); | ||
227 | else if (ttisnumber(l)) | ||
228 | return luai_numlt(nvalue(l), nvalue(r)); | ||
229 | else if (ttisstring(l)) | ||
230 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; | ||
231 | else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) | ||
232 | return res; | ||
233 | return luaG_ordererror(L, l, r); | ||
234 | } | ||
235 | |||
236 | |||
237 | static int lessequal (lua_State *L, const TValue *l, const TValue *r) { | ||
238 | int res; | ||
239 | if (ttype(l) != ttype(r)) | ||
240 | return luaG_ordererror(L, l, r); | ||
241 | else if (ttisnumber(l)) | ||
242 | return luai_numle(nvalue(l), nvalue(r)); | ||
243 | else if (ttisstring(l)) | ||
244 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; | ||
245 | else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ | ||
246 | return res; | ||
247 | else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ | ||
248 | return !res; | ||
249 | return luaG_ordererror(L, l, r); | ||
250 | } | ||
251 | |||
252 | |||
253 | int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { | ||
254 | const TValue *tm; | ||
255 | lua_assert(ttype(t1) == ttype(t2)); | ||
256 | switch (ttype(t1)) { | ||
257 | case LUA_TNIL: return 1; | ||
258 | case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); | ||
259 | case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ | ||
260 | case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); | ||
261 | case LUA_TUSERDATA: { | ||
262 | if (uvalue(t1) == uvalue(t2)) return 1; | ||
263 | tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, | ||
264 | TM_EQ); | ||
265 | break; /* will try TM */ | ||
266 | } | ||
267 | case LUA_TTABLE: { | ||
268 | if (hvalue(t1) == hvalue(t2)) return 1; | ||
269 | tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); | ||
270 | break; /* will try TM */ | ||
271 | } | ||
272 | default: return gcvalue(t1) == gcvalue(t2); | ||
273 | } | ||
274 | if (tm == NULL) return 0; /* no TM? */ | ||
275 | callTMres(L, L->top, tm, t1, t2); /* call TM */ | ||
276 | return !l_isfalse(L->top); | ||
277 | } | ||
278 | |||
279 | |||
280 | void luaV_concat (lua_State *L, int total, int last) { | ||
281 | do { | ||
282 | StkId top = L->base + last + 1; | ||
283 | int n = 2; /* number of elements handled in this pass (at least 2) */ | ||
284 | if (!tostring(L, top-2) || !tostring(L, top-1)) { | ||
285 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) | ||
286 | luaG_concaterror(L, top-2, top-1); | ||
287 | } else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ | ||
288 | /* at least two string values; get as many as possible */ | ||
289 | size_t tl = tsvalue(top-1)->len; | ||
290 | char *buffer; | ||
291 | int i; | ||
292 | /* collect total length */ | ||
293 | for (n = 1; n < total && tostring(L, top-n-1); n++) { | ||
294 | size_t l = tsvalue(top-n-1)->len; | ||
295 | if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); | ||
296 | tl += l; | ||
297 | } | ||
298 | buffer = luaZ_openspace(L, &G(L)->buff, tl); | ||
299 | tl = 0; | ||
300 | for (i=n; i>0; i--) { /* concat all strings */ | ||
301 | size_t l = tsvalue(top-i)->len; | ||
302 | memcpy(buffer+tl, svalue(top-i), l); | ||
303 | tl += l; | ||
304 | } | ||
305 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); | ||
306 | } | ||
307 | total -= n-1; /* got `n' strings to create 1 new */ | ||
308 | last -= n-1; | ||
309 | } while (total > 1); /* repeat until only 1 result left */ | ||
310 | } | ||
311 | |||
312 | |||
313 | static void Arith (lua_State *L, StkId ra, const TValue *rb, | ||
314 | const TValue *rc, TMS op) { | ||
315 | TValue tempb, tempc; | ||
316 | const TValue *b, *c; | ||
317 | if ((b = luaV_tonumber(rb, &tempb)) != NULL && | ||
318 | (c = luaV_tonumber(rc, &tempc)) != NULL) { | ||
319 | lua_Number nb = nvalue(b), nc = nvalue(c); | ||
320 | switch (op) { | ||
321 | case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; | ||
322 | case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; | ||
323 | case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; | ||
324 | case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; | ||
325 | case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; | ||
326 | case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; | ||
327 | case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; | ||
328 | default: lua_assert(0); break; | ||
329 | } | ||
330 | } | ||
331 | else if (!call_binTM(L, rb, rc, ra, op)) | ||
332 | luaG_aritherror(L, rb, rc); | ||
333 | } | ||
334 | |||
335 | |||
336 | |||
337 | /* | ||
338 | ** some macros for common tasks in `luaV_execute' | ||
339 | */ | ||
340 | |||
341 | #define runtime_check(L, c) { if (!(c)) break; } | ||
342 | |||
343 | #define RA(i) (base+GETARG_A(i)) | ||
344 | /* to be used after possible stack reallocation */ | ||
345 | #define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) | ||
346 | #define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) | ||
347 | #define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ | ||
348 | ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) | ||
349 | #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ | ||
350 | ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) | ||
351 | #define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) | ||
352 | |||
353 | |||
354 | #define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} | ||
355 | |||
356 | |||
357 | #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } | ||
358 | |||
359 | |||
360 | #define arith_op(op,tm) { \ | ||
361 | TValue *rb = RKB(i); \ | ||
362 | TValue *rc = RKC(i); \ | ||
363 | if (ttisnumber(rb) && ttisnumber(rc)) { \ | ||
364 | lua_Number nb = nvalue(rb), nc = nvalue(rc); \ | ||
365 | setnvalue(ra, op(nb, nc)); \ | ||
366 | } \ | ||
367 | else \ | ||
368 | Protect(Arith(L, ra, rb, rc, tm)); \ | ||
369 | } | ||
370 | |||
371 | |||
372 | |||
373 | void luaV_execute (lua_State *L, int nexeccalls) { | ||
374 | LClosure *cl; | ||
375 | StkId base; | ||
376 | TValue *k; | ||
377 | const Instruction *pc; | ||
378 | reentry: /* entry point */ | ||
379 | lua_assert(isLua(L->ci)); | ||
380 | pc = L->savedpc; | ||
381 | cl = &clvalue(L->ci->func)->l; | ||
382 | base = L->base; | ||
383 | k = cl->p->k; | ||
384 | /* main loop of interpreter */ | ||
385 | for (;;) { | ||
386 | const Instruction i = *pc++; | ||
387 | StkId ra; | ||
388 | if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && | ||
389 | (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { | ||
390 | traceexec(L, pc); | ||
391 | if (L->status == LUA_YIELD) { /* did hook yield? */ | ||
392 | L->savedpc = pc - 1; | ||
393 | return; | ||
394 | } | ||
395 | base = L->base; | ||
396 | } | ||
397 | /* warning!! several calls may realloc the stack and invalidate `ra' */ | ||
398 | ra = RA(i); | ||
399 | lua_assert(base == L->base && L->base == L->ci->base); | ||
400 | lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); | ||
401 | lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); | ||
402 | switch (GET_OPCODE(i)) { | ||
403 | case OP_MOVE: { | ||
404 | setobjs2s(L, ra, RB(i)); | ||
405 | continue; | ||
406 | } | ||
407 | case OP_LOADK: { | ||
408 | setobj2s(L, ra, KBx(i)); | ||
409 | continue; | ||
410 | } | ||
411 | case OP_LOADBOOL: { | ||
412 | setbvalue(ra, GETARG_B(i)); | ||
413 | if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ | ||
414 | continue; | ||
415 | } | ||
416 | case OP_LOADNIL: { | ||
417 | TValue *rb = RB(i); | ||
418 | do { | ||
419 | setnilvalue(rb--); | ||
420 | } while (rb >= ra); | ||
421 | continue; | ||
422 | } | ||
423 | case OP_GETUPVAL: { | ||
424 | int b = GETARG_B(i); | ||
425 | setobj2s(L, ra, cl->upvals[b]->v); | ||
426 | continue; | ||
427 | } | ||
428 | case OP_GETGLOBAL: { | ||
429 | TValue g; | ||
430 | TValue *rb = KBx(i); | ||
431 | sethvalue(L, &g, cl->env); | ||
432 | lua_assert(ttisstring(rb)); | ||
433 | Protect(luaV_gettable(L, &g, rb, ra)); | ||
434 | continue; | ||
435 | } | ||
436 | case OP_GETTABLE: { | ||
437 | Protect(luaV_gettable(L, RB(i), RKC(i), ra)); | ||
438 | continue; | ||
439 | } | ||
440 | case OP_SETGLOBAL: { | ||
441 | TValue g; | ||
442 | sethvalue(L, &g, cl->env); | ||
443 | lua_assert(ttisstring(KBx(i))); | ||
444 | Protect(luaV_settable(L, &g, KBx(i), ra)); | ||
445 | continue; | ||
446 | } | ||
447 | case OP_SETUPVAL: { | ||
448 | UpVal *uv = cl->upvals[GETARG_B(i)]; | ||
449 | setobj(L, uv->v, ra); | ||
450 | luaC_barrier(L, uv, ra); | ||
451 | continue; | ||
452 | } | ||
453 | case OP_SETTABLE: { | ||
454 | Protect(luaV_settable(L, ra, RKB(i), RKC(i))); | ||
455 | continue; | ||
456 | } | ||
457 | case OP_NEWTABLE: { | ||
458 | int b = GETARG_B(i); | ||
459 | int c = GETARG_C(i); | ||
460 | sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); | ||
461 | Protect(luaC_checkGC(L)); | ||
462 | continue; | ||
463 | } | ||
464 | case OP_SELF: { | ||
465 | StkId rb = RB(i); | ||
466 | setobjs2s(L, ra+1, rb); | ||
467 | Protect(luaV_gettable(L, rb, RKC(i), ra)); | ||
468 | continue; | ||
469 | } | ||
470 | case OP_ADD: { | ||
471 | arith_op(luai_numadd, TM_ADD); | ||
472 | continue; | ||
473 | } | ||
474 | case OP_SUB: { | ||
475 | arith_op(luai_numsub, TM_SUB); | ||
476 | continue; | ||
477 | } | ||
478 | case OP_MUL: { | ||
479 | arith_op(luai_nummul, TM_MUL); | ||
480 | continue; | ||
481 | } | ||
482 | case OP_DIV: { | ||
483 | arith_op(luai_numdiv, TM_DIV); | ||
484 | continue; | ||
485 | } | ||
486 | case OP_MOD: { | ||
487 | arith_op(luai_nummod, TM_MOD); | ||
488 | continue; | ||
489 | } | ||
490 | case OP_POW: { | ||
491 | arith_op(luai_numpow, TM_POW); | ||
492 | continue; | ||
493 | } | ||
494 | case OP_UNM: { | ||
495 | TValue *rb = RB(i); | ||
496 | if (ttisnumber(rb)) { | ||
497 | lua_Number nb = nvalue(rb); | ||
498 | setnvalue(ra, luai_numunm(nb)); | ||
499 | } | ||
500 | else { | ||
501 | Protect(Arith(L, ra, rb, rb, TM_UNM)); | ||
502 | } | ||
503 | continue; | ||
504 | } | ||
505 | case OP_NOT: { | ||
506 | int res = l_isfalse(RB(i)); /* next assignment may change this value */ | ||
507 | setbvalue(ra, res); | ||
508 | continue; | ||
509 | } | ||
510 | case OP_LEN: { | ||
511 | const TValue *rb = RB(i); | ||
512 | switch (ttype(rb)) { | ||
513 | case LUA_TTABLE: { | ||
514 | setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); | ||
515 | break; | ||
516 | } | ||
517 | case LUA_TSTRING: { | ||
518 | setnvalue(ra, cast_num(tsvalue(rb)->len)); | ||
519 | break; | ||
520 | } | ||
521 | default: { /* try metamethod */ | ||
522 | Protect( | ||
523 | if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) | ||
524 | luaG_typeerror(L, rb, "get length of"); | ||
525 | ) | ||
526 | } | ||
527 | } | ||
528 | continue; | ||
529 | } | ||
530 | case OP_CONCAT: { | ||
531 | int b = GETARG_B(i); | ||
532 | int c = GETARG_C(i); | ||
533 | Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); | ||
534 | setobjs2s(L, RA(i), base+b); | ||
535 | continue; | ||
536 | } | ||
537 | case OP_JMP: { | ||
538 | dojump(L, pc, GETARG_sBx(i)); | ||
539 | continue; | ||
540 | } | ||
541 | case OP_EQ: { | ||
542 | TValue *rb = RKB(i); | ||
543 | TValue *rc = RKC(i); | ||
544 | Protect( | ||
545 | if (equalobj(L, rb, rc) == GETARG_A(i)) | ||
546 | dojump(L, pc, GETARG_sBx(*pc)); | ||
547 | ) | ||
548 | pc++; | ||
549 | continue; | ||
550 | } | ||
551 | case OP_LT: { | ||
552 | Protect( | ||
553 | if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) | ||
554 | dojump(L, pc, GETARG_sBx(*pc)); | ||
555 | ) | ||
556 | pc++; | ||
557 | continue; | ||
558 | } | ||
559 | case OP_LE: { | ||
560 | Protect( | ||
561 | if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) | ||
562 | dojump(L, pc, GETARG_sBx(*pc)); | ||
563 | ) | ||
564 | pc++; | ||
565 | continue; | ||
566 | } | ||
567 | case OP_TEST: { | ||
568 | if (l_isfalse(ra) != GETARG_C(i)) | ||
569 | dojump(L, pc, GETARG_sBx(*pc)); | ||
570 | pc++; | ||
571 | continue; | ||
572 | } | ||
573 | case OP_TESTSET: { | ||
574 | TValue *rb = RB(i); | ||
575 | if (l_isfalse(rb) != GETARG_C(i)) { | ||
576 | setobjs2s(L, ra, rb); | ||
577 | dojump(L, pc, GETARG_sBx(*pc)); | ||
578 | } | ||
579 | pc++; | ||
580 | continue; | ||
581 | } | ||
582 | case OP_CALL: { | ||
583 | int b = GETARG_B(i); | ||
584 | int nresults = GETARG_C(i) - 1; | ||
585 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | ||
586 | L->savedpc = pc; | ||
587 | switch (luaD_precall(L, ra, nresults)) { | ||
588 | case PCRLUA: { | ||
589 | nexeccalls++; | ||
590 | goto reentry; /* restart luaV_execute over new Lua function */ | ||
591 | } | ||
592 | case PCRC: { | ||
593 | /* it was a C function (`precall' called it); adjust results */ | ||
594 | if (nresults >= 0) L->top = L->ci->top; | ||
595 | base = L->base; | ||
596 | continue; | ||
597 | } | ||
598 | default: { | ||
599 | return; /* yield */ | ||
600 | } | ||
601 | } | ||
602 | } | ||
603 | case OP_TAILCALL: { | ||
604 | int b = GETARG_B(i); | ||
605 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | ||
606 | L->savedpc = pc; | ||
607 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); | ||
608 | switch (luaD_precall(L, ra, LUA_MULTRET)) { | ||
609 | case PCRLUA: { | ||
610 | /* tail call: put new frame in place of previous one */ | ||
611 | CallInfo *ci = L->ci - 1; /* previous frame */ | ||
612 | int aux; | ||
613 | StkId func = ci->func; | ||
614 | StkId pfunc = (ci+1)->func; /* previous function index */ | ||
615 | if (L->openupval) luaF_close(L, ci->base); | ||
616 | L->base = ci->base = ci->func + ((ci+1)->base - pfunc); | ||
617 | for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ | ||
618 | setobjs2s(L, func+aux, pfunc+aux); | ||
619 | ci->top = L->top = func+aux; /* correct top */ | ||
620 | lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); | ||
621 | ci->savedpc = L->savedpc; | ||
622 | ci->tailcalls++; /* one more call lost */ | ||
623 | L->ci--; /* remove new frame */ | ||
624 | goto reentry; | ||
625 | } | ||
626 | case PCRC: { /* it was a C function (`precall' called it) */ | ||
627 | base = L->base; | ||
628 | continue; | ||
629 | } | ||
630 | default: { | ||
631 | return; /* yield */ | ||
632 | } | ||
633 | } | ||
634 | } | ||
635 | case OP_RETURN: { | ||
636 | int b = GETARG_B(i); | ||
637 | if (b != 0) L->top = ra+b-1; | ||
638 | if (L->openupval) luaF_close(L, base); | ||
639 | L->savedpc = pc; | ||
640 | b = luaD_poscall(L, ra); | ||
641 | if (--nexeccalls == 0) /* was previous function running `here'? */ | ||
642 | return; /* no: return */ | ||
643 | else { /* yes: continue its execution */ | ||
644 | if (b) L->top = L->ci->top; | ||
645 | lua_assert(isLua(L->ci)); | ||
646 | lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); | ||
647 | goto reentry; | ||
648 | } | ||
649 | } | ||
650 | case OP_FORLOOP: { | ||
651 | lua_Number step = nvalue(ra+2); | ||
652 | lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ | ||
653 | lua_Number limit = nvalue(ra+1); | ||
654 | if (luai_numlt(0, step) ? luai_numle(idx, limit) | ||
655 | : luai_numle(limit, idx)) { | ||
656 | dojump(L, pc, GETARG_sBx(i)); /* jump back */ | ||
657 | setnvalue(ra, idx); /* update internal index... */ | ||
658 | setnvalue(ra+3, idx); /* ...and external index */ | ||
659 | } | ||
660 | continue; | ||
661 | } | ||
662 | case OP_FORPREP: { | ||
663 | const TValue *init = ra; | ||
664 | const TValue *plimit = ra+1; | ||
665 | const TValue *pstep = ra+2; | ||
666 | L->savedpc = pc; /* next steps may throw errors */ | ||
667 | if (!tonumber(init, ra)) | ||
668 | luaG_runerror(L, LUA_QL("for") " initial value must be a number"); | ||
669 | else if (!tonumber(plimit, ra+1)) | ||
670 | luaG_runerror(L, LUA_QL("for") " limit must be a number"); | ||
671 | else if (!tonumber(pstep, ra+2)) | ||
672 | luaG_runerror(L, LUA_QL("for") " step must be a number"); | ||
673 | setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); | ||
674 | dojump(L, pc, GETARG_sBx(i)); | ||
675 | continue; | ||
676 | } | ||
677 | case OP_TFORLOOP: { | ||
678 | StkId cb = ra + 3; /* call base */ | ||
679 | setobjs2s(L, cb+2, ra+2); | ||
680 | setobjs2s(L, cb+1, ra+1); | ||
681 | setobjs2s(L, cb, ra); | ||
682 | L->top = cb+3; /* func. + 2 args (state and index) */ | ||
683 | Protect(luaD_call(L, cb, GETARG_C(i))); | ||
684 | L->top = L->ci->top; | ||
685 | cb = RA(i) + 3; /* previous call may change the stack */ | ||
686 | if (!ttisnil(cb)) { /* continue loop? */ | ||
687 | setobjs2s(L, cb-1, cb); /* save control variable */ | ||
688 | dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ | ||
689 | } | ||
690 | pc++; | ||
691 | continue; | ||
692 | } | ||
693 | case OP_SETLIST: { | ||
694 | int n = GETARG_B(i); | ||
695 | int c = GETARG_C(i); | ||
696 | int last; | ||
697 | Table *h; | ||
698 | if (n == 0) { | ||
699 | n = cast_int(L->top - ra) - 1; | ||
700 | L->top = L->ci->top; | ||
701 | } | ||
702 | if (c == 0) c = cast_int(*pc++); | ||
703 | runtime_check(L, ttistable(ra)); | ||
704 | h = hvalue(ra); | ||
705 | last = ((c-1)*LFIELDS_PER_FLUSH) + n; | ||
706 | if (last > h->sizearray) /* needs more space? */ | ||
707 | luaH_resizearray(L, h, last); /* pre-alloc it at once */ | ||
708 | for (; n > 0; n--) { | ||
709 | TValue *val = ra+n; | ||
710 | setobj2t(L, luaH_setnum(L, h, last--), val); | ||
711 | luaC_barriert(L, h, val); | ||
712 | } | ||
713 | continue; | ||
714 | } | ||
715 | case OP_CLOSE: { | ||
716 | luaF_close(L, ra); | ||
717 | continue; | ||
718 | } | ||
719 | case OP_CLOSURE: { | ||
720 | Proto *p; | ||
721 | Closure *ncl; | ||
722 | int nup, j; | ||
723 | p = cl->p->p[GETARG_Bx(i)]; | ||
724 | nup = p->nups; | ||
725 | ncl = luaF_newLclosure(L, nup, cl->env); | ||
726 | ncl->l.p = p; | ||
727 | for (j=0; j<nup; j++, pc++) { | ||
728 | if (GET_OPCODE(*pc) == OP_GETUPVAL) | ||
729 | ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; | ||
730 | else { | ||
731 | lua_assert(GET_OPCODE(*pc) == OP_MOVE); | ||
732 | ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); | ||
733 | } | ||
734 | } | ||
735 | setclvalue(L, ra, ncl); | ||
736 | Protect(luaC_checkGC(L)); | ||
737 | continue; | ||
738 | } | ||
739 | case OP_VARARG: { | ||
740 | int b = GETARG_B(i) - 1; | ||
741 | int j; | ||
742 | CallInfo *ci = L->ci; | ||
743 | int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; | ||
744 | if (b == LUA_MULTRET) { | ||
745 | Protect(luaD_checkstack(L, n)); | ||
746 | ra = RA(i); /* previous call may change the stack */ | ||
747 | b = n; | ||
748 | L->top = ra + n; | ||
749 | } | ||
750 | for (j = 0; j < b; j++) { | ||
751 | if (j < n) { | ||
752 | setobjs2s(L, ra + j, ci->base - n + j); | ||
753 | } | ||
754 | else { | ||
755 | setnilvalue(ra + j); | ||
756 | } | ||
757 | } | ||
758 | continue; | ||
759 | } | ||
760 | } | ||
761 | } | ||
762 | } | ||
763 | |||