diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-08-27 13:59:39 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-08-27 13:59:39 -0300 |
commit | df13f259487459f3a28d31d76c890aa6c2d061e0 (patch) | |
tree | f354a0746530369d4dd70113c9752d019fbd200b /lcode.c | |
parent | 643188d6e58dfd3270d689230867289347260b74 (diff) | |
download | lua-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.c | 46 |
1 files changed, 27 insertions, 19 deletions
@@ -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 | */ |
1344 | static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, | 1341 | static 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); |
1350 | if (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, | |||
1359 | static void codebinexpval (FuncState *fs, OpCode op, | 1361 | static 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 | */ |
1369 | static void codebini (FuncState *fs, OpCode op, | 1373 | static 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 | */ |
1386 | static void codearith (FuncState *fs, OpCode op, | 1391 | static 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 | */ |
1408 | static void codecommutative (FuncState *fs, OpCode op, | 1415 | static 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); |