diff options
| -rw-r--r-- | lcode.c | 14 | ||||
| -rw-r--r-- | lopcodes.c | 6 | ||||
| -rw-r--r-- | lopcodes.h | 5 | ||||
| -rw-r--r-- | lvm.c | 69 |
4 files changed, 77 insertions, 17 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 2.137 2017/11/28 12:58:18 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.138 2017/11/28 15:26:15 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -152,7 +152,17 @@ int luaK_jump (FuncState *fs) { | |||
| 152 | ** Code a 'return' instruction | 152 | ** Code a 'return' instruction |
| 153 | */ | 153 | */ |
| 154 | void luaK_ret (FuncState *fs, int first, int nret) { | 154 | void luaK_ret (FuncState *fs, int first, int nret) { |
| 155 | luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); | 155 | switch (nret) { |
| 156 | case 0: | ||
| 157 | luaK_codeABC(fs, OP_RETURN0, 0, 0, 0); | ||
| 158 | break; | ||
| 159 | case 1: | ||
| 160 | luaK_codeABC(fs, OP_RETURN1, first, 0, 0); | ||
| 161 | break; | ||
| 162 | default: | ||
| 163 | luaK_codeABC(fs, OP_RETURN, first, nret + 1, 0); | ||
| 164 | break; | ||
| 165 | } | ||
| 156 | } | 166 | } |
| 157 | 167 | ||
| 158 | 168 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lopcodes.c,v 1.69 2017/11/22 18:41:20 roberto Exp roberto $ | 2 | ** $Id: lopcodes.c,v 1.70 2017/11/27 17:44:31 roberto Exp roberto $ |
| 3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -75,6 +75,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { | |||
| 75 | "CALL", | 75 | "CALL", |
| 76 | "TAILCALL", | 76 | "TAILCALL", |
| 77 | "RETURN", | 77 | "RETURN", |
| 78 | "RETURN0", | ||
| 79 | "RETURN1", | ||
| 78 | "FORLOOP", | 80 | "FORLOOP", |
| 79 | "FORPREP", | 81 | "FORPREP", |
| 80 | "TFORCALL", | 82 | "TFORCALL", |
| @@ -146,6 +148,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
| 146 | ,opmode(0, 1, iABC) /* OP_CALL */ | 148 | ,opmode(0, 1, iABC) /* OP_CALL */ |
| 147 | ,opmode(0, 1, iABC) /* OP_TAILCALL */ | 149 | ,opmode(0, 1, iABC) /* OP_TAILCALL */ |
| 148 | ,opmode(0, 0, iABC) /* OP_RETURN */ | 150 | ,opmode(0, 0, iABC) /* OP_RETURN */ |
| 151 | ,opmode(0, 0, iABC) /* OP_RETURN0 */ | ||
| 152 | ,opmode(0, 0, iABC) /* OP_RETURN1 */ | ||
| 149 | ,opmode(0, 1, iABx) /* OP_FORLOOP */ | 153 | ,opmode(0, 1, iABx) /* OP_FORLOOP */ |
| 150 | ,opmode(0, 1, iABx) /* OP_FORPREP */ | 154 | ,opmode(0, 1, iABx) /* OP_FORPREP */ |
| 151 | ,opmode(0, 0, iABC) /* OP_TFORCALL */ | 155 | ,opmode(0, 0, iABC) /* OP_TFORCALL */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lopcodes.h,v 1.171 2017/11/27 17:44:31 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.172 2017/11/28 12:58:18 roberto Exp roberto $ |
| 3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -252,7 +252,10 @@ OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */ | |||
| 252 | 252 | ||
| 253 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ | 253 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ |
| 254 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ | 254 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ |
| 255 | |||
| 255 | OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ | 256 | OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ |
| 257 | OP_RETURN0,/* return */ | ||
| 258 | OP_RETURN1,/* A return R(A) */ | ||
| 256 | 259 | ||
| 257 | OP_FORLOOP,/* A Bx R(A)+=R(A+2); | 260 | OP_FORLOOP,/* A Bx R(A)+=R(A+2); |
| 258 | if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) }*/ | 261 | if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) }*/ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.320 2017/11/28 14:51:00 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.321 2017/11/29 13:02:17 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -798,6 +798,11 @@ void luaV_finishOp (lua_State *L) { | |||
| 798 | */ | 798 | */ |
| 799 | #define Protect(exp) (savepc(L), (exp), updatetrap(ci)) | 799 | #define Protect(exp) (savepc(L), (exp), updatetrap(ci)) |
| 800 | 800 | ||
| 801 | /* | ||
| 802 | ** Protect code that will return. | ||
| 803 | */ | ||
| 804 | #define halfProtect(exp) (savepc(L), (exp)) | ||
| 805 | |||
| 801 | 806 | ||
| 802 | #define checkGC(L,c) \ | 807 | #define checkGC(L,c) \ |
| 803 | { luaC_condGC(L, L->top = (c), /* limit of live values */ \ | 808 | { luaC_condGC(L, L->top = (c), /* limit of live values */ \ |
| @@ -824,11 +829,16 @@ void luaV_finishOp (lua_State *L) { | |||
| 824 | 829 | ||
| 825 | 830 | ||
| 826 | void luaV_execute (lua_State *L, CallInfo *ci) { | 831 | void luaV_execute (lua_State *L, CallInfo *ci) { |
| 827 | LClosure *cl = clLvalue(s2v(ci->func)); | 832 | LClosure *cl; |
| 828 | TValue *k = cl->p->k; | 833 | TValue *k; |
| 829 | StkId base = ci->func + 1; | 834 | StkId base; |
| 835 | const Instruction *pc; | ||
| 830 | int trap = ci->u.l.trap; | 836 | int trap = ci->u.l.trap; |
| 831 | const Instruction *pc = ci->u.l.savedpc; | 837 | tailcall: |
| 838 | cl = clLvalue(s2v(ci->func)); | ||
| 839 | k = cl->p->k; | ||
| 840 | base = ci->func + 1; | ||
| 841 | pc = ci->u.l.savedpc; | ||
| 832 | /* main loop of interpreter */ | 842 | /* main loop of interpreter */ |
| 833 | for (;;) { | 843 | for (;;) { |
| 834 | int cond; /* flag for conditional jumps */ | 844 | int cond; /* flag for conditional jumps */ |
| @@ -1438,16 +1448,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1438 | vra = s2v(ra); | 1448 | vra = s2v(ra); |
| 1439 | b++; /* there is now one extra argument */ | 1449 | b++; /* there is now one extra argument */ |
| 1440 | } | 1450 | } |
| 1441 | if (!ttisLclosure(vra)) /* C function? */ | 1451 | if (!ttisLclosure(vra)) { /* C function? */ |
| 1442 | Protect(luaD_call(L, ra, LUA_MULTRET)); /* call it */ | 1452 | Protect(luaD_call(L, ra, LUA_MULTRET)); /* call it */ |
| 1453 | /* next instruction will do the return */ | ||
| 1454 | } | ||
| 1443 | else { /* tail call */ | 1455 | else { /* tail call */ |
| 1444 | if (cl->p->sizep > 0) /* close upvalues from previous call */ | 1456 | if (cl->p->sizep > 0) /* close upvalues from previous call */ |
| 1445 | luaF_close(L, ci->func + 1); | 1457 | luaF_close(L, ci->func + 1); |
| 1446 | luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ | 1458 | luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ |
| 1447 | cl = clLvalue(s2v(ci->func)); | 1459 | goto tailcall; |
| 1448 | k = cl->p->k; | ||
| 1449 | updatebase(ci); | ||
| 1450 | pc = ci->u.l.savedpc; | ||
| 1451 | } | 1460 | } |
| 1452 | vmbreak; | 1461 | vmbreak; |
| 1453 | } | 1462 | } |
| @@ -1455,9 +1464,43 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1455 | int b = GETARG_B(i); | 1464 | int b = GETARG_B(i); |
| 1456 | if (cl->p->sizep > 0) | 1465 | if (cl->p->sizep > 0) |
| 1457 | luaF_close(L, base); | 1466 | luaF_close(L, base); |
| 1458 | savepc(L); | 1467 | halfProtect( |
| 1459 | luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); | 1468 | luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))) |
| 1460 | return; /* external invocation: return */ | 1469 | ); |
| 1470 | return; | ||
| 1471 | } | ||
| 1472 | vmcase(OP_RETURN0) { | ||
| 1473 | if (cl->p->sizep > 0) | ||
| 1474 | luaF_close(L, base); | ||
| 1475 | if (L->hookmask) | ||
| 1476 | halfProtect(luaD_poscall(L, ci, ra, 0)); /* no hurry... */ | ||
| 1477 | else { | ||
| 1478 | int nres = ci->nresults; | ||
| 1479 | L->ci = ci->previous; /* back to caller */ | ||
| 1480 | L->top = base - 1; | ||
| 1481 | while (nres-- > 0) | ||
| 1482 | setnilvalue(s2v(L->top++)); /* all results are nil */ | ||
| 1483 | } | ||
| 1484 | return; | ||
| 1485 | } | ||
| 1486 | vmcase(OP_RETURN1) { | ||
| 1487 | if (cl->p->sizep > 0) | ||
| 1488 | luaF_close(L, base); | ||
| 1489 | if (L->hookmask) | ||
| 1490 | halfProtect(luaD_poscall(L, ci, ra, 1)); /* no hurry... */ | ||
| 1491 | else { | ||
| 1492 | int nres = ci->nresults; | ||
| 1493 | L->ci = ci->previous; /* back to caller */ | ||
| 1494 | if (nres == 0) | ||
| 1495 | L->top = base - 1; /* asked for no results */ | ||
| 1496 | else { | ||
| 1497 | setobjs2s(L, base - 1, ra); /* at least this result */ | ||
| 1498 | L->top = base; | ||
| 1499 | while (--nres > 0) /* complete missing results */ | ||
| 1500 | setnilvalue(s2v(L->top++)); | ||
| 1501 | } | ||
| 1502 | } | ||
| 1503 | return; | ||
| 1461 | } | 1504 | } |
| 1462 | vmcase(OP_FORLOOP) { | 1505 | vmcase(OP_FORLOOP) { |
| 1463 | if (ttisinteger(vra)) { /* integer loop? */ | 1506 | if (ttisinteger(vra)) { /* integer loop? */ |
