Showing the changes to src/lcode.c (1 of 60 files). Show all
Unified · Split
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lcode.c,v 2.71 2013/06/25 18:57:18 roberto Exp $ | |
| 2 | +** $Id: lcode.c,v 2.85 2014/03/21 13:52:33 roberto Exp $ | |
| 3 | 3 | ** Code generator for Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -307,17 +307,21 @@ static void freeexp (FuncState *fs, expdesc *e) { · 301 unmodified lines | ||
| 307 | 307 | } |
| 308 | 308 | |
| 309 | 309 | |
| 310 | +/* | |
| 311 | +** Use scanner's table to cache position of constants in constant list | |
| 312 | +** and try to reuse constants | |
| 313 | +*/ | |
| 310 | 314 | static int addk (FuncState *fs, TValue *key, TValue *v) { |
| 311 | 315 | lua_State *L = fs->ls->L; |
| 312 | − TValue *idx = luaH_set(L, fs->h, key); | |
| 313 | 316 | Proto *f = fs->f; |
| 317 | + TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ | |
| 314 | 318 | int k, oldsize; |
| 315 | − if (ttisinteger(idx)) { | |
| 319 | + if (ttisinteger(idx)) { /* is there an index there? */ | |
| 316 | 320 | k = ivalue(idx); |
| 317 | − if (luaV_rawequalobj(&f->k[k], v)) | |
| 318 | − return k; | |
| 319 | − /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); | |
| 320 | − go through and create a new entry for this value */ | |
| 321 | + /* correct value? (warning: must distinguish floats from integers!) */ | |
| 322 | + if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && | |
| 323 | + luaV_rawequalobj(&f->k[k], v)) | |
| 324 | + return k; /* reuse index */ | |
| 321 | 325 | } |
| 322 | 326 | /* constant not found; create a new entry */ |
| 323 | 327 | oldsize = f->sizek; |
| @@ -360,7 +364,7 @@ int luaK_intK (FuncState *fs, lua_Integer n) { · 36 unmodified lines | ||
| 360 | 364 | */ |
| 361 | 365 | static int luaK_numberK (FuncState *fs, lua_Number r) { |
| 362 | 366 | TValue o; |
| 363 | − lua_assert(!luai_numisnan(NULL, r) && !isminuszero(r)); | |
| 367 | + lua_assert(!luai_numisnan(r) && !isminuszero(r)); | |
| 364 | 368 | setnvalue(&o, r); |
| 365 | 369 | return addk(fs, &o, &o); |
| 366 | 370 | } |
| @@ -377,7 +381,7 @@ static int nilK (FuncState *fs) { · 10 unmodified lines | ||
| 377 | 381 | TValue k, v; |
| 378 | 382 | setnilvalue(&v); |
| 379 | 383 | /* cannot use nil as key; instead use table itself to represent nil */ |
| 380 | − sethvalue(fs->ls->L, &k, fs->h); | |
| 384 | + sethvalue(fs->ls->L, &k, fs->ls->h); | |
| 381 | 385 | return addk(fs, &k, &v); |
| 382 | 386 | } |
| 383 | 387 | |
| @@ -746,24 +750,46 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { · 362 unmodified lines | ||
| 746 | 750 | } |
| 747 | 751 | |
| 748 | 752 | |
| 749 | −static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { | |
| 750 | − TValue v1, v2, res; | |
| 753 | +/* | |
| 754 | +** return false if folding can raise an error | |
| 755 | +*/ | |
| 756 | +static int validop (int op, TValue *v1, TValue *v2) { | |
| 757 | + lua_Number a, b; | |
| 751 | 758 | lua_Integer i; |
| 752 | − if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2)) | |
| 759 | + cast_void(a); cast_void(b); /* macro may not use its arguments */ | |
| 760 | + if (luai_numinvalidop(op, (cast_void(tonumber(v1, &a)), a), | |
| 761 | + (cast_void(tonumber(v2, &b)), b))) | |
| 753 | 762 | return 0; |
| 754 | − if (op == OP_IDIV && | |
| 755 | − (!tointeger(&v1, &i) || !tointeger(&v2, &i) || i == 0)) | |
| 756 | − return 0; /* avoid division by 0 and conversion errors */ | |
| 757 | − if (op == OP_MOD && ttisinteger(&v1) && ttisinteger(&v2) && ivalue(&v2) == 0) | |
| 758 | − return 0; /* avoid module by 0 at compile time */ | |
| 759 | − luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res); | |
| 763 | + switch (op) { | |
| 764 | + case LUA_OPIDIV: /* division by 0 and conversion errors */ | |
| 765 | + return (tointeger(v1, &i) && tointeger(v2, &i) && i != 0); | |
| 766 | + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: | |
| 767 | + case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: /* conversion errors */ | |
| 768 | + return (tointeger(v1, &i) && tointeger(v2, &i)); | |
| 769 | + case LUA_OPMOD: /* integer module by 0 */ | |
| 770 | + return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) == 0); | |
| 771 | + case LUA_OPPOW: /* negative integer exponentiation */ | |
| 772 | + return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) < 0); | |
| 773 | + default: return 1; /* everything else is valid */ | |
| 774 | + } | |
| 775 | +} | |
| 776 | + | |
| 777 | + | |
| 778 | +/* | |
| 779 | +** Try to "constant-fold" an operation; return 1 iff successful | |
| 780 | +*/ | |
| 781 | +static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) { | |
| 782 | + TValue v1, v2, res; | |
| 783 | + if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) | |
| 784 | + return 0; /* non-numeric operands or not safe to fold */ | |
| 785 | + luaO_arith(fs->ls->L, op, &v1, &v2, &res); | |
| 760 | 786 | if (ttisinteger(&res)) { |
| 761 | 787 | e1->k = VKINT; |
| 762 | 788 | e1->u.ival = ivalue(&res); |
| 763 | 789 | } |
| 764 | 790 | else { |
| 765 | 791 | lua_Number n = fltvalue(&res); |
| 766 | − if (luai_numisnan(NULL, n) || isminuszero(n)) | |
| 792 | + if (luai_numisnan(n) || isminuszero(n)) | |
| 767 | 793 | return 0; /* folds neither NaN nor -0 */ |
| 768 | 794 | e1->k = VKFLT; |
| 769 | 795 | e1->u.nval = n; |
| @@ -774,9 +800,16 @@ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { · 4 unmodified lines | ||
| 774 | 800 | |
| 775 | 801 | static void codearith (FuncState *fs, OpCode op, |
| 776 | 802 | expdesc *e1, expdesc *e2, int line) { |
| 777 | − if (!constfolding(op, e1, e2)) { /* could not fold operation? */ | |
| 778 | − int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; | |
| 779 | − int o1 = luaK_exp2RK(fs, e1); | |
| 803 | + if (!constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2)) { | |
| 804 | + int o1, o2; | |
| 805 | + if (op == OP_UNM || op == OP_BNOT || op == OP_LEN) { | |
| 806 | + o2 = 0; | |
| 807 | + o1 = luaK_exp2anyreg(fs, e1); /* cannot operate on constants */ | |
| 808 | + } | |
| 809 | + else { /* regular case (binary operators) */ | |
| 810 | + o2 = luaK_exp2RK(fs, e2); | |
| 811 | + o1 = luaK_exp2RK(fs, e1); | |
| 812 | + } | |
| 780 | 813 | if (o1 > o2) { |
| 781 | 814 | freeexp(fs, e1); |
| 782 | 815 | freeexp(fs, e2); |
| @@ -810,21 +843,13 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, · 27 unmodified lines | ||
| 810 | 843 | |
| 811 | 844 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { |
| 812 | 845 | expdesc e2; |
| 813 | − e2.t = e2.f = NO_JUMP; e2.k = VKFLT; e2.u.nval = 0; | |
| 846 | + e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0; | |
| 814 | 847 | switch (op) { |
| 815 | − case OPR_MINUS: { | |
| 816 | − if (!constfolding(OP_UNM, e, e)) { /* cannot fold it? */ | |
| 817 | − luaK_exp2anyreg(fs, e); | |
| 818 | − codearith(fs, OP_UNM, e, &e2, line); | |
| 819 | − } | |
| 848 | + case OPR_MINUS: case OPR_BNOT: case OPR_LEN: { | |
| 849 | + codearith(fs, cast(OpCode, (op - OPR_MINUS) + OP_UNM), e, &e2, line); | |
| 820 | 850 | break; |
| 821 | 851 | } |
| 822 | 852 | case OPR_NOT: codenot(fs, e); break; |
| 823 | − case OPR_LEN: { | |
| 824 | − luaK_exp2anyreg(fs, e); /* cannot operate on constants */ | |
| 825 | − codearith(fs, OP_LEN, e, &e2, line); | |
| 826 | − break; | |
| 827 | − } | |
| 828 | 853 | default: lua_assert(0); |
| 829 | 854 | } |
| 830 | 855 | } |
| @@ -846,7 +871,9 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { · 15 unmodified lines | ||
| 846 | 871 | } |
| 847 | 872 | case OPR_ADD: case OPR_SUB: |
| 848 | 873 | case OPR_MUL: case OPR_DIV: case OPR_IDIV: |
| 849 | − case OPR_MOD: case OPR_POW: { | |
| 874 | + case OPR_MOD: case OPR_POW: | |
| 875 | + case OPR_BAND: case OPR_BOR: case OPR_BXOR: | |
| 876 | + case OPR_SHL: case OPR_SHR: { | |
| 850 | 877 | if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v); |
| 851 | 878 | break; |
| 852 | 879 | } |
| @@ -890,8 +917,10 @@ void luaK_posfix (FuncState *fs, BinOpr op, · 37 unmodified lines | ||
| 890 | 917 | break; |
| 891 | 918 | } |
| 892 | 919 | case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: |
| 893 | − case OPR_IDIV: case OPR_MOD: case OPR_POW: { | |
| 894 | − codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); | |
| 920 | + case OPR_IDIV: case OPR_MOD: case OPR_POW: | |
| 921 | + case OPR_BAND: case OPR_BOR: case OPR_BXOR: | |
| 922 | + case OPR_SHL: case OPR_SHR: { | |
| 923 | + codearith(fs, cast(OpCode, (op - OPR_ADD) + OP_ADD), e1, e2, line); | |
| 895 | 924 | break; |
| 896 | 925 | } |
| 897 | 926 | case OPR_EQ: case OPR_LT: case OPR_LE: { |