rpm
4.5
|
00001 /* 00002 ** $Id: lvm.c,v 1.2 2004/03/19 21:14:32 niemeyer Exp $ 00003 ** Lua virtual machine 00004 ** See Copyright Notice in lua.h 00005 */ 00006 00007 00008 #include <stdarg.h> 00009 #include <stdlib.h> 00010 #include <string.h> 00011 00012 /* needed only when `lua_number2str' uses `sprintf' */ 00013 #include <stdio.h> 00014 00015 #define lvm_c 00016 00017 #include "lua.h" 00018 00019 #include "ldebug.h" 00020 #include "ldo.h" 00021 #include "lfunc.h" 00022 #include "lgc.h" 00023 #include "lobject.h" 00024 #include "lopcodes.h" 00025 #include "lstate.h" 00026 #include "lstring.h" 00027 #include "ltable.h" 00028 #include "ltm.h" 00029 #include "lvm.h" 00030 00031 00032 00033 /* function to convert a lua_Number to a string */ 00034 #ifndef lua_number2str 00035 #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) 00036 #endif 00037 00038 00039 /* limit for table tag-method chains (to avoid loops) */ 00040 #define MAXTAGLOOP 100 00041 00042 00043 const TObject *luaV_tonumber (const TObject *obj, TObject *n) { 00044 lua_Number num; 00045 if (ttisnumber(obj)) return obj; 00046 if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { 00047 setnvalue(n, num); 00048 return n; 00049 } 00050 else 00051 return NULL; 00052 } 00053 00054 00055 int luaV_tostring (lua_State *L, StkId obj) { 00056 if (!ttisnumber(obj)) 00057 return 0; 00058 else { 00059 char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */ 00060 lua_number2str(s, nvalue(obj)); 00061 setsvalue2s(obj, luaS_new(L, s)); 00062 return 1; 00063 } 00064 } 00065 00066 00067 static void traceexec (lua_State *L) 00068 /*@modifies L @*/ 00069 { 00070 lu_byte mask = L->hookmask; 00071 if (mask & LUA_MASKCOUNT) { /* instruction-hook set? */ 00072 if (L->hookcount == 0) { 00073 resethookcount(L); 00074 luaD_callhook(L, LUA_HOOKCOUNT, -1); 00075 return; 00076 } 00077 } 00078 if (mask & LUA_MASKLINE) { 00079 CallInfo *ci = L->ci; 00080 Proto *p = ci_func(ci)->l.p; 00081 int newline = getline(p, pcRel(*ci->u.l.pc, p)); 00082 if (!L->hookinit) { 00083 luaG_inithooks(L); 00084 return; 00085 } 00086 lua_assert(ci->state & CI_HASFRAME); 00087 if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */ 00088 ci->u.l.savedpc = *ci->u.l.pc; /* initialize `savedpc' */ 00089 /* calls linehook when enters a new line or jumps back (loop) */ 00090 if (*ci->u.l.pc <= ci->u.l.savedpc || 00091 newline != getline(p, pcRel(ci->u.l.savedpc, p))) { 00092 luaD_callhook(L, LUA_HOOKLINE, newline); 00093 ci = L->ci; /* previous call may reallocate `ci' */ 00094 } 00095 ci->u.l.savedpc = *ci->u.l.pc; 00096 } 00097 } 00098 00099 00100 static void callTMres (lua_State *L, const TObject *f, 00101 const TObject *p1, const TObject *p2) 00102 /*@modifies L @*/ 00103 { 00104 setobj2s(L->top, f); /* push function */ 00105 setobj2s(L->top+1, p1); /* 1st argument */ 00106 setobj2s(L->top+2, p2); /* 2nd argument */ 00107 luaD_checkstack(L, 3); /* cannot check before (could invalidate p1, p2) */ 00108 L->top += 3; 00109 luaD_call(L, L->top - 3, 1); 00110 L->top--; /* result will be in L->top */ 00111 } 00112 00113 00114 00115 static void callTM (lua_State *L, const TObject *f, 00116 const TObject *p1, const TObject *p2, const TObject *p3) 00117 /*@modifies L @*/ 00118 { 00119 setobj2s(L->top, f); /* push function */ 00120 setobj2s(L->top+1, p1); /* 1st argument */ 00121 setobj2s(L->top+2, p2); /* 2nd argument */ 00122 setobj2s(L->top+3, p3); /* 3th argument */ 00123 luaD_checkstack(L, 4); /* cannot check before (could invalidate p1...p3) */ 00124 L->top += 4; 00125 luaD_call(L, L->top - 4, 0); 00126 } 00127 00128 00129 /*@observer@*/ 00130 static const TObject *luaV_index (lua_State *L, const TObject *t, 00131 TObject *key, int loop) 00132 /*@modifies L, t @*/ 00133 { 00134 const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); 00135 if (tm == NULL) return &luaO_nilobject; /* no TM */ 00136 if (ttisfunction(tm)) { 00137 callTMres(L, tm, t, key); 00138 return L->top; 00139 } 00140 else return luaV_gettable(L, tm, key, loop); 00141 } 00142 00143 /*@observer@*/ 00144 static const TObject *luaV_getnotable (lua_State *L, const TObject *t, 00145 TObject *key, int loop) 00146 /*@modifies L @*/ 00147 { 00148 const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX); 00149 if (ttisnil(tm)) 00150 luaG_typeerror(L, t, "index"); 00151 if (ttisfunction(tm)) { 00152 callTMres(L, tm, t, key); 00153 return L->top; 00154 } 00155 /*@-modobserver@*/ 00156 else return luaV_gettable(L, tm, key, loop); 00157 /*@=modobserver@*/ 00158 } 00159 00160 00161 /* 00162 ** Function to index a table. 00163 ** Receives the table at `t' and the key at `key'. 00164 ** leaves the result at `res'. 00165 */ 00166 const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key, 00167 int loop) { 00168 if (loop > MAXTAGLOOP) 00169 luaG_runerror(L, "loop in gettable"); 00170 if (ttistable(t)) { /* `t' is a table? */ 00171 Table *h = hvalue(t); 00172 const TObject *v = luaH_get(h, key); /* do a primitive get */ 00173 if (!ttisnil(v)) return v; 00174 else return luaV_index(L, t, key, loop+1); 00175 } 00176 else return luaV_getnotable(L, t, key, loop+1); 00177 } 00178 00179 00180 /* 00181 ** Receives table at `t', key at `key' and value at `val'. 00182 */ 00183 void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) { 00184 const TObject *tm; 00185 int loop = 0; 00186 do { 00187 if (ttistable(t)) { /* `t' is a table? */ 00188 Table *h = hvalue(t); 00189 TObject *oldval = luaH_set(L, h, key); /* do a primitive set */ 00190 if (!ttisnil(oldval) || /* result is no nil? */ 00191 (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ 00192 setobj2t(oldval, val); /* write barrier */ 00193 return; 00194 } 00195 /* else will try the tag method */ 00196 } 00197 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) 00198 luaG_typeerror(L, t, "index"); 00199 if (ttisfunction(tm)) { 00200 callTM(L, tm, t, key, val); 00201 return; 00202 } 00203 t = tm; /* else repeat with `tm' */ 00204 } while (++loop <= MAXTAGLOOP); 00205 luaG_runerror(L, "loop in settable"); 00206 } 00207 00208 00209 static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, 00210 StkId res, TMS event) 00211 /*@modifies L @*/ 00212 { 00213 ptrdiff_t result = savestack(L, res); 00214 const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ 00215 if (ttisnil(tm)) 00216 tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ 00217 if (!ttisfunction(tm)) return 0; 00218 callTMres(L, tm, p1, p2); 00219 res = restorestack(L, result); /* previous call may change stack */ 00220 setobjs2s(res, L->top); 00221 return 1; 00222 } 00223 00224 00225 /*@null@*/ 00226 static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2, 00227 TMS event) 00228 /*@modifies mt1, mt2 @*/ 00229 { 00230 const TObject *tm1 = fasttm(L, mt1, event); 00231 const TObject *tm2; 00232 if (tm1 == NULL) return NULL; /* no metamethod */ 00233 if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ 00234 tm2 = fasttm(L, mt2, event); 00235 if (tm2 == NULL) return NULL; /* no metamethod */ 00236 if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ 00237 return tm1; 00238 return NULL; 00239 } 00240 00241 00242 static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2, 00243 TMS event) 00244 /*@modifies L @*/ 00245 { 00246 const TObject *tm1 = luaT_gettmbyobj(L, p1, event); 00247 const TObject *tm2; 00248 if (ttisnil(tm1)) return -1; /* no metamethod? */ 00249 tm2 = luaT_gettmbyobj(L, p2, event); 00250 if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ 00251 return -1; 00252 callTMres(L, tm1, p1, p2); 00253 return !l_isfalse(L->top); 00254 } 00255 00256 00257 static int luaV_strcmp (const TString *ls, const TString *rs) 00258 /*@*/ 00259 { 00260 const char *l = getstr(ls); 00261 size_t ll = ls->tsv.len; 00262 const char *r = getstr(rs); 00263 size_t lr = rs->tsv.len; 00264 for (;;) { 00265 int temp = strcoll(l, r); 00266 if (temp != 0) return temp; 00267 else { /* strings are equal up to a `\0' */ 00268 size_t len = strlen(l); /* index of first `\0' in both strings */ 00269 if (len == lr) /* r is finished? */ 00270 return (len == ll) ? 0 : 1; 00271 else if (len == ll) /* l is finished? */ 00272 return -1; /* l is smaller than r (because r is not finished) */ 00273 /* both strings longer than `len'; go on comparing (after the `\0') */ 00274 len++; 00275 l += len; ll -= len; r += len; lr -= len; 00276 } 00277 } 00278 } 00279 00280 00281 int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { 00282 int res; 00283 if (ttype(l) != ttype(r)) 00284 return luaG_ordererror(L, l, r); 00285 else if (ttisnumber(l)) 00286 return nvalue(l) < nvalue(r); 00287 else if (ttisstring(l)) 00288 return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0; 00289 else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) 00290 return res; 00291 return luaG_ordererror(L, l, r); 00292 } 00293 00294 00295 static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) 00296 /*@modifies L @*/ 00297 { 00298 int res; 00299 if (ttype(l) != ttype(r)) 00300 return luaG_ordererror(L, l, r); 00301 else if (ttisnumber(l)) 00302 return nvalue(l) <= nvalue(r); 00303 else if (ttisstring(l)) 00304 return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0; 00305 else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ 00306 return res; 00307 else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ 00308 return !res; 00309 return luaG_ordererror(L, l, r); 00310 } 00311 00312 00313 int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) { 00314 const TObject *tm; 00315 lua_assert(ttype(t1) == ttype(t2)); 00316 switch (ttype(t1)) { 00317 case LUA_TNIL: return 1; 00318 case LUA_TNUMBER: return nvalue(t1) == nvalue(t2); 00319 case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ 00320 case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); 00321 case LUA_TUSERDATA: { 00322 if (uvalue(t1) == uvalue(t2)) return 1; 00323 tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable, 00324 TM_EQ); 00325 break; /* will try TM */ 00326 } 00327 case LUA_TTABLE: { 00328 if (hvalue(t1) == hvalue(t2)) return 1; 00329 tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); 00330 break; /* will try TM */ 00331 } 00332 default: return gcvalue(t1) == gcvalue(t2); 00333 } 00334 if (tm == NULL) return 0; /* no TM? */ 00335 callTMres(L, tm, t1, t2); /* call TM */ 00336 return !l_isfalse(L->top); 00337 } 00338 00339 00340 void luaV_concat (lua_State *L, int total, int last) { 00341 do { 00342 StkId top = L->base + last + 1; 00343 int n = 2; /* number of elements handled in this pass (at least 2) */ 00344 if (!tostring(L, top-2) || !tostring(L, top-1)) { 00345 if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) 00346 luaG_concaterror(L, top-2, top-1); 00347 } else if (tsvalue(top-1)->tsv.len > 0) { /* if len=0, do nothing */ 00348 /* at least two string values; get as many as possible */ 00349 lu_mem tl = cast(lu_mem, tsvalue(top-1)->tsv.len) + 00350 cast(lu_mem, tsvalue(top-2)->tsv.len); 00351 char *buffer; 00352 int i; 00353 while (n < total && tostring(L, top-n-1)) { /* collect total length */ 00354 tl += tsvalue(top-n-1)->tsv.len; 00355 n++; 00356 } 00357 if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow"); 00358 buffer = luaZ_openspace(L, &G(L)->buff, tl); 00359 tl = 0; 00360 for (i=n; i>0; i--) { /* concat all strings */ 00361 size_t l = tsvalue(top-i)->tsv.len; 00362 memcpy(buffer+tl, svalue(top-i), l); 00363 tl += l; 00364 } 00365 setsvalue2s(top-n, luaS_newlstr(L, buffer, tl)); 00366 } 00367 total -= n-1; /* got `n' strings to create 1 new */ 00368 last -= n-1; 00369 } while (total > 1); /* repeat until only 1 result left */ 00370 } 00371 00372 00373 static void Arith (lua_State *L, StkId ra, 00374 const TObject *rb, const TObject *rc, TMS op) 00375 /*@modifies L, ra @*/ 00376 { 00377 TObject tempb, tempc; 00378 const TObject *b, *c; 00379 if ((b = luaV_tonumber(rb, &tempb)) != NULL && 00380 (c = luaV_tonumber(rc, &tempc)) != NULL) { 00381 switch (op) { 00382 case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break; 00383 case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break; 00384 case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break; 00385 case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break; 00386 case TM_POW: { 00387 const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]); 00388 ptrdiff_t res = savestack(L, ra); 00389 if (!ttisfunction(f)) 00390 luaG_runerror(L, "`__pow' (`^' operator) is not a function"); 00391 callTMres(L, f, b, c); 00392 ra = restorestack(L, res); /* previous call may change stack */ 00393 setobjs2s(ra, L->top); 00394 break; 00395 } 00396 default: lua_assert(0); break; 00397 } 00398 } 00399 else if (!call_binTM(L, rb, rc, ra, op)) 00400 luaG_aritherror(L, rb, rc); 00401 } 00402 00403 00404 00405 /* 00406 ** some macros for common tasks in `luaV_execute' 00407 */ 00408 00409 #define runtime_check(L, c) { if (!(c)) return 0; } 00410 00411 #define RA(i) (base+GETARG_A(i)) 00412 /* to be used after possible stack reallocation */ 00413 #define XRA(i) (L->base+GETARG_A(i)) 00414 #define RB(i) (base+GETARG_B(i)) 00415 #define RKB(i) ((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK) 00416 #define RC(i) (base+GETARG_C(i)) 00417 #define RKC(i) ((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK) 00418 #define KBx(i) (k+GETARG_Bx(i)) 00419 00420 00421 #define dojump(pc, i) ((pc) += (i)) 00422 00423 00424 StkId luaV_execute (lua_State *L) { 00425 LClosure *cl; 00426 TObject *k; 00427 const Instruction *pc; 00428 callentry: /* entry point when calling new functions */ 00429 if (L->hookmask & LUA_MASKCALL) { 00430 L->ci->u.l.pc = &pc; 00431 luaD_callhook(L, LUA_HOOKCALL, -1); 00432 } 00433 retentry: /* entry point when returning to old functions */ 00434 L->ci->u.l.pc = &pc; 00435 lua_assert(L->ci->state == CI_SAVEDPC || 00436 L->ci->state == (CI_SAVEDPC | CI_CALLING)); 00437 L->ci->state = CI_HASFRAME; /* activate frame */ 00438 pc = L->ci->u.l.savedpc; 00439 cl = &clvalue(L->base - 1)->l; 00440 k = cl->p->k; 00441 /* main loop of interpreter */ 00442 for (;;) { 00443 const Instruction i = *pc++; 00444 StkId base, ra; 00445 if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && 00446 (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { 00447 traceexec(L); 00448 if (L->ci->state & CI_YIELD) { /* did hook yield? */ 00449 L->ci->u.l.savedpc = pc - 1; 00450 L->ci->state = CI_YIELD | CI_SAVEDPC; 00451 return NULL; 00452 } 00453 } 00454 /* warning!! several calls may realloc the stack and invalidate `ra' */ 00455 base = L->base; 00456 ra = RA(i); 00457 lua_assert(L->ci->state & CI_HASFRAME); 00458 lua_assert(base == L->ci->base); 00459 lua_assert(L->top <= L->stack + L->stacksize && L->top >= base); 00460 lua_assert(L->top == L->ci->top || 00461 GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || 00462 GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO); 00463 switch (GET_OPCODE(i)) { 00464 case OP_MOVE: { 00465 setobjs2s(ra, RB(i)); 00466 break; 00467 } 00468 case OP_LOADK: { 00469 setobj2s(ra, KBx(i)); 00470 break; 00471 } 00472 case OP_LOADBOOL: { 00473 setbvalue(ra, GETARG_B(i)); 00474 if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ 00475 break; 00476 } 00477 case OP_LOADNIL: { 00478 TObject *rb = RB(i); 00479 do { 00480 setnilvalue(rb--); 00481 } while (rb >= ra); 00482 break; 00483 } 00484 case OP_GETUPVAL: { 00485 int b = GETARG_B(i); 00486 setobj2s(ra, cl->upvals[b]->v); 00487 break; 00488 } 00489 case OP_GETGLOBAL: { 00490 TObject *rb = KBx(i); 00491 const TObject *v; 00492 lua_assert(ttisstring(rb) && ttistable(&cl->g)); 00493 v = luaH_getstr(hvalue(&cl->g), tsvalue(rb)); 00494 if (!ttisnil(v)) { setobj2s(ra, v); } 00495 else 00496 setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0)); 00497 break; 00498 } 00499 case OP_GETTABLE: { 00500 StkId rb = RB(i); 00501 TObject *rc = RKC(i); 00502 if (ttistable(rb)) { 00503 const TObject *v = luaH_get(hvalue(rb), rc); 00504 if (!ttisnil(v)) { setobj2s(ra, v); } 00505 else 00506 setobj2s(XRA(i), luaV_index(L, rb, rc, 0)); 00507 } 00508 else 00509 setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0)); 00510 break; 00511 } 00512 case OP_SETGLOBAL: { 00513 lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g)); 00514 luaV_settable(L, &cl->g, KBx(i), ra); 00515 break; 00516 } 00517 case OP_SETUPVAL: { 00518 int b = GETARG_B(i); 00519 setobj(cl->upvals[b]->v, ra); /* write barrier */ 00520 break; 00521 } 00522 case OP_SETTABLE: { 00523 luaV_settable(L, ra, RKB(i), RKC(i)); 00524 break; 00525 } 00526 case OP_NEWTABLE: { 00527 int b = GETARG_B(i); 00528 b = fb2int(b); 00529 sethvalue(ra, luaH_new(L, b, GETARG_C(i))); 00530 luaC_checkGC(L); 00531 break; 00532 } 00533 case OP_SELF: { 00534 StkId rb = RB(i); 00535 TObject *rc = RKC(i); 00536 runtime_check(L, ttisstring(rc)); 00537 setobjs2s(ra+1, rb); 00538 if (ttistable(rb)) { 00539 const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc)); 00540 if (!ttisnil(v)) { setobj2s(ra, v); } 00541 else 00542 setobj2s(XRA(i), luaV_index(L, rb, rc, 0)); 00543 } 00544 else 00545 setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0)); 00546 break; 00547 } 00548 case OP_ADD: { 00549 TObject *rb = RKB(i); 00550 TObject *rc = RKC(i); 00551 if (ttisnumber(rb) && ttisnumber(rc)) { 00552 setnvalue(ra, nvalue(rb) + nvalue(rc)); 00553 } 00554 else 00555 Arith(L, ra, rb, rc, TM_ADD); 00556 break; 00557 } 00558 case OP_SUB: { 00559 TObject *rb = RKB(i); 00560 TObject *rc = RKC(i); 00561 if (ttisnumber(rb) && ttisnumber(rc)) { 00562 setnvalue(ra, nvalue(rb) - nvalue(rc)); 00563 } 00564 else 00565 Arith(L, ra, rb, rc, TM_SUB); 00566 break; 00567 } 00568 case OP_MUL: { 00569 TObject *rb = RKB(i); 00570 TObject *rc = RKC(i); 00571 if (ttisnumber(rb) && ttisnumber(rc)) { 00572 setnvalue(ra, nvalue(rb) * nvalue(rc)); 00573 } 00574 else 00575 Arith(L, ra, rb, rc, TM_MUL); 00576 break; 00577 } 00578 case OP_DIV: { 00579 TObject *rb = RKB(i); 00580 TObject *rc = RKC(i); 00581 if (ttisnumber(rb) && ttisnumber(rc)) { 00582 setnvalue(ra, nvalue(rb) / nvalue(rc)); 00583 } 00584 else 00585 Arith(L, ra, rb, rc, TM_DIV); 00586 break; 00587 } 00588 case OP_POW: { 00589 Arith(L, ra, RKB(i), RKC(i), TM_POW); 00590 break; 00591 } 00592 case OP_UNM: { 00593 const TObject *rb = RB(i); 00594 TObject temp; 00595 if (tonumber(rb, &temp)) { 00596 setnvalue(ra, -nvalue(rb)); 00597 } 00598 else { 00599 setnilvalue(&temp); 00600 if (!call_binTM(L, RB(i), &temp, ra, TM_UNM)) 00601 luaG_aritherror(L, RB(i), &temp); 00602 } 00603 break; 00604 } 00605 case OP_NOT: { 00606 int res = l_isfalse(RB(i)); /* next assignment may change this value */ 00607 setbvalue(ra, res); 00608 break; 00609 } 00610 case OP_CONCAT: { 00611 int b = GETARG_B(i); 00612 int c = GETARG_C(i); 00613 luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */ 00614 base = L->base; 00615 setobjs2s(RA(i), base+b); 00616 luaC_checkGC(L); 00617 break; 00618 } 00619 case OP_JMP: { 00620 dojump(pc, GETARG_sBx(i)); 00621 break; 00622 } 00623 case OP_EQ: { 00624 if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; 00625 else dojump(pc, GETARG_sBx(*pc) + 1); 00626 break; 00627 } 00628 case OP_LT: { 00629 if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; 00630 else dojump(pc, GETARG_sBx(*pc) + 1); 00631 break; 00632 } 00633 case OP_LE: { 00634 if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; 00635 else dojump(pc, GETARG_sBx(*pc) + 1); 00636 break; 00637 } 00638 case OP_TEST: { 00639 TObject *rb = RB(i); 00640 if (l_isfalse(rb) == GETARG_C(i)) pc++; 00641 else { 00642 setobjs2s(ra, rb); 00643 dojump(pc, GETARG_sBx(*pc) + 1); 00644 } 00645 break; 00646 } 00647 case OP_CALL: 00648 case OP_TAILCALL: { 00649 StkId firstResult; 00650 int b = GETARG_B(i); 00651 int nresults; 00652 if (b != 0) L->top = ra+b; /* else previous instruction set top */ 00653 nresults = GETARG_C(i) - 1; 00654 firstResult = luaD_precall(L, ra); 00655 if (firstResult) { 00656 if (firstResult > L->top) { /* yield? */ 00657 lua_assert(L->ci->state == (CI_C | CI_YIELD)); 00658 (L->ci - 1)->u.l.savedpc = pc; 00659 (L->ci - 1)->state = CI_SAVEDPC; 00660 return NULL; 00661 } 00662 /* it was a C function (`precall' called it); adjust results */ 00663 luaD_poscall(L, nresults, firstResult); 00664 if (nresults >= 0) L->top = L->ci->top; 00665 } 00666 else { /* it is a Lua function */ 00667 if (GET_OPCODE(i) == OP_CALL) { /* regular call? */ 00668 (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */ 00669 (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING); 00670 } 00671 else { /* tail call: put new frame in place of previous one */ 00672 int aux; 00673 base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */ 00674 ra = RA(i); 00675 if (L->openupval) luaF_close(L, base); 00676 for (aux = 0; ra+aux < L->top; aux++) /* move frame down */ 00677 setobjs2s(base+aux-1, ra+aux); 00678 (L->ci - 1)->top = L->top = base+aux; /* correct top */ 00679 lua_assert(L->ci->state & CI_SAVEDPC); 00680 (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; 00681 (L->ci - 1)->u.l.tailcalls++; /* one more call lost */ 00682 (L->ci - 1)->state = CI_SAVEDPC; 00683 L->ci--; /* remove new frame */ 00684 L->base = L->ci->base; 00685 } 00686 goto callentry; 00687 } 00688 break; 00689 } 00690 case OP_RETURN: { 00691 CallInfo *ci = L->ci - 1; /* previous function frame */ 00692 int b = GETARG_B(i); 00693 if (b != 0) L->top = ra+b-1; 00694 lua_assert(L->ci->state & CI_HASFRAME); 00695 if (L->openupval) luaF_close(L, base); 00696 L->ci->state = CI_SAVEDPC; /* deactivate current function */ 00697 L->ci->u.l.savedpc = pc; 00698 /* previous function was running `here'? */ 00699 if (!(ci->state & CI_CALLING)) { 00700 lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc); 00701 return ra; /* no: return */ 00702 } 00703 else { /* yes: continue its execution */ 00704 int nresults; 00705 lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC)); 00706 lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); 00707 nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1; 00708 luaD_poscall(L, nresults, ra); 00709 if (nresults >= 0) L->top = L->ci->top; 00710 goto retentry; 00711 } 00712 } 00713 case OP_FORLOOP: { 00714 lua_Number step, idx, limit; 00715 const TObject *plimit = ra+1; 00716 const TObject *pstep = ra+2; 00717 if (!ttisnumber(ra)) 00718 luaG_runerror(L, "`for' initial value must be a number"); 00719 if (!tonumber(plimit, ra+1)) 00720 luaG_runerror(L, "`for' limit must be a number"); 00721 /*@-modobserver@*/ 00722 if (!tonumber(pstep, ra+2)) 00723 luaG_runerror(L, "`for' step must be a number"); 00724 /*@=modobserver@*/ 00725 step = nvalue(pstep); 00726 idx = nvalue(ra) + step; /* increment index */ 00727 limit = nvalue(plimit); 00728 if (step > 0 ? idx <= limit : idx >= limit) { 00729 dojump(pc, GETARG_sBx(i)); /* jump back */ 00730 chgnvalue(ra, idx); /* update index */ 00731 } 00732 break; 00733 } 00734 case OP_TFORLOOP: { 00735 int nvar = GETARG_C(i) + 1; 00736 StkId cb = ra + nvar + 2; /* call base */ 00737 setobjs2s(cb, ra); 00738 setobjs2s(cb+1, ra+1); 00739 setobjs2s(cb+2, ra+2); 00740 L->top = cb+3; /* func. + 2 args (state and index) */ 00741 luaD_call(L, cb, nvar); 00742 L->top = L->ci->top; 00743 ra = XRA(i) + 2; /* final position of first result */ 00744 cb = ra + nvar; 00745 do { /* move results to proper positions */ 00746 nvar--; 00747 setobjs2s(ra+nvar, cb+nvar); 00748 } while (nvar > 0); 00749 if (ttisnil(ra)) /* break loop? */ 00750 pc++; /* skip jump (break loop) */ 00751 else 00752 dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */ 00753 break; 00754 } 00755 case OP_TFORPREP: { /* for compatibility only */ 00756 if (ttistable(ra)) { 00757 setobjs2s(ra+1, ra); 00758 setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next"))); 00759 } 00760 dojump(pc, GETARG_sBx(i)); 00761 break; 00762 } 00763 case OP_SETLIST: 00764 case OP_SETLISTO: { 00765 int bc; 00766 int n; 00767 Table *h; 00768 runtime_check(L, ttistable(ra)); 00769 h = hvalue(ra); 00770 bc = GETARG_Bx(i); 00771 if (GET_OPCODE(i) == OP_SETLIST) 00772 n = (bc&(LFIELDS_PER_FLUSH-1)) + 1; 00773 else { 00774 n = L->top - ra - 1; 00775 L->top = L->ci->top; 00776 } 00777 bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */ 00778 for (; n > 0; n--) 00779 setobj2t(luaH_setnum(L, h, bc+n), ra+n); /* write barrier */ 00780 break; 00781 } 00782 case OP_CLOSE: { 00783 luaF_close(L, ra); 00784 break; 00785 } 00786 case OP_CLOSURE: { 00787 Proto *p; 00788 Closure *ncl; 00789 int nup, j; 00790 p = cl->p->p[GETARG_Bx(i)]; 00791 nup = p->nups; 00792 ncl = luaF_newLclosure(L, nup, &cl->g); 00793 ncl->l.p = p; 00794 for (j=0; j<nup; j++, pc++) { 00795 if (GET_OPCODE(*pc) == OP_GETUPVAL) 00796 ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; 00797 else { 00798 lua_assert(GET_OPCODE(*pc) == OP_MOVE); 00799 ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); 00800 } 00801 } 00802 setclvalue(ra, ncl); 00803 luaC_checkGC(L); 00804 break; 00805 } 00806 } 00807 } 00808 } 00809 00810