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 |
