Showing the changes to src/lcode.c (1 of 86 files). Show all
Unified · Split
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ | |
| 2 | +** $Id: lcode.c,v 2.42 2009/09/23 20:33:05 roberto Exp $ | |
| 3 | 3 | ** Code generator for Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -21,6 +21,7 @@ · 15 unmodified lines | ||
| 21 | 21 | #include "lobject.h" |
| 22 | 22 | #include "lopcodes.h" |
| 23 | 23 | #include "lparser.h" |
| 24 | +#include "lstring.h" | |
| 24 | 25 | #include "ltable.h" |
| 25 | 26 | |
| 26 | 27 | |
| @@ -35,20 +36,14 @@ static int isnumeral(expdesc *e) { · 8 unmodified lines | ||
| 35 | 36 | void luaK_nil (FuncState *fs, int from, int n) { |
| 36 | 37 | Instruction *previous; |
| 37 | 38 | if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ |
| 38 | − if (fs->pc == 0) { /* function start? */ | |
| 39 | − if (from >= fs->nactvar) | |
| 40 | − return; /* positions are already clean */ | |
| 41 | − } | |
| 42 | − else { | |
| 43 | − previous = &fs->f->code[fs->pc-1]; | |
| 44 | − if (GET_OPCODE(*previous) == OP_LOADNIL) { | |
| 45 | − int pfrom = GETARG_A(*previous); | |
| 46 | − int pto = GETARG_B(*previous); | |
| 47 | − if (pfrom <= from && from <= pto+1) { /* can connect both? */ | |
| 48 | − if (from+n-1 > pto) | |
| 49 | − SETARG_B(*previous, from+n-1); | |
| 50 | − return; | |
| 51 | − } | |
| 39 | + previous = &fs->f->code[fs->pc-1]; | |
| 40 | + if (GET_OPCODE(*previous) == OP_LOADNIL) { | |
| 41 | + int pfrom = GETARG_A(*previous); | |
| 42 | + int pto = GETARG_B(*previous); | |
| 43 | + if (pfrom <= from && from <= pto+1) { /* can connect both? */ | |
| 44 | + if (from+n-1 > pto) | |
| 45 | + SETARG_B(*previous, from+n-1); | |
| 46 | + return; | |
| 52 | 47 | } |
| 53 | 48 | } |
| 54 | 49 | } |
| @@ -196,6 +191,55 @@ void luaK_concat (FuncState *fs, int *l1, int l2) { · 141 unmodified lines | ||
| 196 | 191 | } |
| 197 | 192 | |
| 198 | 193 | |
| 194 | +static int luaK_code (FuncState *fs, Instruction i) { | |
| 195 | + Proto *f = fs->f; | |
| 196 | + dischargejpc(fs); /* `pc' will change */ | |
| 197 | + /* put new instruction in code array */ | |
| 198 | + luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, | |
| 199 | + MAX_INT, "opcodes"); | |
| 200 | + f->code[fs->pc] = i; | |
| 201 | + /* save corresponding line information */ | |
| 202 | + luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, | |
| 203 | + MAX_INT, "opcodes"); | |
| 204 | + f->lineinfo[fs->pc] = fs->ls->lastline; | |
| 205 | + return fs->pc++; | |
| 206 | +} | |
| 207 | + | |
| 208 | + | |
| 209 | +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { | |
| 210 | + lua_assert(getOpMode(o) == iABC); | |
| 211 | + lua_assert(getBMode(o) != OpArgN || b == 0); | |
| 212 | + lua_assert(getCMode(o) != OpArgN || c == 0); | |
| 213 | + lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); | |
| 214 | + return luaK_code(fs, CREATE_ABC(o, a, b, c)); | |
| 215 | +} | |
| 216 | + | |
| 217 | + | |
| 218 | +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { | |
| 219 | + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); | |
| 220 | + lua_assert(getCMode(o) == OpArgN); | |
| 221 | + lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); | |
| 222 | + return luaK_code(fs, CREATE_ABx(o, a, bc)); | |
| 223 | +} | |
| 224 | + | |
| 225 | + | |
| 226 | +static int codeextraarg (FuncState *fs, int a) { | |
| 227 | + lua_assert(a <= MAXARG_Ax); | |
| 228 | + return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); | |
| 229 | +} | |
| 230 | + | |
| 231 | + | |
| 232 | +int luaK_codeABxX (FuncState *fs, OpCode o, int reg, int k) { | |
| 233 | + if (k < MAXARG_Bx) | |
| 234 | + return luaK_codeABx(fs, o, reg, k + 1); | |
| 235 | + else { | |
| 236 | + int p = luaK_codeABx(fs, o, reg, 0); | |
| 237 | + codeextraarg(fs, k); | |
| 238 | + return p; | |
| 239 | + } | |
| 240 | +} | |
| 241 | + | |
| 242 | + | |
| 199 | 243 | void luaK_checkstack (FuncState *fs, int n) { |
| 200 | 244 | int newstack = fs->freereg + n; |
| 201 | 245 | if (newstack > fs->f->maxstacksize) { |
| @@ -226,24 +270,29 @@ static void freeexp (FuncState *fs, expdesc *e) { · 24 unmodified lines | ||
| 226 | 270 | } |
| 227 | 271 | |
| 228 | 272 | |
| 229 | −static int addk (FuncState *fs, TValue *k, TValue *v) { | |
| 273 | +static int addk (FuncState *fs, TValue *key, TValue *v) { | |
| 230 | 274 | lua_State *L = fs->L; |
| 231 | − TValue *idx = luaH_set(L, fs->h, k); | |
| 275 | + TValue *idx = luaH_set(L, fs->h, key); | |
| 232 | 276 | Proto *f = fs->f; |
| 233 | − int oldsize = f->sizek; | |
| 277 | + int k, oldsize; | |
| 234 | 278 | if (ttisnumber(idx)) { |
| 235 | − lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); | |
| 236 | − return cast_int(nvalue(idx)); | |
| 237 | − } | |
| 238 | − else { /* constant not found; create a new entry */ | |
| 239 | − setnvalue(idx, cast_num(fs->nk)); | |
| 240 | − luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, | |
| 241 | − MAXARG_Bx, "constant table overflow"); | |
| 242 | − while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | |
| 243 | − setobj(L, &f->k[fs->nk], v); | |
| 244 | − luaC_barrier(L, f, v); | |
| 245 | − return fs->nk++; | |
| 279 | + lua_Number n = nvalue(idx); | |
| 280 | + lua_number2int(k, n); | |
| 281 | + if (luaO_rawequalObj(&f->k[k], v)) | |
| 282 | + return k; | |
| 283 | + /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); | |
| 284 | + go through and create a new entry for this value */ | |
| 246 | 285 | } |
| 286 | + /* constant not found; create a new entry */ | |
| 287 | + oldsize = f->sizek; | |
| 288 | + k = fs->nk; | |
| 289 | + setnvalue(idx, cast_num(k)); | |
| 290 | + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); | |
| 291 | + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | |
| 292 | + setobj(L, &f->k[k], v); | |
| 293 | + fs->nk++; | |
| 294 | + luaC_barrier(L, f, v); | |
| 295 | + return k; | |
| 247 | 296 | } |
| 248 | 297 | |
| 249 | 298 | |
| @@ -255,9 +304,20 @@ int luaK_stringK (FuncState *fs, TString *s) { · 5 unmodified lines | ||
| 255 | 304 | |
| 256 | 305 | |
| 257 | 306 | int luaK_numberK (FuncState *fs, lua_Number r) { |
| 307 | + int n; | |
| 308 | + lua_State *L = fs->L; | |
| 258 | 309 | TValue o; |
| 259 | 310 | setnvalue(&o, r); |
| 260 | − return addk(fs, &o, &o); | |
| 311 | + if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ | |
| 312 | + /* use raw representation as key to avoid numeric problems */ | |
| 313 | + setsvalue(L, L->top, luaS_newlstr(L, (char *)&r, sizeof(r))); | |
| 314 | + incr_top(L); | |
| 315 | + n = addk(fs, L->top - 1, &o); | |
| 316 | + L->top--; | |
| 317 | + } | |
| 318 | + else | |
| 319 | + n = addk(fs, &o, &o); /* regular case */ | |
| 320 | + return n; | |
| 261 | 321 | } |
| 262 | 322 | |
| 263 | 323 | |
| @@ -313,7 +373,7 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { · 49 unmodified lines | ||
| 313 | 373 | break; |
| 314 | 374 | } |
| 315 | 375 | case VGLOBAL: { |
| 316 | − e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); | |
| 376 | + e->u.s.info = luaK_codeABxX(fs, OP_GETGLOBAL, 0, e->u.s.info); | |
| 317 | 377 | e->k = VRELOCABLE; |
| 318 | 378 | break; |
| 319 | 379 | } |
| @@ -352,11 +412,11 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { · 32 unmodified lines | ||
| 352 | 412 | break; |
| 353 | 413 | } |
| 354 | 414 | case VK: { |
| 355 | − luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); | |
| 415 | + luaK_codek(fs, reg, e->u.s.info); | |
| 356 | 416 | break; |
| 357 | 417 | } |
| 358 | 418 | case VKNUM: { |
| 359 | − luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); | |
| 419 | + luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); | |
| 360 | 420 | break; |
| 361 | 421 | } |
| 362 | 422 | case VRELOCABLE: { |
| @@ -444,19 +504,21 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { · 81 unmodified lines | ||
| 444 | 504 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
| 445 | 505 | luaK_exp2val(fs, e); |
| 446 | 506 | switch (e->k) { |
| 447 | − case VKNUM: | |
| 448 | 507 | case VTRUE: |
| 449 | 508 | case VFALSE: |
| 450 | 509 | case VNIL: { |
| 451 | 510 | if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ |
| 452 | − e->u.s.info = (e->k == VNIL) ? nilK(fs) : | |
| 453 | − (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : | |
| 454 | − boolK(fs, (e->k == VTRUE)); | |
| 511 | + e->u.s.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); | |
| 455 | 512 | e->k = VK; |
| 456 | 513 | return RKASK(e->u.s.info); |
| 457 | 514 | } |
| 458 | 515 | else break; |
| 459 | 516 | } |
| 517 | + case VKNUM: { | |
| 518 | + e->u.s.info = luaK_numberK(fs, e->u.nval); | |
| 519 | + e->k = VK; | |
| 520 | + /* go through */ | |
| 521 | + } | |
| 460 | 522 | case VK: { |
| 461 | 523 | if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ |
| 462 | 524 | return RKASK(e->u.s.info); |
| @@ -483,7 +545,7 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { · 20 unmodified lines | ||
| 483 | 545 | } |
| 484 | 546 | case VGLOBAL: { |
| 485 | 547 | int e = luaK_exp2anyreg(fs, ex); |
| 486 | − luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); | |
| 548 | + luaK_codeABxX(fs, OP_SETGLOBAL, e, var->u.s.info); | |
| 487 | 549 | break; |
| 488 | 550 | } |
| 489 | 551 | case VINDEXED: { |
| @@ -544,15 +606,18 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { · 54 unmodified lines | ||
| 544 | 606 | pc = NO_JUMP; /* always true; do nothing */ |
| 545 | 607 | break; |
| 546 | 608 | } |
| 547 | − case VFALSE: { | |
| 548 | − pc = luaK_jump(fs); /* always jump */ | |
| 549 | − break; | |
| 550 | − } | |
| 551 | 609 | case VJMP: { |
| 552 | 610 | invertjump(fs, e); |
| 553 | 611 | pc = e->u.s.info; |
| 554 | 612 | break; |
| 555 | 613 | } |
| 614 | + case VFALSE: { | |
| 615 | + if (!hasjumps(e)) { | |
| 616 | + pc = luaK_jump(fs); /* always jump */ | |
| 617 | + break; | |
| 618 | + } | |
| 619 | + /* else go through */ | |
| 620 | + } | |
| 556 | 621 | default: { |
| 557 | 622 | pc = jumponcond(fs, e, 0); |
| 558 | 623 | break; |
| @@ -572,14 +637,17 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) { · 13 unmodified lines | ||
| 572 | 637 | pc = NO_JUMP; /* always false; do nothing */ |
| 573 | 638 | break; |
| 574 | 639 | } |
| 575 | − case VTRUE: { | |
| 576 | − pc = luaK_jump(fs); /* always jump */ | |
| 577 | − break; | |
| 578 | − } | |
| 579 | 640 | case VJMP: { |
| 580 | 641 | pc = e->u.s.info; |
| 581 | 642 | break; |
| 582 | 643 | } |
| 644 | + case VTRUE: { | |
| 645 | + if (!hasjumps(e)) { | |
| 646 | + pc = luaK_jump(fs); /* always jump */ | |
| 647 | + break; | |
| 648 | + } | |
| 649 | + /* else go through */ | |
| 650 | + } | |
| 583 | 651 | default: { |
| 584 | 652 | pc = jumponcond(fs, e, 1); |
| 585 | 653 | break; |
| @@ -633,26 +701,11 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { · 47 unmodified lines | ||
| 633 | 701 | |
| 634 | 702 | |
| 635 | 703 | static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { |
| 636 | − lua_Number v1, v2, r; | |
| 704 | + lua_Number r; | |
| 637 | 705 | if (!isnumeral(e1) || !isnumeral(e2)) return 0; |
| 638 | − v1 = e1->u.nval; | |
| 639 | − v2 = e2->u.nval; | |
| 640 | − switch (op) { | |
| 641 | − case OP_ADD: r = luai_numadd(v1, v2); break; | |
| 642 | − case OP_SUB: r = luai_numsub(v1, v2); break; | |
| 643 | − case OP_MUL: r = luai_nummul(v1, v2); break; | |
| 644 | − case OP_DIV: | |
| 645 | − if (v2 == 0) return 0; /* do not attempt to divide by 0 */ | |
| 646 | − r = luai_numdiv(v1, v2); break; | |
| 647 | − case OP_MOD: | |
| 648 | − if (v2 == 0) return 0; /* do not attempt to divide by 0 */ | |
| 649 | − r = luai_nummod(v1, v2); break; | |
| 650 | − case OP_POW: r = luai_numpow(v1, v2); break; | |
| 651 | − case OP_UNM: r = luai_numunm(v1); break; | |
| 652 | − case OP_LEN: return 0; /* no constant folding for 'len' */ | |
| 653 | − default: lua_assert(0); r = 0; break; | |
| 654 | − } | |
| 655 | − if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ | |
| 706 | + if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) | |
| 707 | + return 0; /* do not attempt to divide by 0 */ | |
| 708 | + r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); | |
| 656 | 709 | e1->u.nval = r; |
| 657 | 710 | return 1; |
| 658 | 711 | } |
| @@ -699,9 +752,12 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { · 40 unmodified lines | ||
| 699 | 752 | e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; |
| 700 | 753 | switch (op) { |
| 701 | 754 | case OPR_MINUS: { |
| 702 | − if (!isnumeral(e)) | |
| 703 | − luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ | |
| 704 | − codearith(fs, OP_UNM, e, &e2); | |
| 755 | + if (isnumeral(e)) /* minus constant? */ | |
| 756 | + e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ | |
| 757 | + else { | |
| 758 | + luaK_exp2anyreg(fs, e); | |
| 759 | + codearith(fs, OP_UNM, e, &e2); | |
| 760 | + } | |
| 705 | 761 | break; |
| 706 | 762 | } |
| 707 | 763 | case OPR_NOT: codenot(fs, e); break; |
| @@ -772,18 +828,19 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { · 64 unmodified lines | ||
| 772 | 828 | } |
| 773 | 829 | break; |
| 774 | 830 | } |
| 775 | − case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; | |
| 776 | − case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; | |
| 777 | − case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; | |
| 778 | − case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; | |
| 779 | − case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; | |
| 780 | − case OPR_POW: codearith(fs, OP_POW, e1, e2); break; | |
| 781 | − case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; | |
| 782 | − case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; | |
| 783 | − case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; | |
| 784 | − case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; | |
| 785 | − case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; | |
| 786 | − case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; | |
| 831 | + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: | |
| 832 | + case OPR_MOD: case OPR_POW: { | |
| 833 | + codearith(fs, op - OPR_ADD + OP_ADD, e1, e2); | |
| 834 | + break; | |
| 835 | + } | |
| 836 | + case OPR_EQ: case OPR_LT: case OPR_LE: { | |
| 837 | + codecomp(fs, op - OPR_EQ + OP_EQ, 1, e1, e2); | |
| 838 | + break; | |
| 839 | + } | |
| 840 | + case OPR_NE: case OPR_GT: case OPR_GE: { | |
| 841 | + codecomp(fs, op - OPR_NE + OP_EQ, 0, e1, e2); | |
| 842 | + break; | |
| 843 | + } | |
| 787 | 844 | default: lua_assert(0); |
| 788 | 845 | } |
| 789 | 846 | } |
| @@ -794,46 +851,18 @@ void luaK_fixline (FuncState *fs, int line) { · 4 unmodified lines | ||
| 794 | 851 | } |
| 795 | 852 | |
| 796 | 853 | |
| 797 | −static int luaK_code (FuncState *fs, Instruction i, int line) { | |
| 798 | − Proto *f = fs->f; | |
| 799 | − dischargejpc(fs); /* `pc' will change */ | |
| 800 | − /* put new instruction in code array */ | |
| 801 | − luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, | |
| 802 | − MAX_INT, "code size overflow"); | |
| 803 | − f->code[fs->pc] = i; | |
| 804 | − /* save corresponding line information */ | |
| 805 | − luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, | |
| 806 | − MAX_INT, "code size overflow"); | |
| 807 | − f->lineinfo[fs->pc] = line; | |
| 808 | − return fs->pc++; | |
| 809 | −} | |
| 810 | − | |
| 811 | − | |
| 812 | −int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { | |
| 813 | − lua_assert(getOpMode(o) == iABC); | |
| 814 | − lua_assert(getBMode(o) != OpArgN || b == 0); | |
| 815 | − lua_assert(getCMode(o) != OpArgN || c == 0); | |
| 816 | − return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); | |
| 817 | −} | |
| 818 | − | |
| 819 | − | |
| 820 | −int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { | |
| 821 | − lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); | |
| 822 | − lua_assert(getCMode(o) == OpArgN); | |
| 823 | − return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); | |
| 824 | −} | |
| 825 | − | |
| 826 | − | |
| 827 | 854 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { |
| 828 | 855 | int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; |
| 829 | 856 | int b = (tostore == LUA_MULTRET) ? 0 : tostore; |
| 830 | 857 | lua_assert(tostore != 0); |
| 831 | 858 | if (c <= MAXARG_C) |
| 832 | 859 | luaK_codeABC(fs, OP_SETLIST, base, b, c); |
| 833 | − else { | |
| 860 | + else if (c <= MAXARG_Ax) { | |
| 834 | 861 | luaK_codeABC(fs, OP_SETLIST, base, b, 0); |
| 835 | − luaK_code(fs, cast(Instruction, c), fs->ls->lastline); | |
| 862 | + codeextraarg(fs, c); | |
| 836 | 863 | } |
| 864 | + else | |
| 865 | + luaX_syntaxerror(fs->ls, "constructor too long"); | |
| 837 | 866 | fs->freereg = base + 1; /* free registers with list values */ |
| 838 | 867 | } |
| 839 | 868 | |