diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-05 15:17:01 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-05 15:17:01 -0300 |
| commit | 762d059a13d83eb367238a6115bbb4f5f13fcb49 (patch) | |
| tree | f35fdf0675b791865d0d4800522b172903b34803 /lvm.c | |
| parent | 572a69b6afbd368beab8844bc876b0f9690b5253 (diff) | |
| download | lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.tar.gz lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.tar.bz2 lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.zip | |
new implementation for the Virtual Machine
Diffstat (limited to 'lvm.c')
| -rw-r--r-- | lvm.c | 476 |
1 files changed, 231 insertions, 245 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.177 2001/03/26 14:31:49 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.178 2001/04/06 18:25:00 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 | */ |
| @@ -28,15 +28,14 @@ | |||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | int luaV_tonumber (TObject *obj) { | 31 | const TObject *luaV_tonumber (const TObject *obj, TObject *n) { |
| 32 | if (ttype(obj) != LUA_TSTRING) | 32 | if (ttype(obj) == LUA_TNUMBER) return obj; |
| 33 | return 1; | 33 | if (ttype(obj) == LUA_TSTRING && luaO_str2d(svalue(obj), &nvalue(n))) { |
| 34 | else { | 34 | ttype(n) = LUA_TNUMBER; |
| 35 | if (!luaO_str2d(svalue(obj), &nvalue(obj))) | 35 | return n; |
| 36 | return 2; | ||
| 37 | ttype(obj) = LUA_TNUMBER; | ||
| 38 | return 0; | ||
| 39 | } | 36 | } |
| 37 | else | ||
| 38 | return NULL; | ||
| 40 | } | 39 | } |
| 41 | 40 | ||
| 42 | 41 | ||
| @@ -148,8 +147,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { | |||
| 148 | } | 147 | } |
| 149 | } | 148 | } |
| 150 | /* else will call the tag method */ | 149 | /* else will call the tag method */ |
| 151 | } | 150 | } else { /* not a table; try a `gettable' tag method */ |
| 152 | else { /* not a table; try a `gettable' tag method */ | ||
| 153 | tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE); | 151 | tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE); |
| 154 | if (tm == NULL) /* no tag method? */ | 152 | if (tm == NULL) /* no tag method? */ |
| 155 | luaG_typeerror(L, t, l_s("index")); | 153 | luaG_typeerror(L, t, l_s("index")); |
| @@ -162,7 +160,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { | |||
| 162 | /* | 160 | /* |
| 163 | ** Receives table at `t', key at `key' and value at `val'. | 161 | ** Receives table at `t', key at `key' and value at `val'. |
| 164 | */ | 162 | */ |
| 165 | void luaV_settable (lua_State *L, StkId t, StkId key, StkId val) { | 163 | void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) { |
| 166 | Closure *tm; | 164 | Closure *tm; |
| 167 | if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ | 165 | if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ |
| 168 | int tg = hvalue(t)->htag; | 166 | int tg = hvalue(t)->htag; |
| @@ -172,8 +170,7 @@ void luaV_settable (lua_State *L, StkId t, StkId key, StkId val) { | |||
| 172 | return; | 170 | return; |
| 173 | } | 171 | } |
| 174 | /* else will call the tag method */ | 172 | /* else will call the tag method */ |
| 175 | } | 173 | } else { /* not a table; try a `settable' tag method */ |
| 176 | else { /* not a table; try a `settable' tag method */ | ||
| 177 | tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE); | 174 | tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE); |
| 178 | if (tm == NULL) /* no tag method? */ | 175 | if (tm == NULL) /* no tag method? */ |
| 179 | luaG_typeerror(L, t, l_s("index")); | 176 | luaG_typeerror(L, t, l_s("index")); |
| @@ -188,8 +185,7 @@ void luaV_getglobal (lua_State *L, TString *name, StkId res) { | |||
| 188 | if (!HAS_TM_GETGLOBAL(L, ttype(value)) || /* is there a tag method? */ | 185 | if (!HAS_TM_GETGLOBAL(L, ttype(value)) || /* is there a tag method? */ |
| 189 | (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) { | 186 | (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) { |
| 190 | setobj(res, value); /* default behavior */ | 187 | setobj(res, value); /* default behavior */ |
| 191 | } | 188 | } else |
| 192 | else | ||
| 193 | callTM(L, l_s("csor"), tm, name, value, res); | 189 | callTM(L, l_s("csor"), tm, name, value, res); |
| 194 | } | 190 | } |
| 195 | 191 | ||
| @@ -200,8 +196,7 @@ void luaV_setglobal (lua_State *L, TString *name, StkId val) { | |||
| 200 | if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) || /* no tag methods? */ | 196 | if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) || /* no tag methods? */ |
| 201 | (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) { | 197 | (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) { |
| 202 | setobj(oldvalue, val); /* raw set */ | 198 | setobj(oldvalue, val); /* raw set */ |
| 203 | } | 199 | } else |
| 204 | else | ||
| 205 | callTM(L, l_s("csoo"), tm, name, oldvalue, val); | 200 | callTM(L, l_s("csoo"), tm, name, oldvalue, val); |
| 206 | } | 201 | } |
| 207 | 202 | ||
| @@ -224,9 +219,10 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, | |||
| 224 | } | 219 | } |
| 225 | 220 | ||
| 226 | 221 | ||
| 227 | static void call_arith (lua_State *L, StkId p1, TMS event) { | 222 | static void call_arith (lua_State *L, StkId p1, TObject *p2, |
| 228 | if (!call_binTM(L, p1, p1+1, p1, event)) | 223 | StkId res, TMS event) { |
| 229 | luaG_binerror(L, p1, LUA_TNUMBER, l_s("perform arithmetic on")); | 224 | if (!call_binTM(L, p1, p2, res, event)) |
| 225 | luaG_aritherror(L, p1, p2); | ||
| 230 | } | 226 | } |
| 231 | 227 | ||
| 232 | 228 | ||
| @@ -270,9 +266,8 @@ void luaV_strconc (lua_State *L, int total, StkId top) { | |||
| 270 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 266 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
| 271 | if (tostring(L, top-2) || tostring(L, top-1)) { | 267 | if (tostring(L, top-2) || tostring(L, top-1)) { |
| 272 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) | 268 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) |
| 273 | luaG_binerror(L, top-2, LUA_TSTRING, l_s("concat")); | 269 | luaG_concaterror(L, top-2, top-1); |
| 274 | } | 270 | } else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ |
| 275 | else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ | ||
| 276 | /* at least two string values; get as many as possible */ | 271 | /* at least two string values; get as many as possible */ |
| 277 | lu_mem tl = (lu_mem)tsvalue(top-1)->len + (lu_mem)tsvalue(top-2)->len; | 272 | lu_mem tl = (lu_mem)tsvalue(top-1)->len + (lu_mem)tsvalue(top-2)->len; |
| 278 | l_char *buffer; | 273 | l_char *buffer; |
| @@ -321,7 +316,32 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { | |||
| 321 | 316 | ||
| 322 | 317 | ||
| 323 | 318 | ||
| 324 | #define dojump(pc, i) ((pc) += GETARG_S(i)) | 319 | /* |
| 320 | ** some macros for common tasks in `luaV_execute' | ||
| 321 | */ | ||
| 322 | |||
| 323 | #define runtime_check(L, c) { if (!(c)) return L->top; } | ||
| 324 | |||
| 325 | #define RA(i) (base+GETARG_A(i)) | ||
| 326 | #define RB(i) (base+GETARG_B(i)) | ||
| 327 | #define RC(i) (base+GETARG_C(i)) | ||
| 328 | #define RKC(i) ((GETARG_C(i) < MAXSTACK) ? \ | ||
| 329 | base+GETARG_C(i) : \ | ||
| 330 | tf->k+GETARG_C(i)-MAXSTACK) | ||
| 331 | #define KBc(i) (tf->k+GETARG_Bc(i)) | ||
| 332 | |||
| 333 | #define Arith(op, optm) { \ | ||
| 334 | const TObject *b = RB(i); const TObject *c = RKC(i); \ | ||
| 335 | TObject tempb, tempc; \ | ||
| 336 | if ((ttype(b) == LUA_TNUMBER || (b = luaV_tonumber(b, &tempb)) != NULL) && \ | ||
| 337 | (ttype(c) == LUA_TNUMBER || (c = luaV_tonumber(c, &tempc)) != NULL)) { \ | ||
| 338 | setnvalue(RA(i), nvalue(b) op nvalue(c)); \ | ||
| 339 | } else \ | ||
| 340 | call_arith(L, RB(i), RKC(i), RA(i), optm); \ | ||
| 341 | } | ||
| 342 | |||
| 343 | |||
| 344 | #define dojump(pc, i) ((pc) += GETARG_sBc(i)) | ||
| 325 | 345 | ||
| 326 | /* | 346 | /* |
| 327 | ** Executes the given Lua function. Parameters are between [base,top). | 347 | ** Executes the given Lua function. Parameters are between [base,top). |
| @@ -329,328 +349,294 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { | |||
| 329 | */ | 349 | */ |
| 330 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | 350 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { |
| 331 | const Proto *const tf = cl->f.l; | 351 | const Proto *const tf = cl->f.l; |
| 332 | StkId top; /* keep top local, for performance */ | 352 | const Instruction *pc; |
| 333 | const Instruction *pc = tf->code; | 353 | lua_Hook linehook; |
| 334 | const lua_Hook linehook = L->linehook; | ||
| 335 | L->ci->pc = &pc; | ||
| 336 | if (tf->is_vararg) /* varargs? */ | 354 | if (tf->is_vararg) /* varargs? */ |
| 337 | adjust_varargs(L, base, tf->numparams); | 355 | adjust_varargs(L, base, tf->numparams); |
| 338 | luaD_adjusttop(L, base, tf->maxstacksize); | 356 | luaD_adjusttop(L, base, tf->maxstacksize); |
| 339 | top = base+tf->numparams+tf->is_vararg; | 357 | pc = tf->code; |
| 358 | L->ci->pc = &pc; | ||
| 359 | linehook = L->linehook; | ||
| 340 | /* main loop of interpreter */ | 360 | /* main loop of interpreter */ |
| 341 | for (;;) { | 361 | for (;;) { |
| 342 | const Instruction i = *pc++; | 362 | const Instruction i = *pc++; |
| 343 | lua_assert(L->top == base+tf->maxstacksize); | ||
| 344 | if (linehook) | 363 | if (linehook) |
| 345 | traceexec(L, linehook); | 364 | traceexec(L, linehook); |
| 346 | switch (GET_OPCODE(i)) { | 365 | switch (GET_OPCODE(i)) { |
| 347 | case OP_RETURN: { | 366 | case OP_MOVE: { |
| 348 | L->top = top; | 367 | setobj(RA(i), RB(i)); |
| 349 | return base+GETARG_U(i); | ||
| 350 | } | ||
| 351 | case OP_CALL: { | ||
| 352 | int nres = GETARG_B(i); | ||
| 353 | if (nres == MULT_RET) nres = LUA_MULTRET; | ||
| 354 | L->top = top; | ||
| 355 | luaD_call(L, base+GETARG_A(i), nres); | ||
| 356 | top = L->top; | ||
| 357 | L->top = base+tf->maxstacksize; | ||
| 358 | break; | ||
| 359 | } | ||
| 360 | case OP_PUSHNIL: { | ||
| 361 | int n = GETARG_U(i); | ||
| 362 | lua_assert(n>0); | ||
| 363 | do { | ||
| 364 | setnilvalue(top++); | ||
| 365 | } while (--n > 0); | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | case OP_POP: { | ||
| 369 | top -= GETARG_U(i); | ||
| 370 | break; | ||
| 371 | } | ||
| 372 | case OP_PUSHINT: { | ||
| 373 | setnvalue(top, (lua_Number)GETARG_S(i)); | ||
| 374 | top++; | ||
| 375 | break; | ||
| 376 | } | ||
| 377 | case OP_PUSHSTRING: { | ||
| 378 | setsvalue(top, tf->kstr[GETARG_U(i)]); | ||
| 379 | top++; | ||
| 380 | break; | 368 | break; |
| 381 | } | 369 | } |
| 382 | case OP_PUSHNUM: { | 370 | case OP_LOADK: { |
| 383 | setnvalue(top, tf->knum[GETARG_U(i)]); | 371 | setobj(RA(i), KBc(i)); |
| 384 | top++; | ||
| 385 | break; | 372 | break; |
| 386 | } | 373 | } |
| 387 | case OP_PUSHNEGNUM: { | 374 | case OP_LOADINT: { |
| 388 | setnvalue(top, -tf->knum[GETARG_U(i)]); | 375 | setnvalue(RA(i), (lua_Number)GETARG_sBc(i)); |
| 389 | top++; | ||
| 390 | break; | 376 | break; |
| 391 | } | 377 | } |
| 392 | case OP_PUSHUPVALUE: { | 378 | case OP_LOADUPVAL: { |
| 393 | setobj(top++, &cl->upvalue[GETARG_U(i)]); | 379 | setobj(RA(i), cl->upvalue+GETARG_Bc(i)); |
| 394 | break; | 380 | break; |
| 395 | } | 381 | } |
| 396 | case OP_GETLOCAL: { | 382 | case OP_LOADNIL: { |
| 397 | setobj(top++, base+GETARG_U(i)); | 383 | TObject *ra = RA(i); |
| 384 | TObject *rb = RB(i); | ||
| 385 | do { | ||
| 386 | setnilvalue(ra++); | ||
| 387 | } while (ra <= rb); | ||
| 398 | break; | 388 | break; |
| 399 | } | 389 | } |
| 400 | case OP_GETGLOBAL: { | 390 | case OP_GETGLOBAL: { |
| 401 | luaV_getglobal(L, tf->kstr[GETARG_U(i)], top); | 391 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); |
| 402 | top++; | 392 | luaV_getglobal(L, tsvalue(KBc(i)), RA(i)); |
| 403 | break; | 393 | break; |
| 404 | } | 394 | } |
| 405 | case OP_GETTABLE: { | 395 | case OP_GETTABLE: { |
| 406 | top--; | 396 | luaV_gettable(L, RB(i), RKC(i), RA(i)); |
| 407 | luaV_gettable(L, top-1, top, top-1); | ||
| 408 | break; | ||
| 409 | } | ||
| 410 | case OP_GETDOTTED: { | ||
| 411 | setsvalue(top, tf->kstr[GETARG_U(i)]); | ||
| 412 | luaV_gettable(L, top-1, top, top-1); | ||
| 413 | break; | ||
| 414 | } | ||
| 415 | case OP_GETINDEXED: { | ||
| 416 | luaV_gettable(L, top-1, base+GETARG_U(i), top-1); | ||
| 417 | break; | ||
| 418 | } | ||
| 419 | case OP_PUSHSELF: { | ||
| 420 | setobj(top, top-1); | ||
| 421 | setsvalue(top+1, tf->kstr[GETARG_U(i)]); | ||
| 422 | luaV_gettable(L, top-1, top+1, top-1); | ||
| 423 | top++; | ||
| 424 | break; | ||
| 425 | } | ||
| 426 | case OP_CREATETABLE: { | ||
| 427 | luaC_checkGC(L); | ||
| 428 | sethvalue(top, luaH_new(L, GETARG_U(i))); | ||
| 429 | top++; | ||
| 430 | break; | ||
| 431 | } | ||
| 432 | case OP_SETLOCAL: { | ||
| 433 | setobj(base+GETARG_U(i), --top); | ||
| 434 | break; | 397 | break; |
| 435 | } | 398 | } |
| 436 | case OP_SETGLOBAL: { | 399 | case OP_SETGLOBAL: { |
| 437 | top--; | 400 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); |
| 438 | luaV_setglobal(L, tf->kstr[GETARG_U(i)], top); | 401 | luaV_setglobal(L, tsvalue(KBc(i)), RA(i)); |
| 439 | break; | 402 | break; |
| 440 | } | 403 | } |
| 441 | case OP_SETTABLE: { | 404 | case OP_SETTABLE: { |
| 442 | StkId t = top-GETARG_A(i); | 405 | luaV_settable(L, RB(i), RKC(i), RA(i)); |
| 443 | luaV_settable(L, t, t+1, top-1); | ||
| 444 | top -= GETARG_B(i); /* pop values */ | ||
| 445 | break; | 406 | break; |
| 446 | } | 407 | } |
| 447 | case OP_SETLIST: { | 408 | case OP_NEWTABLE: { |
| 448 | int aux = GETARG_A(i) * LFIELDS_PER_FLUSH; | 409 | luaC_checkGC(L); |
| 449 | TObject *t = base+GETARG_B(i); | 410 | sethvalue(RA(i), luaH_new(L, GETARG_Bc(i))); |
| 450 | Hash *h = hvalue(t); | ||
| 451 | int n; | ||
| 452 | for (n = top-t-1; n; n--) | ||
| 453 | setobj(luaH_setnum(L, h, n+aux), --top); | ||
| 454 | break; | 411 | break; |
| 455 | } | 412 | } |
| 456 | case OP_SETMAP: { | 413 | case OP_SELF: { |
| 457 | TObject *t = base+GETARG_U(i); | 414 | StkId ra = RA(i); |
| 458 | Hash *h = hvalue(t); | 415 | StkId rb = RB(i); |
| 459 | while (top-1 > t) { | 416 | setobj(ra+1, rb); |
| 460 | top-=2; | 417 | luaV_gettable(L, rb, RKC(i), ra); |
| 461 | setobj(luaH_set(L, h, top), top+1); | ||
| 462 | } | ||
| 463 | break; | 418 | break; |
| 464 | } | 419 | } |
| 465 | case OP_ADD: { | 420 | case OP_ADD: { |
| 466 | if (tonumber(top-2) || tonumber(top-1)) | 421 | Arith( + , TM_ADD); |
| 467 | call_arith(L, top-2, TM_ADD); | ||
| 468 | else | ||
| 469 | nvalue(top-2) += nvalue(top-1); | ||
| 470 | top--; | ||
| 471 | break; | ||
| 472 | } | ||
| 473 | case OP_ADDI: { | ||
| 474 | if (tonumber(top-1)) { | ||
| 475 | setnvalue(top, (lua_Number)GETARG_S(i)); | ||
| 476 | call_arith(L, top-1, TM_ADD); | ||
| 477 | } | ||
| 478 | else | ||
| 479 | nvalue(top-1) += (lua_Number)GETARG_S(i); | ||
| 480 | break; | 422 | break; |
| 481 | } | 423 | } |
| 482 | case OP_SUB: { | 424 | case OP_SUB: { |
| 483 | if (tonumber(top-2) || tonumber(top-1)) | 425 | Arith( - , TM_SUB); |
| 484 | call_arith(L, top-2, TM_SUB); | ||
| 485 | else | ||
| 486 | nvalue(top-2) -= nvalue(top-1); | ||
| 487 | top--; | ||
| 488 | break; | 426 | break; |
| 489 | } | 427 | } |
| 490 | case OP_MULT: { | 428 | case OP_MUL: { |
| 491 | if (tonumber(top-2) || tonumber(top-1)) | 429 | Arith( * , TM_MUL); |
| 492 | call_arith(L, top-2, TM_MUL); | ||
| 493 | else | ||
| 494 | nvalue(top-2) *= nvalue(top-1); | ||
| 495 | top--; | ||
| 496 | break; | 430 | break; |
| 497 | } | 431 | } |
| 498 | case OP_DIV: { | 432 | case OP_DIV: { |
| 499 | if (tonumber(top-2) || tonumber(top-1)) | 433 | Arith( / , TM_DIV); |
| 500 | call_arith(L, top-2, TM_DIV); | ||
| 501 | else | ||
| 502 | nvalue(top-2) /= nvalue(top-1); | ||
| 503 | top--; | ||
| 504 | break; | 434 | break; |
| 505 | } | 435 | } |
| 506 | case OP_POW: { | 436 | case OP_POW: { |
| 507 | if (!call_binTM(L, top-2, top-1, top-2, TM_POW)) | 437 | call_arith(L, RB(i), RKC(i), RA(i), TM_POW); |
| 508 | luaD_error(L, l_s("undefined operation")); | ||
| 509 | top--; | ||
| 510 | break; | 438 | break; |
| 511 | } | 439 | } |
| 512 | case OP_CONCAT: { | 440 | case OP_UNM: { |
| 513 | int n = GETARG_U(i); | 441 | const TObject *rb = RB(i); |
| 514 | luaV_strconc(L, n, top); | 442 | StkId ra = RA(i); |
| 515 | top -= n-1; | 443 | if (ttype(rb) == LUA_TNUMBER || (rb=luaV_tonumber(rb, ra)) != NULL) { |
| 516 | luaC_checkGC(L); | 444 | setnvalue(ra, -nvalue(rb)); |
| 517 | break; | 445 | } |
| 518 | } | 446 | else { |
| 519 | case OP_MINUS: { | 447 | TObject temp; |
| 520 | if (tonumber(top-1)) { | 448 | setnilvalue(&temp); |
| 521 | setnilvalue(top); | 449 | call_arith(L, RB(i), &temp, ra, TM_UNM); |
| 522 | call_arith(L, top-1, TM_UNM); | ||
| 523 | } | 450 | } |
| 524 | else | ||
| 525 | nvalue(top-1) = -nvalue(top-1); | ||
| 526 | break; | 451 | break; |
| 527 | } | 452 | } |
| 528 | case OP_NOT: { | 453 | case OP_NOT: { |
| 529 | ttype(top-1) = | 454 | if (ttype(RB(i)) == LUA_TNIL) { |
| 530 | (ttype(top-1) == LUA_TNIL) ? LUA_TNUMBER : LUA_TNIL; | 455 | setnvalue(RA(i), 1); |
| 531 | nvalue(top-1) = 1; | 456 | } else { |
| 457 | setnilvalue(RA(i)); | ||
| 458 | } | ||
| 532 | break; | 459 | break; |
| 533 | } | 460 | } |
| 534 | case OP_JMPNE: { | 461 | case OP_CONCAT: { |
| 535 | top -= 2; | 462 | StkId top = RC(i)+1; |
| 536 | if (!luaO_equalObj(top, top+1)) dojump(pc, i); | 463 | StkId rb = RB(i); |
| 464 | luaV_strconc(L, top-rb, top); | ||
| 465 | setobj(RA(i), rb); | ||
| 466 | luaC_checkGC(L); | ||
| 537 | break; | 467 | break; |
| 538 | } | 468 | } |
| 539 | case OP_JMPEQ: { | 469 | case OP_CJMP: |
| 540 | top -= 2; | 470 | case OP_JMP: { |
| 541 | if (luaO_equalObj(top, top+1)) dojump(pc, i); | 471 | dojump(pc, i); |
| 542 | break; | 472 | break; |
| 543 | } | 473 | } |
| 544 | case OP_JMPLT: { | 474 | case OP_TESTEQ: { |
| 545 | top -= 2; | 475 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 546 | if (luaV_lessthan(L, top, top+1)) dojump(pc, i); | 476 | if (luaO_equalObj(RB(i), RKC(i))) dojump(pc, *pc); |
| 477 | pc++; | ||
| 547 | break; | 478 | break; |
| 548 | } | 479 | } |
| 549 | case OP_JMPLE: { /* a <= b === !(b<a) */ | 480 | case OP_TESTNE: { |
| 550 | top -= 2; | 481 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 551 | if (!luaV_lessthan(L, top+1, top)) dojump(pc, i); | 482 | if (!luaO_equalObj(RB(i), RKC(i))) dojump(pc, *pc); |
| 483 | pc++; | ||
| 552 | break; | 484 | break; |
| 553 | } | 485 | } |
| 554 | case OP_JMPGT: { /* a > b === (b<a) */ | 486 | case OP_TESTLT: { |
| 555 | top -= 2; | 487 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 556 | if (luaV_lessthan(L, top+1, top)) dojump(pc, i); | 488 | if (luaV_lessthan(L, RB(i), RKC(i))) dojump(pc, *pc); |
| 489 | pc++; | ||
| 557 | break; | 490 | break; |
| 558 | } | 491 | } |
| 559 | case OP_JMPGE: { /* a >= b === !(a<b) */ | 492 | case OP_TESTLE: { /* b <= c === !(c<b) */ |
| 560 | top -= 2; | 493 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 561 | if (!luaV_lessthan(L, top, top+1)) dojump(pc, i); | 494 | if (!luaV_lessthan(L, RKC(i), RB(i))) dojump(pc, *pc); |
| 495 | pc++; | ||
| 562 | break; | 496 | break; |
| 563 | } | 497 | } |
| 564 | case OP_JMPT: { | 498 | case OP_TESTGT: { /* b > c === (c<b) */ |
| 565 | if (ttype(--top) != LUA_TNIL) dojump(pc, i); | 499 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 500 | if (luaV_lessthan(L, RKC(i), RB(i))) dojump(pc, *pc); | ||
| 501 | pc++; | ||
| 566 | break; | 502 | break; |
| 567 | } | 503 | } |
| 568 | case OP_JMPF: { | 504 | case OP_TESTGE: { /* b >= c === !(b<c) */ |
| 569 | if (ttype(--top) == LUA_TNIL) dojump(pc, i); | 505 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 506 | if (!luaV_lessthan(L, RB(i), RKC(i))) dojump(pc, *pc); | ||
| 507 | pc++; | ||
| 570 | break; | 508 | break; |
| 571 | } | 509 | } |
| 572 | case OP_JMPONT: { | 510 | case OP_TESTT: { |
| 573 | if (ttype(top-1) == LUA_TNIL) top--; | 511 | StkId rb = RB(i); |
| 574 | else dojump(pc, i); | 512 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 513 | if (ttype(rb) != LUA_TNIL) { | ||
| 514 | int a = GETARG_A(i); | ||
| 515 | if (a != NO_REG) setobj(base+a, rb); | ||
| 516 | dojump(pc, *pc); | ||
| 517 | } | ||
| 518 | pc++; | ||
| 575 | break; | 519 | break; |
| 576 | } | 520 | } |
| 577 | case OP_JMPONF: { | 521 | case OP_TESTF: { |
| 578 | if (ttype(top-1) != LUA_TNIL) top--; | 522 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 579 | else dojump(pc, i); | 523 | if (ttype(RB(i)) == LUA_TNIL) { |
| 524 | int a = GETARG_A(i); | ||
| 525 | if (a != NO_REG) setnilvalue(base+a); | ||
| 526 | dojump(pc, *pc); | ||
| 527 | } | ||
| 528 | pc++; | ||
| 580 | break; | 529 | break; |
| 581 | } | 530 | } |
| 582 | case OP_JMP: { | 531 | case OP_NILJMP: { |
| 583 | dojump(pc, i); | 532 | setnilvalue(RA(i)); |
| 533 | pc++; | ||
| 584 | break; | 534 | break; |
| 585 | } | 535 | } |
| 586 | case OP_PUSHNILJMP: { | 536 | case OP_CALL: { |
| 587 | setnilvalue(top++); | 537 | int nres; |
| 588 | pc++; | 538 | int b = GETARG_B(i); |
| 539 | if (b != NO_REG) | ||
| 540 | L->top = base+b; | ||
| 541 | nres = GETARG_C(i); | ||
| 542 | if (nres == NO_REG) nres = LUA_MULTRET; | ||
| 543 | luaD_call(L, RA(i), nres); | ||
| 544 | if (nres != LUA_MULTRET) { | ||
| 545 | lua_assert(L->top == RA(i)+nres); | ||
| 546 | L->top = base+tf->maxstacksize; | ||
| 547 | } | ||
| 589 | break; | 548 | break; |
| 590 | } | 549 | } |
| 550 | case OP_RETURN: { | ||
| 551 | int b = GETARG_B(i); | ||
| 552 | if (b != NO_REG) | ||
| 553 | L->top = base+b; | ||
| 554 | return RA(i); | ||
| 555 | } | ||
| 591 | case OP_FORPREP: { | 556 | case OP_FORPREP: { |
| 592 | int jmp = GETARG_S(i); | 557 | int jmp = GETARG_sBc(i); |
| 593 | if (tonumber(top-1)) | 558 | StkId breg = RA(i); |
| 594 | luaD_error(L, l_s("`for' step must be a number")); | 559 | if (luaV_tonumber(breg, breg) == NULL) |
| 595 | if (tonumber(top-2)) | ||
| 596 | luaD_error(L, l_s("`for' limit must be a number")); | ||
| 597 | if (tonumber(top-3)) | ||
| 598 | luaD_error(L, l_s("`for' initial value must be a number")); | 560 | luaD_error(L, l_s("`for' initial value must be a number")); |
| 561 | if (luaV_tonumber(breg+1, breg+1) == NULL) | ||
| 562 | luaD_error(L, l_s("`for' limit must be a number")); | ||
| 563 | if (luaV_tonumber(breg+2, breg+2) == NULL) | ||
| 564 | luaD_error(L, l_s("`for' step must be a number")); | ||
| 599 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ | 565 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ |
| 600 | goto forloop; /* do not increment index */ | 566 | nvalue(breg) -= nvalue(breg+2);/* decrement index (to be incremented) */ |
| 567 | /* go through */ | ||
| 601 | } | 568 | } |
| 602 | case OP_FORLOOP: { | 569 | case OP_FORLOOP: { |
| 603 | lua_assert(ttype(top-1) == LUA_TNUMBER); | 570 | StkId breg = RA(i); |
| 604 | lua_assert(ttype(top-2) == LUA_TNUMBER); | 571 | if (ttype(breg) != LUA_TNUMBER) |
| 605 | if (ttype(top-3) != LUA_TNUMBER) | ||
| 606 | luaD_error(L, l_s("`for' index must be a number")); | 572 | luaD_error(L, l_s("`for' index must be a number")); |
| 607 | nvalue(top-3) += nvalue(top-1); /* increment index */ | 573 | runtime_check(L, ttype(breg+1) == LUA_TNUMBER && |
| 608 | forloop: | 574 | ttype(breg+2) == LUA_TNUMBER); |
| 609 | if (nvalue(top-1) > 0 ? | 575 | nvalue(breg) += nvalue(breg+2); /* increment index */ |
| 610 | nvalue(top-3) > nvalue(top-2) : | 576 | if (nvalue(breg+2) > 0 ? |
| 611 | nvalue(top-3) < nvalue(top-2)) | 577 | nvalue(breg) <= nvalue(breg+1) : |
| 612 | top -= 3; /* end loop: remove control variables */ | 578 | nvalue(breg) >= nvalue(breg+1)) |
| 613 | else | ||
| 614 | dojump(pc, i); /* repeat loop */ | 579 | dojump(pc, i); /* repeat loop */ |
| 615 | break; | 580 | break; |
| 616 | } | 581 | } |
| 617 | case OP_LFORPREP: { | 582 | case OP_TFORPREP: { |
| 618 | int jmp = GETARG_S(i); | 583 | int jmp = GETARG_sBc(i); |
| 619 | if (ttype(top-1) != LUA_TTABLE) | 584 | StkId breg = RA(i); |
| 585 | if (ttype(breg) != LUA_TTABLE) | ||
| 620 | luaD_error(L, l_s("`for' table must be a table")); | 586 | luaD_error(L, l_s("`for' table must be a table")); |
| 621 | top += 3; /* index,key,value */ | 587 | setnvalue(breg+1, -1); /* initial index */ |
| 622 | setnvalue(top-3, -1); /* initial index */ | 588 | setnilvalue(breg+2); |
| 623 | setnilvalue(top-2); | 589 | setnilvalue(breg+3); |
| 624 | setnilvalue(top-1); | ||
| 625 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ | 590 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ |
| 626 | /* go through */ | 591 | /* go through */ |
| 627 | } | 592 | } |
| 628 | case OP_LFORLOOP: { | 593 | case OP_TFORLOOP: { |
| 629 | Hash *t = hvalue(top-4); | 594 | StkId breg = RA(i); |
| 630 | int n = (int)nvalue(top-3); | 595 | Hash *t; |
| 631 | lua_assert(ttype(top-3) == LUA_TNUMBER); | 596 | int n; |
| 632 | lua_assert(ttype(top-4) == LUA_TTABLE); | 597 | runtime_check(L, ttype(breg) == LUA_TTABLE); |
| 598 | runtime_check(L, ttype(breg+1) == LUA_TNUMBER); | ||
| 599 | t = hvalue(breg); | ||
| 600 | n = (int)nvalue(breg+1); | ||
| 633 | n = luaH_nexti(t, n); | 601 | n = luaH_nexti(t, n); |
| 634 | if (n == -1) /* end loop? */ | 602 | if (n != -1) { /* repeat loop? */ |
| 635 | top -= 4; /* remove table, index, key, and value */ | ||
| 636 | else { | ||
| 637 | Node *node = node(t, n); | 603 | Node *node = node(t, n); |
| 638 | setnvalue(top-3, n); /* index */ | 604 | setnvalue(breg+1, n); /* index */ |
| 639 | setkey2obj(top-2, node); | 605 | setkey2obj(breg+2, node); |
| 640 | setobj(top-1, val(node)); | 606 | setobj(breg+3, val(node)); |
| 641 | dojump(pc, i); /* repeat loop */ | 607 | dojump(pc, i); /* repeat loop */ |
| 642 | } | 608 | } |
| 643 | break; | 609 | break; |
| 644 | } | 610 | } |
| 611 | case OP_SETLIST: | ||
| 612 | case OP_SETLISTO: { | ||
| 613 | int bc; | ||
| 614 | int n; | ||
| 615 | Hash *h; | ||
| 616 | StkId ra = RA(i); | ||
| 617 | runtime_check(L, ttype(ra) == LUA_TTABLE); | ||
| 618 | h = hvalue(ra); | ||
| 619 | bc = GETARG_Bc(i); | ||
| 620 | if (GET_OPCODE(i) == OP_SETLIST) | ||
| 621 | n = (bc&(LFIELDS_PER_FLUSH-1)) + 1; | ||
| 622 | else | ||
| 623 | n = L->top - ra - 1; | ||
| 624 | bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */ | ||
| 625 | for (; n > 0; n--) | ||
| 626 | setobj(luaH_setnum(L, h, bc+n), ra+n); | ||
| 627 | break; | ||
| 628 | } | ||
| 645 | case OP_CLOSURE: { | 629 | case OP_CLOSURE: { |
| 646 | int nup = GETARG_B(i); | 630 | Proto *p = tf->kproto[GETARG_Bc(i)]; |
| 647 | luaC_checkGC(L); | 631 | int nup = p->nupvalues; |
| 648 | L->top = top; | 632 | StkId ra = RA(i); |
| 649 | luaV_Lclosure(L, tf->kproto[GETARG_A(i)], nup); | 633 | L->top = ra+nup; |
| 650 | top -= (nup-1); | 634 | luaV_Lclosure(L, p, nup); |
| 651 | L->top = base+tf->maxstacksize; | 635 | L->top = base+tf->maxstacksize; |
| 636 | luaC_checkGC(L); | ||
| 652 | break; | 637 | break; |
| 653 | } | 638 | } |
| 654 | } | 639 | } |
| 655 | } | 640 | } |
| 656 | } | 641 | } |
| 642 | |||
