diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-12-28 13:42:57 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-12-28 13:42:57 -0200 |
commit | cf7eff45f3abf2386d5392c0b431498bbb274ac7 (patch) | |
tree | 0eaafe3456bd03b241e447f1375296341fb648e8 /lvm.c | |
parent | 8691612f01ae4b32d861464032521d969766c1c5 (diff) | |
download | lua-cf7eff45f3abf2386d5392c0b431498bbb274ac7.tar.gz lua-cf7eff45f3abf2386d5392c0b431498bbb274ac7.tar.bz2 lua-cf7eff45f3abf2386d5392c0b431498bbb274ac7.zip |
keep control of stack top in Lua functions concentrated in 'luaV_execute'
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 46 |
1 files changed, 29 insertions, 17 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.328 2017/12/20 14:58:05 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.329 2017/12/22 14:16:46 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 | */ |
@@ -464,8 +464,6 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { | |||
464 | } | 464 | } |
465 | if (tm == NULL) /* no TM? */ | 465 | if (tm == NULL) /* no TM? */ |
466 | return 0; /* objects are different */ | 466 | return 0; /* objects are different */ |
467 | if (isLuacode(L->ci)) | ||
468 | L->top = L->ci->top; /* prepare top */ | ||
469 | luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */ | 467 | luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */ |
470 | return !l_isfalse(s2v(L->top)); | 468 | return !l_isfalse(s2v(L->top)); |
471 | } | 469 | } |
@@ -780,20 +778,29 @@ void luaV_finishOp (lua_State *L) { | |||
780 | #define donextjump(ci) { i = *pc; dojump(ci, i, 1); } | 778 | #define donextjump(ci) { i = *pc; dojump(ci, i, 1); } |
781 | 779 | ||
782 | /* | 780 | /* |
783 | ** Whenever code can raise errors (including memory errors), the global | 781 | ** Correct global 'pc'. |
784 | ** 'pc' must be correct to report occasional errors. | ||
785 | */ | 782 | */ |
786 | #define savepc(L) (ci->u.l.savedpc = pc) | 783 | #define savepc(L) (ci->u.l.savedpc = pc) |
787 | 784 | ||
788 | 785 | ||
789 | /* | 786 | /* |
787 | ** Whenever code can raise errors, the global 'pc' and the global | ||
788 | ** 'top' must be correct to report occasional errors. | ||
789 | */ | ||
790 | #define savestate(L,ci) (savepc(L), L->top = ci->top) | ||
791 | |||
792 | |||
793 | /* | ||
790 | ** Protect code that, in general, can raise errors, reallocate the | 794 | ** Protect code that, in general, can raise errors, reallocate the |
791 | ** stack, and change the hooks. | 795 | ** stack, and change the hooks. |
792 | */ | 796 | */ |
793 | #define Protect(exp) (savepc(L), (exp), updatetrap(ci)) | 797 | #define Protect(exp) (savestate(L,ci), (exp), updatetrap(ci)) |
798 | |||
799 | /* special version that does not change the top */ | ||
800 | #define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci)) | ||
794 | 801 | ||
795 | /* | 802 | /* |
796 | ** Protect code that will return. | 803 | ** Protect code that will finish the loop (returns). |
797 | */ | 804 | */ |
798 | #define halfProtect(exp) (savepc(L), (exp)) | 805 | #define halfProtect(exp) (savepc(L), (exp)) |
799 | 806 | ||
@@ -842,6 +849,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
842 | vmfetch(); | 849 | vmfetch(); |
843 | lua_assert(base == ci->func + 1); | 850 | lua_assert(base == ci->func + 1); |
844 | lua_assert(base <= L->top && L->top < L->stack + L->stacksize); | 851 | lua_assert(base <= L->top && L->top < L->stack + L->stacksize); |
852 | lua_assert(ci->top < L->stack + L->stacksize); | ||
845 | vmdispatch (GET_OPCODE(i)) { | 853 | vmdispatch (GET_OPCODE(i)) { |
846 | vmcase(OP_MOVE) { | 854 | vmcase(OP_MOVE) { |
847 | setobjs2s(L, ra, RB(i)); | 855 | setobjs2s(L, ra, RB(i)); |
@@ -1000,10 +1008,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1000 | int b = GETARG_B(i); | 1008 | int b = GETARG_B(i); |
1001 | int c = GETARG_C(i); | 1009 | int c = GETARG_C(i); |
1002 | Table *t; | 1010 | Table *t; |
1003 | t = luaH_new(L); | 1011 | L->top = ci->top; /* correct top in case of GC */ |
1012 | t = luaH_new(L); /* memory allocation */ | ||
1004 | sethvalue2s(L, ra, t); | 1013 | sethvalue2s(L, ra, t); |
1005 | if (b != 0 || c != 0) | 1014 | if (b != 0 || c != 0) |
1006 | luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); | 1015 | luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); /* idem */ |
1007 | checkGC(L, ra + 1); | 1016 | checkGC(L, ra + 1); |
1008 | vmbreak; | 1017 | vmbreak; |
1009 | } | 1018 | } |
@@ -1371,7 +1380,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1371 | int c = GETARG_C(i); | 1380 | int c = GETARG_C(i); |
1372 | StkId rb; | 1381 | StkId rb; |
1373 | L->top = base + c + 1; /* mark the end of concat operands */ | 1382 | L->top = base + c + 1; /* mark the end of concat operands */ |
1374 | Protect(luaV_concat(L, c - b + 1)); | 1383 | ProtectNT(luaV_concat(L, c - b + 1)); |
1375 | if (trap) { /* 'luaV_concat' may move the stack */ | 1384 | if (trap) { /* 'luaV_concat' may move the stack */ |
1376 | updatebase(ci); | 1385 | updatebase(ci); |
1377 | ra = RA(i); | 1386 | ra = RA(i); |
@@ -1481,7 +1490,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1481 | if (b != 0) /* fixed number of arguments? */ | 1490 | if (b != 0) /* fixed number of arguments? */ |
1482 | L->top = ra + b; /* top signals number of arguments */ | 1491 | L->top = ra + b; /* top signals number of arguments */ |
1483 | /* else previous instruction set top */ | 1492 | /* else previous instruction set top */ |
1484 | Protect(luaD_call(L, ra, nresults)); | 1493 | ProtectNT(luaD_call(L, ra, nresults)); |
1485 | vmbreak; | 1494 | vmbreak; |
1486 | } | 1495 | } |
1487 | vmcase(OP_TAILCALL) { | 1496 | vmcase(OP_TAILCALL) { |
@@ -1493,12 +1502,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1493 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); | 1502 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); |
1494 | if (!ttisfunction(vra)) { /* not a function? */ | 1503 | if (!ttisfunction(vra)) { /* not a function? */ |
1495 | /* try to get '__call' metamethod */ | 1504 | /* try to get '__call' metamethod */ |
1496 | Protect(ra = luaD_tryfuncTM(L, ra)); | 1505 | ProtectNT(ra = luaD_tryfuncTM(L, ra)); |
1497 | vra = s2v(ra); | 1506 | vra = s2v(ra); |
1498 | b++; /* there is now one extra argument */ | 1507 | b++; /* there is now one extra argument */ |
1499 | } | 1508 | } |
1500 | if (!ttisLclosure(vra)) { /* C function? */ | 1509 | if (!ttisLclosure(vra)) { /* C function? */ |
1501 | Protect(luaD_call(L, ra, LUA_MULTRET)); /* call it */ | 1510 | ProtectNT(luaD_call(L, ra, LUA_MULTRET)); /* call it */ |
1502 | /* next instruction will do the return */ | 1511 | /* next instruction will do the return */ |
1503 | } | 1512 | } |
1504 | else { /* tail call */ | 1513 | else { /* tail call */ |
@@ -1568,7 +1577,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1568 | lua_Integer ilimit, initv; | 1577 | lua_Integer ilimit, initv; |
1569 | int stopnow; | 1578 | int stopnow; |
1570 | if (!forlimit(plimit, &ilimit, 1, &stopnow)) { | 1579 | if (!forlimit(plimit, &ilimit, 1, &stopnow)) { |
1571 | savepc(L); /* for the error message */ | 1580 | savestate(L, ci); /* for the error message */ |
1572 | luaG_runerror(L, "'for' limit must be a number"); | 1581 | luaG_runerror(L, "'for' limit must be a number"); |
1573 | } | 1582 | } |
1574 | initv = (stopnow ? 0 : ivalue(init)); | 1583 | initv = (stopnow ? 0 : ivalue(init)); |
@@ -1618,7 +1627,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1618 | } | 1627 | } |
1619 | else { /* try making all values floats */ | 1628 | else { /* try making all values floats */ |
1620 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; | 1629 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; |
1621 | savepc(L); /* in case of errors */ | 1630 | savestate(L, ci); /* in case of errors */ |
1622 | if (!tonumber(plimit, &nlimit)) | 1631 | if (!tonumber(plimit, &nlimit)) |
1623 | luaG_runerror(L, "'for' limit must be a number"); | 1632 | luaG_runerror(L, "'for' limit must be a number"); |
1624 | setfltvalue(plimit, nlimit); | 1633 | setfltvalue(plimit, nlimit); |
@@ -1659,7 +1668,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1659 | int c = GETARG_C(i); | 1668 | int c = GETARG_C(i); |
1660 | unsigned int last; | 1669 | unsigned int last; |
1661 | Table *h; | 1670 | Table *h; |
1662 | if (n == 0) n = cast_int(L->top - ra) - 1; | 1671 | if (n == 0) |
1672 | n = cast_int(L->top - ra) - 1; | ||
1673 | else | ||
1674 | L->top = ci->top; /* correct top in case of GC */ | ||
1663 | if (c == 0) { | 1675 | if (c == 0) { |
1664 | c = GETARG_Ax(*pc); pc++; | 1676 | c = GETARG_Ax(*pc); pc++; |
1665 | } | 1677 | } |
@@ -1679,7 +1691,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1679 | Proto *p = cl->p->p[GETARG_Bx(i)]; | 1691 | Proto *p = cl->p->p[GETARG_Bx(i)]; |
1680 | LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ | 1692 | LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ |
1681 | if (ncl == NULL) { /* no match? */ | 1693 | if (ncl == NULL) { /* no match? */ |
1682 | savepc(L); /* in case of allocation errors */ | 1694 | savestate(L, ci); /* in case of allocation errors */ |
1683 | pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ | 1695 | pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ |
1684 | } | 1696 | } |
1685 | else | 1697 | else |