aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-10-01 17:24:37 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-10-01 17:24:37 -0300
commitb2a580bdb1982e45bb37f95b78c2dafec6efa7a6 (patch)
tree76de58214adff838a26346514a8a6fba459bde9b
parent89f6a85f034b2535e43e421991098fa05a92cd60 (diff)
downloadlua-b2a580bdb1982e45bb37f95b78c2dafec6efa7a6.tar.gz
lua-b2a580bdb1982e45bb37f95b78c2dafec6efa7a6.tar.bz2
lua-b2a580bdb1982e45bb37f95b78c2dafec6efa7a6.zip
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.c61
-rw-r--r--lopcodes.h8
-rw-r--r--ltable.c44
-rw-r--r--testes/code.lua7
4 files changed, 62 insertions, 58 deletions
diff --git a/lcode.c b/lcode.c
index bc86793a..abb8a811 100644
--- a/lcode.c
+++ b/lcode.c
@@ -359,12 +359,12 @@ static void removelastlineinfo (FuncState *fs) {
359 Proto *f = fs->f; 359 Proto *f = fs->f;
360 int pc = fs->pc - 1; /* last instruction coded */ 360 int pc = fs->pc - 1; /* last instruction coded */
361 if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */ 361 if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */
362 fs->previousline -= f->lineinfo[pc]; /* last line saved */ 362 fs->previousline -= f->lineinfo[pc]; /* correct last line saved */
363 fs->iwthabs--; 363 fs->iwthabs--; /* undo previous increment */
364 } 364 }
365 else { /* absolute line information */ 365 else { /* absolute line information */
366 lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == pc);
366 fs->nabslineinfo--; /* remove it */ 367 fs->nabslineinfo--; /* remove it */
367 lua_assert(f->abslineinfo[fs->nabslineinfo].pc = pc);
368 fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */ 368 fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */
369 } 369 }
370} 370}
@@ -626,12 +626,12 @@ static int nilK (FuncState *fs) {
626 626
627 627
628/* 628/*
629** Check whether 'i' can be stored in an 'sC' operand. 629** Check whether 'i' can be stored in an 'sC' operand. Equivalent to
630** Equivalent to (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) 630** (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) but without risk of
631** but without risk of overflows in the addition. 631** overflows in the hidden addition inside 'int2sC'.
632*/ 632*/
633static int fitsC (lua_Integer i) { 633static int fitsC (lua_Integer i) {
634 return (-OFFSET_sC <= i && i <= MAXARG_C - OFFSET_sC); 634 return (l_castS2U(i) + OFFSET_sC <= cast_uint(MAXARG_C));
635} 635}
636 636
637 637
@@ -1213,15 +1213,6 @@ static int isSCint (expdesc *e) {
1213 1213
1214 1214
1215/* 1215/*
1216** Check whether expression 'e' and its negation are literal integers
1217** in proper range to fit in register sC
1218*/
1219static int isSCintN (expdesc *e) {
1220 return luaK_isKint(e) && fitsC(e->u.ival) && fitsC(-e->u.ival);
1221}
1222
1223
1224/*
1225** Check whether expression 'e' is a literal integer or float in 1216** Check whether expression 'e' is a literal integer or float in
1226** proper range to fit in a register (sB or sC). 1217** proper range to fit in a register (sB or sC).
1227*/ 1218*/
@@ -1382,15 +1373,25 @@ static void codebini (FuncState *fs, OpCode op,
1382} 1373}
1383 1374
1384 1375
1385/* Code binary operators negating the immediate operand for the 1376/* Try to code a binary operator negating its second operand.
1386** opcode. For the metamethod, 'v2' must keep its original value. 1377** For the metamethod, 2nd operand must keep its original value.
1387*/ 1378*/
1388static void finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, 1379static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2,
1389 OpCode op, int line, TMS event) { 1380 OpCode op, int line, TMS event) {
1390 int v2 = cast_int(e2->u.ival); 1381 if (!luaK_isKint(e2))
1391 finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); 1382 return 0; /* not an integer constant */
1392 /* correct metamethod argument */ 1383 else {
1393 SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2)); 1384 lua_Integer i2 = e2->u.ival;
1385 if (!(fitsC(i2) && fitsC(-i2)))
1386 return 0; /* not in the proper range */
1387 else { /* operating a small integer constant */
1388 int v2 = cast_int(i2);
1389 finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event);
1390 /* correct metamethod argument */
1391 SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2));
1392 return 1; /* successfully coded */
1393 }
1394 }
1394} 1395}
1395 1396
1396 1397
@@ -1647,11 +1648,8 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
1647 break; 1648 break;
1648 } 1649 }
1649 case OPR_SUB: { 1650 case OPR_SUB: {
1650 if (isSCintN(e2)) { /* subtracting a small integer constant? */ 1651 if (finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB))
1651 /* code it as (r1 + -I) */ 1652 break; /* coded as (r1 + -I) */
1652 finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB);
1653 break;
1654 }
1655 /* ELSE *//* FALLTHROUGH */ 1653 /* ELSE *//* FALLTHROUGH */
1656 } 1654 }
1657 case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { 1655 case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: {
@@ -1667,16 +1665,15 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
1667 swapexps(e1, e2); 1665 swapexps(e1, e2);
1668 codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */ 1666 codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */
1669 } 1667 }
1670 else if (isSCintN(e2)) { /* shifting by a small integer constant? */ 1668 else if (finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL)) {
1671 /* code it as (r1 >> -I) */ 1669 /* coded as (r1 >> -I) */;
1672 finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL);
1673 } 1670 }
1674 else /* regular case (two registers) */ 1671 else /* regular case (two registers) */
1675 codebinexpval(fs, OP_SHL, e1, e2, line); 1672 codebinexpval(fs, OP_SHL, e1, e2, line);
1676 break; 1673 break;
1677 } 1674 }
1678 case OPR_SHR: { 1675 case OPR_SHR: {
1679 if (isSCintN(e2)) 1676 if (isSCint(e2))
1680 codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ 1677 codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */
1681 else /* regular case (two registers) */ 1678 else /* regular case (two registers) */
1682 codebinexpval(fs, OP_SHR, e1, e2, line); 1679 codebinexpval(fs, OP_SHR, e1, e2, line);
diff --git a/lopcodes.h b/lopcodes.h
index 95241702..443a71e9 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -221,7 +221,7 @@ OP_NEWTABLE,/* A B C R(A) := {} */
221 221
222OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */ 222OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */
223 223
224OP_ADDI,/* A B sC R(A) := R(B) + C */ 224OP_ADDI,/* A B sC R(A) := R(B) + sC */
225 225
226OP_ADDK,/* A B C R(A) := R(B) + K(C) */ 226OP_ADDK,/* A B C R(A) := R(B) + K(C) */
227OP_SUBK,/* A B C R(A) := R(B) - K(C) */ 227OP_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 */
235OP_BORK,/* A B C R(A) := R(B) | K(C):integer */ 235OP_BORK,/* A B C R(A) := R(B) | K(C):integer */
236OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */ 236OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */
237 237
238OP_SHRI,/* A B sC R(A) := R(B) >> C */ 238OP_SHRI,/* A B sC R(A) := R(B) >> sC */
239OP_SHLI,/* A B sC R(A) := C << R(B) */ 239OP_SHLI,/* A B sC R(A) := sC << R(B) */
240 240
241OP_ADD,/* A B C R(A) := R(B) + R(C) */ 241OP_ADD,/* A B C R(A) := R(B) + R(C) */
242OP_SUB,/* A B C R(A) := R(B) - R(C) */ 242OP_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) */
253OP_SHR,/* A B C R(A) := R(B) >> R(C) */ 253OP_SHR,/* A B C R(A) := R(B) >> R(C) */
254 254
255OP_MMBIN,/* A B C call C metamethod over R(A) and R(B) */ 255OP_MMBIN,/* A B C call C metamethod over R(A) and R(B) */
256OP_MMBINI,/* A B C call C metamethod over R(A) and B */ 256OP_MMBINI,/* A sB C call C metamethod over R(A) and sB */
257OP_MMBINK,/* A B C call C metamethod over R(A) and K(B) */ 257OP_MMBINK,/* A B C call C metamethod over R(A) and K(B) */
258 258
259OP_UNM,/* A B R(A) := -R(B) */ 259OP_UNM,/* A B R(A) := -R(B) */
diff --git a/ltable.c b/ltable.c
index d8ff3d80..5561d45e 100644
--- a/ltable.c
+++ b/ltable.c
@@ -833,39 +833,41 @@ static unsigned int binsearch (const TValue *array, unsigned int i,
833** and 'maxinteger' if t[maxinteger] is present.) 833** and 'maxinteger' if t[maxinteger] is present.)
834** (In the next explanation, we use Lua indices, that is, with base 1. 834** (In the next explanation, we use Lua indices, that is, with base 1.
835** The code itself uses base 0 when indexing the array part of the table.) 835** The code itself uses base 0 when indexing the array part of the table.)
836** The code starts with 'limit', a position in the array part that may 836** The code starts with 'limit = t->alimit', a position in the array
837** be a boundary. 837** part that may be a boundary.
838**
838** (1) If 't[limit]' is empty, there must be a boundary before it. 839** (1) If 't[limit]' is empty, there must be a boundary before it.
839** As a common case (e.g., after 't[#t]=nil'), check whether 'hint-1' 840** As a common case (e.g., after 't[#t]=nil'), check whether 'limit-1'
840** is present. If so, it is a boundary. Otherwise, do a binary search 841** is present. If so, it is a boundary. Otherwise, do a binary search
841** between 0 and limit to find a boundary. In both cases, try to 842** between 0 and limit to find a boundary. In both cases, try to
842** use this boundary as the new 'limit', as a hint for the next call. 843** use this boundary as the new 'alimit', as a hint for the next call.
844**
843** (2) If 't[limit]' is not empty and the array has more elements 845** (2) If 't[limit]' is not empty and the array has more elements
844** after 'limit', try to find a boundary there. Again, try first 846** after 'limit', try to find a boundary there. Again, try first
845** the special case (which should be quite frequent) where 'limit+1' 847** the special case (which should be quite frequent) where 'limit+1'
846** is empty, so that 'limit' is a boundary. Otherwise, check the 848** is empty, so that 'limit' is a boundary. Otherwise, check the
847** last element of the array part (set it as a new limit). If it is empty, 849** last element of the array part. If it is empty, there must be a
848** there must be a boundary between the old limit (present) and the new 850** boundary between the old limit (present) and the last element
849** limit (absent), which is found with a binary search. (This boundary 851** (absent), which is found with a binary search. (This boundary always
850** always can be a new limit.) 852** can be a new limit.)
853**
851** (3) The last case is when there are no elements in the array part 854** (3) The last case is when there are no elements in the array part
852** (limit == 0) or its last element (the new limit) is present. 855** (limit == 0) or its last element (the new limit) is present.
853** In this case, must check the hash part. If there is no hash part, 856** In this case, must check the hash part. If there is no hash part
854** the boundary is 0. Otherwise, if 'limit+1' is absent, 'limit' is 857** or 'limit+1' is absent, 'limit' is a boundary. Otherwise, call
855** a boundary. Finally, if 'limit+1' is present, call 'hash_search' 858** 'hash_search' to find a boundary in the hash part of the table.
856** to find a boundary in the hash part of the table. (In those 859** (In those cases, the boundary is not inside the array part, and
857** cases, the boundary is not inside the array part, and therefore 860** therefore cannot be used as a new limit.)
858** cannot be used as a new limit.)
859*/ 861*/
860lua_Unsigned luaH_getn (Table *t) { 862lua_Unsigned luaH_getn (Table *t) {
861 unsigned int limit = t->alimit; 863 unsigned int limit = t->alimit;
862 if (limit > 0 && isempty(&t->array[limit - 1])) { 864 if (limit > 0 && isempty(&t->array[limit - 1])) { /* (1)? */
863 /* (1) there must be a boundary before 'limit' */ 865 /* there must be a boundary before 'limit' */
864 if (limit >= 2 && !isempty(&t->array[limit - 2])) { 866 if (limit >= 2 && !isempty(&t->array[limit - 2])) {
865 /* 'limit - 1' is a boundary; can it be a new limit? */ 867 /* 'limit - 1' is a boundary; can it be a new limit? */
866 if (ispow2realasize(t) && !ispow2(limit - 1)) { 868 if (ispow2realasize(t) && !ispow2(limit - 1)) {
867 t->alimit = limit - 1; 869 t->alimit = limit - 1;
868 setnorealasize(t); 870 setnorealasize(t); /* now 'alimit' is not the real size */
869 } 871 }
870 return limit - 1; 872 return limit - 1;
871 } 873 }
@@ -880,8 +882,8 @@ lua_Unsigned luaH_getn (Table *t) {
880 } 882 }
881 } 883 }
882 /* 'limit' is zero or present in table */ 884 /* 'limit' is zero or present in table */
883 if (!limitequalsasize(t)) { 885 if (!limitequalsasize(t)) { /* (2)? */
884 /* (2) 'limit' > 0 and array has more elements after 'limit' */ 886 /* 'limit' > 0 and array has more elements after 'limit' */
885 if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */ 887 if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */
886 return limit; /* this is the boundary */ 888 return limit; /* this is the boundary */
887 /* else, try last element in the array */ 889 /* else, try last element in the array */
@@ -899,7 +901,7 @@ lua_Unsigned luaH_getn (Table *t) {
899 lua_assert(limit == luaH_realasize(t) && 901 lua_assert(limit == luaH_realasize(t) &&
900 (limit == 0 || !isempty(&t->array[limit - 1]))); 902 (limit == 0 || !isempty(&t->array[limit - 1])));
901 if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1)))) 903 if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1))))
902 return limit; /* 'limit + 1' is absent... */ 904 return limit; /* 'limit + 1' is absent */
903 else /* 'limit + 1' is also present */ 905 else /* 'limit + 1' is also present */
904 return hash_search(t, limit); 906 return hash_search(t, limit);
905} 907}
@@ -908,6 +910,8 @@ lua_Unsigned luaH_getn (Table *t) {
908 910
909#if defined(LUA_DEBUG) 911#if defined(LUA_DEBUG)
910 912
913/* export these functions for the test library */
914
911Node *luaH_mainposition (const Table *t, const TValue *key) { 915Node *luaH_mainposition (const Table *t, const TValue *key) {
912 return mainpositionTV(t, key); 916 return mainpositionTV(t, key);
913} 917}
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,
306checkR(function (x) return x % (100 - 10) end, 91, 1, 306checkR(function (x) return x % (100 - 10) end, 91, 1,
307 'MODK', 'MMBINK', 'RETURN1') 307 'MODK', 'MMBINK', 'RETURN1')
308checkR(function (x) return k1 << x end, 3, 8, 'SHLI', 'MMBINI', 'RETURN1') 308checkR(function (x) return k1 << x end, 3, 8, 'SHLI', 'MMBINI', 'RETURN1')
309checkR(function (x) return x << 2 end, 10, 40, 'SHRI', 'MMBINI', 'RETURN1') 309checkR(function (x) return x << 127 end, 10, 0, 'SHRI', 'MMBINI', 'RETURN1')
310checkR(function (x) return x >> 2 end, 8, 2, 'SHRI', 'MMBINI', 'RETURN1') 310checkR(function (x) return x << -127 end, 10, 0, 'SHRI', 'MMBINI', 'RETURN1')
311checkR(function (x) return x >> 128 end, 8, 0, 'SHRI', 'MMBINI', 'RETURN1')
312checkR(function (x) return x >> -127 end, 8, 0, 'SHRI', 'MMBINI', 'RETURN1')
311checkR(function (x) return x & 1 end, 9, 1, 'BANDK', 'MMBINK', 'RETURN1') 313checkR(function (x) return x & 1 end, 9, 1, 'BANDK', 'MMBINK', 'RETURN1')
312checkR(function (x) return 10 | x end, 1, 11, 'BORK', 'MMBINK', 'RETURN1') 314checkR(function (x) return 10 | x end, 1, 11, 'BORK', 'MMBINK', 'RETURN1')
313checkR(function (x) return -10 ~ x end, -1, 9, 'BXORK', 'MMBINK', 'RETURN1') 315checkR(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')
331check(function () return 0%0 end, 'LOADI', 'MODK', 'MMBINK', 'RETURN1') 333check(function () return 0%0 end, 'LOADI', 'MODK', 'MMBINK', 'RETURN1')
332check(function () return -4//0 end, 'LOADI', 'IDIVK', 'MMBINK', 'RETURN1') 334check(function () return -4//0 end, 'LOADI', 'IDIVK', 'MMBINK', 'RETURN1')
333check(function (x) return x >> 2.0 end, 'LOADF', 'SHR', 'MMBIN', 'RETURN1') 335check(function (x) return x >> 2.0 end, 'LOADF', 'SHR', 'MMBIN', 'RETURN1')
336check(function (x) return x << 128 end, 'LOADI', 'SHL', 'MMBIN', 'RETURN1')
334check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'MMBIN', 'RETURN1') 337check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'MMBIN', 'RETURN1')
335 338
336-- basic 'for' loops 339-- basic 'for' loops