aboutsummaryrefslogtreecommitdiff
path: root/lcode.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-08-27 13:59:39 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-08-27 13:59:39 -0300
commitdf13f259487459f3a28d31d76c890aa6c2d061e0 (patch)
treef354a0746530369d4dd70113c9752d019fbd200b /lcode.c
parent643188d6e58dfd3270d689230867289347260b74 (diff)
downloadlua-df13f259487459f3a28d31d76c890aa6c2d061e0.tar.gz
lua-df13f259487459f3a28d31d76c890aa6c2d061e0.tar.bz2
lua-df13f259487459f3a28d31d76c890aa6c2d061e0.zip
First version of OP_MMBIN opcodes
In arithmetic/bitwise operators, the call to metamethods is made in a separate opcode following the main one. (The main opcode skips this next one when the operation succeeds.) This change reduces slightly the size of the binary and the complexity of the arithmetic/bitwise opcodes. It also simplfies the treatment of errors and yeld/resume in these operations, as there are much fewer cases to consider. (Only OP_MMBIN/OP_MMBINI/OP_MMBINK, instead of all variants of all arithmetic/bitwise operators.)
Diffstat (limited to '')
-rw-r--r--lcode.c46
1 files changed, 27 insertions, 19 deletions
diff --git a/lcode.c b/lcode.c
index c2b5fc6d..a1b27a00 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1337,18 +1337,20 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) {
1337** (everything but logical operators 'and'/'or' and comparison 1337** (everything but logical operators 'and'/'or' and comparison
1338** operators). 1338** operators).
1339** Expression to produce final result will be encoded in 'e1'. 1339** Expression to produce final result will be encoded in 'e1'.
1340** Because 'luaK_exp2anyreg' can free registers, its calls must be
1341** in "stack order" (that is, first on 'e2', which may have more
1342** recent registers to be released).
1343*/ 1340*/
1344static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, 1341static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2,
1345 OpCode op, int v2, int k, int line) { 1342 OpCode op, int v2, int k, int line,
1343 OpCode mmop, TMS event) {
1346 int v1 = luaK_exp2anyreg(fs, e1); 1344 int v1 = luaK_exp2anyreg(fs, e1);
1347 int pc = luaK_codeABCk(fs, op, 0, v1, v2, k); 1345 int pc = luaK_codeABCk(fs, op, 0, v1, v2, k);
1348 freeexps(fs, e1, e2); 1346 freeexps(fs, e1, e2);
1349 e1->u.info = pc; 1347 e1->u.info = pc;
1350 e1->k = VRELOC; /* all those operations are relocatable */ 1348 e1->k = VRELOC; /* all those operations are relocatable */
1351 luaK_fixline(fs, line); 1349 luaK_fixline(fs, line);
1350if (event != TM_SHL && event != TM_SHR) {
1351 luaK_codeABCk(fs, mmop, v1, v2, event, k); /* to call metamethod */
1352 luaK_fixline(fs, line);
1353}
1352} 1354}
1353 1355
1354 1356
@@ -1359,7 +1361,9 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2,
1359static void codebinexpval (FuncState *fs, OpCode op, 1361static void codebinexpval (FuncState *fs, OpCode op,
1360 expdesc *e1, expdesc *e2, int line) { 1362 expdesc *e1, expdesc *e2, int line) {
1361 int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ 1363 int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */
1362 finishbinexpval(fs, e1, e2, op, v2, 0, line); 1364 lua_assert(OP_ADD <= op && op <= OP_SHR);
1365 finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN,
1366 cast(TMS, (op - OP_ADD) + TM_ADD));
1363} 1367}
1364 1368
1365 1369
@@ -1367,9 +1371,10 @@ static void codebinexpval (FuncState *fs, OpCode op,
1367** Code binary operators ('+', '-', ...) with immediate operands. 1371** Code binary operators ('+', '-', ...) with immediate operands.
1368*/ 1372*/
1369static void codebini (FuncState *fs, OpCode op, 1373static void codebini (FuncState *fs, OpCode op,
1370 expdesc *e1, expdesc *e2, int k, int line) { 1374 expdesc *e1, expdesc *e2, int k, int line,
1375 TMS event) {
1371 int v2 = cast_int(e2->u.ival) + OFFSET_sC; /* immediate operand */ 1376 int v2 = cast_int(e2->u.ival) + OFFSET_sC; /* immediate operand */
1372 finishbinexpval(fs, e1, e2, op, v2, k, line); 1377 finishbinexpval(fs, e1, e2, op, v2, k, line, OP_MMBINI, event);
1373} 1378}
1374 1379
1375 1380
@@ -1383,16 +1388,18 @@ static void swapexps (expdesc *e1, expdesc *e2) {
1383** constant in the proper range, use variant opcodes with immediate 1388** constant in the proper range, use variant opcodes with immediate
1384** operands or K operands. 1389** operands or K operands.
1385*/ 1390*/
1386static void codearith (FuncState *fs, OpCode op, 1391static void codearith (FuncState *fs, BinOpr opr,
1387 expdesc *e1, expdesc *e2, int flip, int line) { 1392 expdesc *e1, expdesc *e2, int flip, int line) {
1393 TMS event = cast(TMS, opr + TM_ADD);
1388 if (isSCint(e2)) /* immediate operand? */ 1394 if (isSCint(e2)) /* immediate operand? */
1389 codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line); 1395 codebini(fs, cast(OpCode, opr + OP_ADDI), e1, e2, flip, line, event);
1390 else if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ 1396 else if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */
1391 int v2 = e2->u.info; /* K index */ 1397 int v2 = e2->u.info; /* K index */
1392 op = cast(OpCode, op - OP_ADD + OP_ADDK); 1398 OpCode op = cast(OpCode, opr + OP_ADDK);
1393 finishbinexpval(fs, e1, e2, op, v2, flip, line); 1399 finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event);
1394 } 1400 }
1395 else { /* 'e2' is neither an immediate nor a K operand */ 1401 else { /* 'e2' is neither an immediate nor a K operand */
1402 OpCode op = cast(OpCode, opr + OP_ADD);
1396 if (flip) 1403 if (flip)
1397 swapexps(e1, e2); /* back to original order */ 1404 swapexps(e1, e2); /* back to original order */
1398 codebinexpval(fs, op, e1, e2, line); /* use standard operators */ 1405 codebinexpval(fs, op, e1, e2, line); /* use standard operators */
@@ -1405,7 +1412,7 @@ static void codearith (FuncState *fs, OpCode op,
1405** numeric constant, change order of operands to try to use an 1412** numeric constant, change order of operands to try to use an
1406** immediate or K operator. 1413** immediate or K operator.
1407*/ 1414*/
1408static void codecommutative (FuncState *fs, OpCode op, 1415static void codecommutative (FuncState *fs, BinOpr op,
1409 expdesc *e1, expdesc *e2, int line) { 1416 expdesc *e1, expdesc *e2, int line) {
1410 int flip = 0; 1417 int flip = 0;
1411 if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ 1418 if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */
@@ -1430,14 +1437,15 @@ static void codebitwise (FuncState *fs, BinOpr opr,
1430 inv = 1; 1437 inv = 1;
1431 } 1438 }
1432 else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ 1439 else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */
1433 op = cast(OpCode, opr - OPR_BAND + OP_BAND); 1440 op = cast(OpCode, opr + OP_ADD);
1434 codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ 1441 codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */
1435 return; 1442 return;
1436 } 1443 }
1437 v2 = e2->u.info; /* index in K array */ 1444 v2 = e2->u.info; /* index in K array */
1438 op = cast(OpCode, opr - OPR_BAND + OP_BANDK); 1445 op = cast(OpCode, opr + OP_ADDK);
1439 lua_assert(ttisinteger(&fs->f->k[v2])); 1446 lua_assert(ttisinteger(&fs->f->k[v2]));
1440 finishbinexpval(fs, e1, e2, op, v2, inv, line); 1447 finishbinexpval(fs, e1, e2, op, v2, inv, line, OP_MMBINK,
1448 cast(TMS, opr + TM_ADD));
1441} 1449}
1442 1450
1443 1451
@@ -1453,7 +1461,7 @@ static void codeshift (FuncState *fs, OpCode op,
1453 changedir = 1; 1461 changedir = 1;
1454 e2->u.ival = -(e2->u.ival); 1462 e2->u.ival = -(e2->u.ival);
1455 } 1463 }
1456 codebini(fs, OP_SHRI, e1, e2, changedir, line); 1464 codebini(fs, OP_SHRI, e1, e2, changedir, line, TM_SHL);
1457 } 1465 }
1458 else 1466 else
1459 codebinexpval(fs, op, e1, e2, line); 1467 codebinexpval(fs, op, e1, e2, line);
@@ -1638,13 +1646,13 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
1638 } 1646 }
1639 case OPR_ADD: case OPR_MUL: { 1647 case OPR_ADD: case OPR_MUL: {
1640 if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) 1648 if (!constfolding(fs, opr + LUA_OPADD, e1, e2))
1641 codecommutative(fs, cast(OpCode, opr + OP_ADD), e1, e2, line); 1649 codecommutative(fs, opr, e1, e2, line);
1642 break; 1650 break;
1643 } 1651 }
1644 case OPR_SUB: case OPR_DIV: 1652 case OPR_SUB: case OPR_DIV:
1645 case OPR_IDIV: case OPR_MOD: case OPR_POW: { 1653 case OPR_IDIV: case OPR_MOD: case OPR_POW: {
1646 if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) 1654 if (!constfolding(fs, opr + LUA_OPADD, e1, e2))
1647 codearith(fs, cast(OpCode, opr + OP_ADD), e1, e2, 0, line); 1655 codearith(fs, opr, e1, e2, 0, line);
1648 break; 1656 break;
1649 } 1657 }
1650 case OPR_BAND: case OPR_BOR: case OPR_BXOR: { 1658 case OPR_BAND: case OPR_BOR: case OPR_BXOR: {
@@ -1656,7 +1664,7 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
1656 if (!constfolding(fs, LUA_OPSHL, e1, e2)) { 1664 if (!constfolding(fs, LUA_OPSHL, e1, e2)) {
1657 if (isSCint(e1)) { 1665 if (isSCint(e1)) {
1658 swapexps(e1, e2); 1666 swapexps(e1, e2);
1659 codebini(fs, OP_SHLI, e1, e2, 1, line); 1667 codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL);
1660 } 1668 }
1661 else 1669 else
1662 codeshift(fs, OP_SHL, e1, e2, line); 1670 codeshift(fs, OP_SHL, e1, e2, line);