diff options
Diffstat (limited to 'src/lua/lvm.c')
-rw-r--r-- | src/lua/lvm.c | 75 |
1 files changed, 47 insertions, 28 deletions
diff --git a/src/lua/lvm.c b/src/lua/lvm.c index 08681af..aa3b22b 100644 --- a/src/lua/lvm.c +++ b/src/lua/lvm.c | |||
@@ -229,7 +229,7 @@ static int forprep (lua_State *L, StkId ra) { | |||
229 | count /= l_castS2U(-(step + 1)) + 1u; | 229 | count /= l_castS2U(-(step + 1)) + 1u; |
230 | } | 230 | } |
231 | /* store the counter in place of the limit (which won't be | 231 | /* store the counter in place of the limit (which won't be |
232 | needed anymore */ | 232 | needed anymore) */ |
233 | setivalue(plimit, l_castU2S(count)); | 233 | setivalue(plimit, l_castU2S(count)); |
234 | } | 234 | } |
235 | } | 235 | } |
@@ -1092,15 +1092,11 @@ void luaV_finishOp (lua_State *L) { | |||
1092 | #define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci)) | 1092 | #define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci)) |
1093 | 1093 | ||
1094 | /* | 1094 | /* |
1095 | ** Protect code that will finish the loop (returns) or can only raise | 1095 | ** Protect code that can only raise errors. (That is, it cannnot change |
1096 | ** errors. (That is, it will not return to the interpreter main loop | 1096 | ** the stack or hooks.) |
1097 | ** after changing the stack or hooks.) | ||
1098 | */ | 1097 | */ |
1099 | #define halfProtect(exp) (savestate(L,ci), (exp)) | 1098 | #define halfProtect(exp) (savestate(L,ci), (exp)) |
1100 | 1099 | ||
1101 | /* idem, but without changing the stack */ | ||
1102 | #define halfProtectNT(exp) (savepc(L), (exp)) | ||
1103 | |||
1104 | /* 'c' is the limit of live values in the stack */ | 1100 | /* 'c' is the limit of live values in the stack */ |
1105 | #define checkGC(L,c) \ | 1101 | #define checkGC(L,c) \ |
1106 | { luaC_condGC(L, (savepc(L), L->top = (c)), \ | 1102 | { luaC_condGC(L, (savepc(L), L->top = (c)), \ |
@@ -1132,17 +1128,20 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1132 | #if LUA_USE_JUMPTABLE | 1128 | #if LUA_USE_JUMPTABLE |
1133 | #include "ljumptab.h" | 1129 | #include "ljumptab.h" |
1134 | #endif | 1130 | #endif |
1135 | tailcall: | 1131 | startfunc: |
1136 | trap = L->hookmask; | 1132 | trap = L->hookmask; |
1133 | returning: /* trap already set */ | ||
1137 | cl = clLvalue(s2v(ci->func)); | 1134 | cl = clLvalue(s2v(ci->func)); |
1138 | k = cl->p->k; | 1135 | k = cl->p->k; |
1139 | pc = ci->u.l.savedpc; | 1136 | pc = ci->u.l.savedpc; |
1140 | if (trap) { | 1137 | if (trap) { |
1141 | if (cl->p->is_vararg) | 1138 | if (pc == cl->p->code) { /* first instruction (not resuming)? */ |
1142 | trap = 0; /* hooks will start after VARARGPREP instruction */ | 1139 | if (cl->p->is_vararg) |
1143 | else if (pc == cl->p->code) /* first instruction (not resuming)? */ | 1140 | trap = 0; /* hooks will start after VARARGPREP instruction */ |
1144 | luaD_hookcall(L, ci); | 1141 | else /* check 'call' hook */ |
1145 | ci->u.l.trap = 1; /* there may be other hooks */ | 1142 | luaD_hookcall(L, ci); |
1143 | } | ||
1144 | ci->u.l.trap = 1; /* assume trap is on, for now */ | ||
1146 | } | 1145 | } |
1147 | base = ci->func + 1; | 1146 | base = ci->func + 1; |
1148 | /* main loop of interpreter */ | 1147 | /* main loop of interpreter */ |
@@ -1151,7 +1150,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1151 | StkId ra; /* instruction's A register */ | 1150 | StkId ra; /* instruction's A register */ |
1152 | vmfetch(); | 1151 | vmfetch(); |
1153 | lua_assert(base == ci->func + 1); | 1152 | lua_assert(base == ci->func + 1); |
1154 | lua_assert(base <= L->top && L->top < L->stack + L->stacksize); | 1153 | lua_assert(base <= L->top && L->top < L->stack_last); |
1155 | /* invalidate top for instructions not expecting it */ | 1154 | /* invalidate top for instructions not expecting it */ |
1156 | lua_assert(isIT(i) || (cast_void(L->top = base), 1)); | 1155 | lua_assert(isIT(i) || (cast_void(L->top = base), 1)); |
1157 | vmdispatch (GET_OPCODE(i)) { | 1156 | vmdispatch (GET_OPCODE(i)) { |
@@ -1606,24 +1605,32 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1606 | vmbreak; | 1605 | vmbreak; |
1607 | } | 1606 | } |
1608 | vmcase(OP_CALL) { | 1607 | vmcase(OP_CALL) { |
1608 | CallInfo *newci; | ||
1609 | int b = GETARG_B(i); | 1609 | int b = GETARG_B(i); |
1610 | int nresults = GETARG_C(i) - 1; | 1610 | int nresults = GETARG_C(i) - 1; |
1611 | if (b != 0) /* fixed number of arguments? */ | 1611 | if (b != 0) /* fixed number of arguments? */ |
1612 | L->top = ra + b; /* top signals number of arguments */ | 1612 | L->top = ra + b; /* top signals number of arguments */ |
1613 | /* else previous instruction set top */ | 1613 | /* else previous instruction set top */ |
1614 | ProtectNT(luaD_call(L, ra, nresults)); | 1614 | savepc(L); /* in case of errors */ |
1615 | if ((newci = luaD_precall(L, ra, nresults)) == NULL) | ||
1616 | updatetrap(ci); /* C call; nothing else to be done */ | ||
1617 | else { /* Lua call: run function in this same C frame */ | ||
1618 | ci = newci; | ||
1619 | ci->callstatus = 0; /* call re-uses 'luaV_execute' */ | ||
1620 | goto startfunc; | ||
1621 | } | ||
1615 | vmbreak; | 1622 | vmbreak; |
1616 | } | 1623 | } |
1617 | vmcase(OP_TAILCALL) { | 1624 | vmcase(OP_TAILCALL) { |
1618 | int b = GETARG_B(i); /* number of arguments + 1 (function) */ | 1625 | int b = GETARG_B(i); /* number of arguments + 1 (function) */ |
1619 | int nparams1 = GETARG_C(i); | 1626 | int nparams1 = GETARG_C(i); |
1620 | /* delat is virtual 'func' - real 'func' (vararg functions) */ | 1627 | /* delta is virtual 'func' - real 'func' (vararg functions) */ |
1621 | int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; | 1628 | int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; |
1622 | if (b != 0) | 1629 | if (b != 0) |
1623 | L->top = ra + b; | 1630 | L->top = ra + b; |
1624 | else /* previous instruction set top */ | 1631 | else /* previous instruction set top */ |
1625 | b = cast_int(L->top - ra); | 1632 | b = cast_int(L->top - ra); |
1626 | savepc(ci); /* some calls here can raise errors */ | 1633 | savepc(ci); /* several calls here can raise errors */ |
1627 | if (TESTARG_k(i)) { | 1634 | if (TESTARG_k(i)) { |
1628 | /* close upvalues from current call; the compiler ensures | 1635 | /* close upvalues from current call; the compiler ensures |
1629 | that there are no to-be-closed variables here, so this | 1636 | that there are no to-be-closed variables here, so this |
@@ -1637,16 +1644,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1637 | checkstackGCp(L, 1, ra); | 1644 | checkstackGCp(L, 1, ra); |
1638 | } | 1645 | } |
1639 | if (!ttisLclosure(s2v(ra))) { /* C function? */ | 1646 | if (!ttisLclosure(s2v(ra))) { /* C function? */ |
1640 | luaD_call(L, ra, LUA_MULTRET); /* call it */ | 1647 | luaD_precall(L, ra, LUA_MULTRET); /* call it */ |
1641 | updatetrap(ci); | 1648 | updatetrap(ci); |
1642 | updatestack(ci); /* stack may have been relocated */ | 1649 | updatestack(ci); /* stack may have been relocated */ |
1643 | ci->func -= delta; | 1650 | ci->func -= delta; /* restore 'func' (if vararg) */ |
1644 | luaD_poscall(L, ci, cast_int(L->top - ra)); | 1651 | luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */ |
1645 | return; | 1652 | updatetrap(ci); /* 'luaD_poscall' can change hooks */ |
1653 | goto ret; /* caller returns after the tail call */ | ||
1646 | } | 1654 | } |
1647 | ci->func -= delta; | 1655 | ci->func -= delta; /* restore 'func' (if vararg) */ |
1648 | luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ | 1656 | luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ |
1649 | goto tailcall; | 1657 | goto startfunc; /* execute the callee */ |
1650 | } | 1658 | } |
1651 | vmcase(OP_RETURN) { | 1659 | vmcase(OP_RETURN) { |
1652 | int n = GETARG_B(i) - 1; /* number of results */ | 1660 | int n = GETARG_B(i) - 1; /* number of results */ |
@@ -1665,12 +1673,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1665 | ci->func -= ci->u.l.nextraargs + nparams1; | 1673 | ci->func -= ci->u.l.nextraargs + nparams1; |
1666 | L->top = ra + n; /* set call for 'luaD_poscall' */ | 1674 | L->top = ra + n; /* set call for 'luaD_poscall' */ |
1667 | luaD_poscall(L, ci, n); | 1675 | luaD_poscall(L, ci, n); |
1668 | return; | 1676 | updatetrap(ci); /* 'luaD_poscall' can change hooks */ |
1677 | goto ret; | ||
1669 | } | 1678 | } |
1670 | vmcase(OP_RETURN0) { | 1679 | vmcase(OP_RETURN0) { |
1671 | if (L->hookmask) { | 1680 | if (L->hookmask) { |
1672 | L->top = ra; | 1681 | L->top = ra; |
1673 | halfProtectNT(luaD_poscall(L, ci, 0)); /* no hurry... */ | 1682 | savepc(ci); |
1683 | luaD_poscall(L, ci, 0); /* no hurry... */ | ||
1684 | trap = 1; | ||
1674 | } | 1685 | } |
1675 | else { /* do the 'poscall' here */ | 1686 | else { /* do the 'poscall' here */ |
1676 | int nres = ci->nresults; | 1687 | int nres = ci->nresults; |
@@ -1679,12 +1690,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1679 | while (nres-- > 0) | 1690 | while (nres-- > 0) |
1680 | setnilvalue(s2v(L->top++)); /* all results are nil */ | 1691 | setnilvalue(s2v(L->top++)); /* all results are nil */ |
1681 | } | 1692 | } |
1682 | return; | 1693 | goto ret; |
1683 | } | 1694 | } |
1684 | vmcase(OP_RETURN1) { | 1695 | vmcase(OP_RETURN1) { |
1685 | if (L->hookmask) { | 1696 | if (L->hookmask) { |
1686 | L->top = ra + 1; | 1697 | L->top = ra + 1; |
1687 | halfProtectNT(luaD_poscall(L, ci, 1)); /* no hurry... */ | 1698 | savepc(ci); |
1699 | luaD_poscall(L, ci, 1); /* no hurry... */ | ||
1700 | trap = 1; | ||
1688 | } | 1701 | } |
1689 | else { /* do the 'poscall' here */ | 1702 | else { /* do the 'poscall' here */ |
1690 | int nres = ci->nresults; | 1703 | int nres = ci->nresults; |
@@ -1698,7 +1711,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1698 | setnilvalue(s2v(L->top++)); | 1711 | setnilvalue(s2v(L->top++)); |
1699 | } | 1712 | } |
1700 | } | 1713 | } |
1701 | return; | 1714 | ret: /* return from a Lua function */ |
1715 | if (ci->callstatus & CIST_FRESH) | ||
1716 | return; /* end this frame */ | ||
1717 | else { | ||
1718 | ci = ci->previous; | ||
1719 | goto returning; /* continue running caller in this frame */ | ||
1720 | } | ||
1702 | } | 1721 | } |
1703 | vmcase(OP_FORLOOP) { | 1722 | vmcase(OP_FORLOOP) { |
1704 | if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ | 1723 | if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ |