diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-10-01 17:24:37 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-10-01 17:24:37 -0300 |
commit | b2a580bdb1982e45bb37f95b78c2dafec6efa7a6 (patch) | |
tree | 76de58214adff838a26346514a8a6fba459bde9b | |
parent | 89f6a85f034b2535e43e421991098fa05a92cd60 (diff) | |
download | lua-github-b2a580bdb1982e45bb37f95b78c2dafec6efa7a6.tar.gz |
Janitorial work
- Several details in 'lcode.c'
- A few more tests for code generation
- Bug in assert in 'lcode.c' ("=" x "==")
- Comments in 'lopcodes.h' and 'ltable.c'
-rw-r--r-- | lcode.c | 61 | ||||
-rw-r--r-- | lopcodes.h | 8 | ||||
-rw-r--r-- | ltable.c | 44 | ||||
-rw-r--r-- | testes/code.lua | 7 |
4 files changed, 62 insertions, 58 deletions
@@ -359,12 +359,12 @@ static void removelastlineinfo (FuncState *fs) { Proto *f = fs->f; int pc = fs->pc - 1; /* last instruction coded */ if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */ - fs->previousline -= f->lineinfo[pc]; /* last line saved */ - fs->iwthabs--; + fs->previousline -= f->lineinfo[pc]; /* correct last line saved */ + fs->iwthabs--; /* undo previous increment */ } else { /* absolute line information */ + lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == pc); fs->nabslineinfo--; /* remove it */ - lua_assert(f->abslineinfo[fs->nabslineinfo].pc = pc); fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */ } } @@ -626,12 +626,12 @@ static int nilK (FuncState *fs) { /* -** Check whether 'i' can be stored in an 'sC' operand. -** Equivalent to (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) -** but without risk of overflows in the addition. +** Check whether 'i' can be stored in an 'sC' operand. Equivalent to +** (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) but without risk of +** overflows in the hidden addition inside 'int2sC'. */ static int fitsC (lua_Integer i) { - return (-OFFSET_sC <= i && i <= MAXARG_C - OFFSET_sC); + return (l_castS2U(i) + OFFSET_sC <= cast_uint(MAXARG_C)); } @@ -1213,15 +1213,6 @@ static int isSCint (expdesc *e) { /* -** Check whether expression 'e' and its negation are literal integers -** in proper range to fit in register sC -*/ -static int isSCintN (expdesc *e) { - return luaK_isKint(e) && fitsC(e->u.ival) && fitsC(-e->u.ival); -} - - -/* ** Check whether expression 'e' is a literal integer or float in ** proper range to fit in a register (sB or sC). */ @@ -1382,15 +1373,25 @@ static void codebini (FuncState *fs, OpCode op, } -/* Code binary operators negating the immediate operand for the -** opcode. For the metamethod, 'v2' must keep its original value. +/* Try to code a binary operator negating its second operand. +** For the metamethod, 2nd operand must keep its original value. */ -static void finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, +static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, OpCode op, int line, TMS event) { - int v2 = cast_int(e2->u.ival); - finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); - /* correct metamethod argument */ - SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2)); + if (!luaK_isKint(e2)) + return 0; /* not an integer constant */ + else { + lua_Integer i2 = e2->u.ival; + if (!(fitsC(i2) && fitsC(-i2))) + return 0; /* not in the proper range */ + else { /* operating a small integer constant */ + int v2 = cast_int(i2); + finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); + /* correct metamethod argument */ + SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2)); + return 1; /* successfully coded */ + } + } } @@ -1647,11 +1648,8 @@ void luaK_posfix (FuncState *fs, BinOpr opr, break; } case OPR_SUB: { - if (isSCintN(e2)) { /* subtracting a small integer constant? */ - /* code it as (r1 + -I) */ - finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB); - break; - } + if (finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB)) + break; /* coded as (r1 + -I) */ /* ELSE *//* FALLTHROUGH */ } case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { @@ -1667,16 +1665,15 @@ void luaK_posfix (FuncState *fs, BinOpr opr, swapexps(e1, e2); codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */ } - else if (isSCintN(e2)) { /* shifting by a small integer constant? */ - /* code it as (r1 >> -I) */ - finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL); + else if (finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL)) { + /* coded as (r1 >> -I) */; } else /* regular case (two registers) */ codebinexpval(fs, OP_SHL, e1, e2, line); break; } case OPR_SHR: { - if (isSCintN(e2)) + if (isSCint(e2)) codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ else /* regular case (two registers) */ codebinexpval(fs, OP_SHR, e1, e2, line); @@ -221,7 +221,7 @@ OP_NEWTABLE,/* A B C R(A) := {} */ OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */ -OP_ADDI,/* A B sC R(A) := R(B) + C */ +OP_ADDI,/* A B sC R(A) := R(B) + sC */ OP_ADDK,/* A B C R(A) := R(B) + K(C) */ OP_SUBK,/* A B C R(A) := R(B) - K(C) */ @@ -235,8 +235,8 @@ OP_BANDK,/* A B C R(A) := R(B) & K(C):integer */ OP_BORK,/* A B C R(A) := R(B) | K(C):integer */ OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */ -OP_SHRI,/* A B sC R(A) := R(B) >> C */ -OP_SHLI,/* A B sC R(A) := C << R(B) */ +OP_SHRI,/* A B sC R(A) := R(B) >> sC */ +OP_SHLI,/* A B sC R(A) := sC << R(B) */ OP_ADD,/* A B C R(A) := R(B) + R(C) */ OP_SUB,/* A B C R(A) := R(B) - R(C) */ @@ -253,7 +253,7 @@ OP_SHL,/* A B C R(A) := R(B) << R(C) */ OP_SHR,/* A B C R(A) := R(B) >> R(C) */ OP_MMBIN,/* A B C call C metamethod over R(A) and R(B) */ -OP_MMBINI,/* A B C call C metamethod over R(A) and B */ +OP_MMBINI,/* A sB C call C metamethod over R(A) and sB */ OP_MMBINK,/* A B C call C metamethod over R(A) and K(B) */ OP_UNM,/* A B R(A) := -R(B) */ @@ -833,39 +833,41 @@ static unsigned int binsearch (const TValue *array, unsigned int i, ** and 'maxinteger' if t[maxinteger] is present.) ** (In the next explanation, we use Lua indices, that is, with base 1. ** The code itself uses base 0 when indexing the array part of the table.) -** The code starts with 'limit', a position in the array part that may -** be a boundary. +** The code starts with 'limit = t->alimit', a position in the array +** part that may be a boundary. +** ** (1) If 't[limit]' is empty, there must be a boundary before it. -** As a common case (e.g., after 't[#t]=nil'), check whether 'hint-1' +** As a common case (e.g., after 't[#t]=nil'), check whether 'limit-1' ** is present. If so, it is a boundary. Otherwise, do a binary search ** between 0 and limit to find a boundary. In both cases, try to -** use this boundary as the new 'limit', as a hint for the next call. +** use this boundary as the new 'alimit', as a hint for the next call. +** ** (2) If 't[limit]' is not empty and the array has more elements ** after 'limit', try to find a boundary there. Again, try first ** the special case (which should be quite frequent) where 'limit+1' ** is empty, so that 'limit' is a boundary. Otherwise, check the -** last element of the array part (set it as a new limit). If it is empty, -** there must be a boundary between the old limit (present) and the new -** limit (absent), which is found with a binary search. (This boundary -** always can be a new limit.) +** last element of the array part. If it is empty, there must be a +** boundary between the old limit (present) and the last element +** (absent), which is found with a binary search. (This boundary always +** can be a new limit.) +** ** (3) The last case is when there are no elements in the array part ** (limit == 0) or its last element (the new limit) is present. -** In this case, must check the hash part. If there is no hash part, -** the boundary is 0. Otherwise, if 'limit+1' is absent, 'limit' is -** a boundary. Finally, if 'limit+1' is present, call 'hash_search' -** to find a boundary in the hash part of the table. (In those -** cases, the boundary is not inside the array part, and therefore -** cannot be used as a new limit.) +** In this case, must check the hash part. If there is no hash part +** or 'limit+1' is absent, 'limit' is a boundary. Otherwise, call +** 'hash_search' to find a boundary in the hash part of the table. +** (In those cases, the boundary is not inside the array part, and +** therefore cannot be used as a new limit.) */ lua_Unsigned luaH_getn (Table *t) { unsigned int limit = t->alimit; - if (limit > 0 && isempty(&t->array[limit - 1])) { - /* (1) there must be a boundary before 'limit' */ + if (limit > 0 && isempty(&t->array[limit - 1])) { /* (1)? */ + /* there must be a boundary before 'limit' */ if (limit >= 2 && !isempty(&t->array[limit - 2])) { /* 'limit - 1' is a boundary; can it be a new limit? */ if (ispow2realasize(t) && !ispow2(limit - 1)) { t->alimit = limit - 1; - setnorealasize(t); + setnorealasize(t); /* now 'alimit' is not the real size */ } return limit - 1; } @@ -880,8 +882,8 @@ lua_Unsigned luaH_getn (Table *t) { } } /* 'limit' is zero or present in table */ - if (!limitequalsasize(t)) { - /* (2) 'limit' > 0 and array has more elements after 'limit' */ + if (!limitequalsasize(t)) { /* (2)? */ + /* 'limit' > 0 and array has more elements after 'limit' */ if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */ return limit; /* this is the boundary */ /* else, try last element in the array */ @@ -899,7 +901,7 @@ lua_Unsigned luaH_getn (Table *t) { lua_assert(limit == luaH_realasize(t) && (limit == 0 || !isempty(&t->array[limit - 1]))); if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1)))) - return limit; /* 'limit + 1' is absent... */ + return limit; /* 'limit + 1' is absent */ else /* 'limit + 1' is also present */ return hash_search(t, limit); } @@ -908,6 +910,8 @@ lua_Unsigned luaH_getn (Table *t) { #if defined(LUA_DEBUG) +/* export these functions for the test library */ + Node *luaH_mainposition (const Table *t, const TValue *key) { return mainpositionTV(t, key); } diff --git a/testes/code.lua b/testes/code.lua index ab531fa8..e12f3f91 100644 --- a/testes/code.lua +++ b/testes/code.lua @@ -306,8 +306,10 @@ checkR(function (x) return x // 1 end, 10.0, 10.0, checkR(function (x) return x % (100 - 10) end, 91, 1, 'MODK', 'MMBINK', 'RETURN1') checkR(function (x) return k1 << x end, 3, 8, 'SHLI', 'MMBINI', 'RETURN1') -checkR(function (x) return x << 2 end, 10, 40, 'SHRI', 'MMBINI', 'RETURN1') -checkR(function (x) return x >> 2 end, 8, 2, 'SHRI', 'MMBINI', 'RETURN1') +checkR(function (x) return x << 127 end, 10, 0, 'SHRI', 'MMBINI', 'RETURN1') +checkR(function (x) return x << -127 end, 10, 0, 'SHRI', 'MMBINI', 'RETURN1') +checkR(function (x) return x >> 128 end, 8, 0, 'SHRI', 'MMBINI', 'RETURN1') +checkR(function (x) return x >> -127 end, 8, 0, 'SHRI', 'MMBINI', 'RETURN1') checkR(function (x) return x & 1 end, 9, 1, 'BANDK', 'MMBINK', 'RETURN1') checkR(function (x) return 10 | x end, 1, 11, 'BORK', 'MMBINK', 'RETURN1') checkR(function (x) return -10 ~ x end, -1, 9, 'BXORK', 'MMBINK', 'RETURN1') @@ -331,6 +333,7 @@ check(function () return k3/0 end, 'LOADI', 'DIVK', 'MMBINK', 'RETURN1') check(function () return 0%0 end, 'LOADI', 'MODK', 'MMBINK', 'RETURN1') check(function () return -4//0 end, 'LOADI', 'IDIVK', 'MMBINK', 'RETURN1') check(function (x) return x >> 2.0 end, 'LOADF', 'SHR', 'MMBIN', 'RETURN1') +check(function (x) return x << 128 end, 'LOADI', 'SHL', 'MMBIN', 'RETURN1') check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'MMBIN', 'RETURN1') -- basic 'for' loops |