aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-12-28 13:42:57 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-12-28 13:42:57 -0200
commitcf7eff45f3abf2386d5392c0b431498bbb274ac7 (patch)
tree0eaafe3456bd03b241e447f1375296341fb648e8
parent8691612f01ae4b32d861464032521d969766c1c5 (diff)
downloadlua-cf7eff45f3abf2386d5392c0b431498bbb274ac7.tar.gz
lua-cf7eff45f3abf2386d5392c0b431498bbb274ac7.tar.bz2
lua-cf7eff45f3abf2386d5392c0b431498bbb274ac7.zip
keep control of stack top in Lua functions concentrated in 'luaV_execute'
-rw-r--r--ldebug.c9
-rw-r--r--lgc.c11
-rw-r--r--ltm.c22
-rw-r--r--lvm.c46
4 files changed, 40 insertions, 48 deletions
diff --git a/ldebug.c b/ldebug.c
index 80c19d31..52335600 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 2.149 2017/12/15 13:07:10 roberto Exp roberto $ 2** $Id: ldebug.c,v 2.150 2017/12/20 14:58:05 roberto Exp roberto $
3** Debug Interface 3** Debug Interface
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -737,8 +737,6 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
737 const char *msg; 737 const char *msg;
738 va_list argp; 738 va_list argp;
739 luaC_checkGC(L); /* error message uses memory */ 739 luaC_checkGC(L); /* error message uses memory */
740 if (isLuacode(ci))
741 L->top = ci->top; /* prepare top */
742 va_start(argp, fmt); 740 va_start(argp, fmt);
743 msg = luaO_pushvfstring(L, fmt, argp); /* format message */ 741 msg = luaO_pushvfstring(L, fmt, argp); /* format message */
744 va_end(argp); 742 va_end(argp);
@@ -762,7 +760,6 @@ static int changedline (Proto *p, int oldpc, int newpc) {
762 760
763 761
764void luaG_traceexec (lua_State *L) { 762void luaG_traceexec (lua_State *L) {
765 ptrdiff_t oldtop = savestack(L, L->top);
766 CallInfo *ci = L->ci; 763 CallInfo *ci = L->ci;
767 lu_byte mask = L->hookmask; 764 lu_byte mask = L->hookmask;
768 int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); 765 int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
@@ -774,7 +771,8 @@ void luaG_traceexec (lua_State *L) {
774 ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ 771 ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
775 return; /* do not call hook again (VM yielded, so it did not move) */ 772 return; /* do not call hook again (VM yielded, so it did not move) */
776 } 773 }
777 L->top = ci->top; /* prepare top */ 774 if (!isIT(*(ci->u.l.savedpc - 1)))
775 L->top = ci->top; /* prepare top */
778 if (counthook) 776 if (counthook)
779 luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ 777 luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */
780 if (mask & LUA_MASKLINE) { 778 if (mask & LUA_MASKLINE) {
@@ -789,7 +787,6 @@ void luaG_traceexec (lua_State *L) {
789 } 787 }
790 L->oldpc = npc; 788 L->oldpc = npc;
791 } 789 }
792 L->top = restorestack(L, oldtop);
793 if (L->status == LUA_YIELD) { /* did hook yield? */ 790 if (L->status == LUA_YIELD) { /* did hook yield? */
794 if (counthook) 791 if (counthook)
795 L->hookcount = 1; /* undo decrement to zero */ 792 L->hookcount = 1; /* undo decrement to zero */
diff --git a/lgc.c b/lgc.c
index 37bcdb8d..d02dc031 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.242 2017/12/08 17:28:25 roberto Exp roberto $ 2** $Id: lgc.c,v 2.243 2017/12/20 14:58:05 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -571,21 +571,16 @@ static int traverseLclosure (global_State *g, LClosure *cl) {
571 571
572/* 572/*
573** Traverse a thread, marking the elements in the stack up to its top 573** Traverse a thread, marking the elements in the stack up to its top
574** and cleaning the rest of the stack in the last traversal. 574** and cleaning the rest of the stack in the final traversal.
575** That ensures that the entire stack have valid (non-dead) objects. 575** That ensures that the entire stack have valid (non-dead) objects.
576** In an emergency collection running Lua code, 'L->top' may not be
577** update. In that case, traverse at least up to 'ci->top'.
578*/ 576*/
579static int traversethread (global_State *g, lua_State *th) { 577static int traversethread (global_State *g, lua_State *th) {
580 StkId o = th->stack; 578 StkId o = th->stack;
581 StkId top = th->top;
582 if (o == NULL) 579 if (o == NULL)
583 return 1; /* stack not completely built yet */ 580 return 1; /* stack not completely built yet */
584 lua_assert(g->gcstate == GCSatomic || 581 lua_assert(g->gcstate == GCSatomic ||
585 th->openupval == NULL || isintwups(th)); 582 th->openupval == NULL || isintwups(th));
586 if (g->gcemergency && isLuacode(th->ci) && top < th->ci->top) 583 for (; o < th->top; o++) /* mark live elements in the stack */
587 top = th->ci->top;
588 for (; o < top; o++) /* mark live elements in the stack */
589 markvalue(g, s2v(o)); 584 markvalue(g, s2v(o));
590 if (g->gcstate == GCSatomic) { /* final traversal? */ 585 if (g->gcstate == GCSatomic) { /* final traversal? */
591 StkId lim = th->stack + th->stacksize; /* real end of stack */ 586 StkId lim = th->stack + th->stacksize; /* real end of stack */
diff --git a/ltm.c b/ltm.c
index d41ab98d..4b14f197 100644
--- a/ltm.c
+++ b/ltm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.c,v 2.54 2017/12/19 16:40:17 roberto Exp roberto $ 2** $Id: ltm.c,v 2.55 2017/12/20 14:58:05 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -101,7 +101,7 @@ const char *luaT_objtypename (lua_State *L, const TValue *o) {
101 101
102void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, 102void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
103 const TValue *p2, const TValue *p3) { 103 const TValue *p2, const TValue *p3) {
104 StkId func = (isLuacode(L->ci)) ? L->ci->top : L->top; 104 StkId func = L->top;
105 setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ 105 setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */
106 setobj2s(L, func + 1, p1); /* 1st argument */ 106 setobj2s(L, func + 1, p1); /* 1st argument */
107 setobj2s(L, func + 2, p2); /* 2nd argument */ 107 setobj2s(L, func + 2, p2); /* 2nd argument */
@@ -115,8 +115,8 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
115} 115}
116 116
117 117
118static void reallycallTMres (lua_State *L, const TValue *f, const TValue *p1, 118void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
119 const TValue *p2, StkId res) { 119 const TValue *p2, StkId res) {
120 ptrdiff_t result = savestack(L, res); 120 ptrdiff_t result = savestack(L, res);
121 StkId func = L->top; 121 StkId func = L->top;
122 setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ 122 setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */
@@ -133,29 +133,19 @@ static void reallycallTMres (lua_State *L, const TValue *f, const TValue *p1,
133} 133}
134 134
135 135
136void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
137 const TValue *p2, StkId res) {
138 if (isLuacode(L->ci))
139 L->top = L->ci->top; /* prepare top */
140 reallycallTMres(L, f, p1, p2, res);
141}
142
143
144static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2, 136static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
145 StkId res, TMS event) { 137 StkId res, TMS event) {
146 const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ 138 const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
147 if (ttisnil(tm)) 139 if (ttisnil(tm))
148 tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ 140 tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
149 if (ttisnil(tm)) return 0; 141 if (ttisnil(tm)) return 0;
150 reallycallTMres(L, tm, p1, p2, res); 142 luaT_callTMres(L, tm, p1, p2, res);
151 return 1; 143 return 1;
152} 144}
153 145
154 146
155void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 147void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
156 StkId res, TMS event) { 148 StkId res, TMS event) {
157 if (event != TM_CONCAT && isLuacode(L->ci))
158 L->top = L->ci->top; /* prepare top */
159 if (!callbinTM(L, p1, p2, res, event)) { 149 if (!callbinTM(L, p1, p2, res, event)) {
160 switch (event) { 150 switch (event) {
161 case TM_CONCAT: 151 case TM_CONCAT:
@@ -195,8 +185,6 @@ void luaT_trybiniTM (lua_State *L, const TValue *p1, int i2,
195 185
196int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, 186int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
197 TMS event) { 187 TMS event) {
198 if (isLuacode(L->ci))
199 L->top = L->ci->top; /* prepare top */
200 if (callbinTM(L, p1, p2, L->top, event)) /* try original event */ 188 if (callbinTM(L, p1, p2, L->top, event)) /* try original event */
201 return !l_isfalse(s2v(L->top)); 189 return !l_isfalse(s2v(L->top));
202 else if (event == TM_LE) { 190 else if (event == TM_LE) {
diff --git a/lvm.c b/lvm.c
index 89646d24..212d5f9d 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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