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? */ |