aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-11-13 13:36:52 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-11-13 13:36:52 -0200
commit5440b42f434ecb6fe7a8e0d19fb8e8baf82e90b7 (patch)
tree6a54560da88065db590bf439c7af64fea88334bb
parent7d4828cc9fdc982ec713922777e77240892474e8 (diff)
downloadlua-5440b42f434ecb6fe7a8e0d19fb8e8baf82e90b7.tar.gz
lua-5440b42f434ecb6fe7a8e0d19fb8e8baf82e90b7.tar.bz2
lua-5440b42f434ecb6fe7a8e0d19fb8e8baf82e90b7.zip
using 'trap' to stop 'luaV_execute' when necessary (tracing and
to update its copy of 'base' when the stack is reallocated)
-rw-r--r--ldebug.c23
-rw-r--r--ldo.c15
-rw-r--r--lstate.c3
-rw-r--r--lstate.h3
-rw-r--r--lvm.c47
5 files changed, 67 insertions, 24 deletions
diff --git a/ldebug.c b/ldebug.c
index 89b36f07..7323f23a 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 2.142 2017/11/08 14:50:23 roberto Exp roberto $ 2** $Id: ldebug.c,v 2.143 2017/11/13 12:20:51 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*/
@@ -107,7 +107,24 @@ static int currentline (CallInfo *ci) {
107 107
108 108
109/* 109/*
110** This function can be called asynchronously (e.g. during a signal). 110** This function can be called asynchronously (e.g. during a signal),
111** under "reasonable" assumptions. A new 'ci' is completely linked
112** in the list before it becomes part of the "active" list, and
113** we assume that pointers are atomic (see comment in next function).
114** (If we traverse one more item, there is no problem. If we traverse
115** one less item, the worst that can happen is that the signal will
116** not interrupt the script.)
117*/
118static void settraps (CallInfo *ci) {
119 for (; ci != NULL; ci = ci->previous)
120 if (isLua(ci))
121 ci->u.l.trap = 1;
122}
123
124
125/*
126** This function can be called asynchronously (e.g. during a signal),
127** under "reasonable" assumptions.
111** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by 128** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
112** 'resethookcount') are for debug only, and it is no problem if they 129** 'resethookcount') are for debug only, and it is no problem if they
113** get arbitrary values (causes at most one wrong hook call). 'hookmask' 130** get arbitrary values (causes at most one wrong hook call). 'hookmask'
@@ -126,6 +143,8 @@ LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
126 L->basehookcount = count; 143 L->basehookcount = count;
127 resethookcount(L); 144 resethookcount(L);
128 L->hookmask = cast_byte(mask); 145 L->hookmask = cast_byte(mask);
146 if (mask & (LUA_MASKLINE | LUA_MASKCOUNT))
147 settraps(L->ci); /* to trace inside 'luaV_execute' */
129} 148}
130 149
131 150
diff --git a/ldo.c b/ldo.c
index 86e77f97..970b890b 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.170 2017/11/07 13:25:26 roberto Exp roberto $ 2** $Id: ldo.c,v 2.171 2017/11/13 12:26:30 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -159,12 +159,16 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
159static void correctstack (lua_State *L, StkId oldstack) { 159static void correctstack (lua_State *L, StkId oldstack) {
160 CallInfo *ci; 160 CallInfo *ci;
161 UpVal *up; 161 UpVal *up;
162 if (L->stack == oldstack)
163 return; /* stack address did not change */
162 L->top = (L->top - oldstack) + L->stack; 164 L->top = (L->top - oldstack) + L->stack;
163 for (up = L->openupval; up != NULL; up = up->u.open.next) 165 for (up = L->openupval; up != NULL; up = up->u.open.next)
164 up->v = s2v((uplevel(up) - oldstack) + L->stack); 166 up->v = s2v((uplevel(up) - oldstack) + L->stack);
165 for (ci = L->ci; ci != NULL; ci = ci->previous) { 167 for (ci = L->ci; ci != NULL; ci = ci->previous) {
166 ci->top = (ci->top - oldstack) + L->stack; 168 ci->top = (ci->top - oldstack) + L->stack;
167 ci->func = (ci->func - oldstack) + L->stack; 169 ci->func = (ci->func - oldstack) + L->stack;
170 if (isLua(ci))
171 ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */
168 } 172 }
169} 173}
170 174
@@ -277,13 +281,18 @@ void luaD_hook (lua_State *L, int event, int line) {
277 281
278 282
279static void callhook (lua_State *L, CallInfo *ci) { 283static void callhook (lua_State *L, CallInfo *ci) {
280 int hook = LUA_HOOKCALL; 284 int hook;
285 ci->u.l.trap = 1;
286 if (!(L->hookmask & LUA_MASKCALL))
287 return; /* some other hook */
281 ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ 288 ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
282 if (isLua(ci->previous) && 289 if (isLua(ci->previous) &&
283 GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { 290 GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) {
284 ci->callstatus |= CIST_TAIL; 291 ci->callstatus |= CIST_TAIL;
285 hook = LUA_HOOKTAILCALL; 292 hook = LUA_HOOKTAILCALL;
286 } 293 }
294 else
295 hook = LUA_HOOKCALL;
287 luaD_hook(L, hook, -1); 296 luaD_hook(L, hook, -1);
288 ci->u.l.savedpc--; /* correct 'pc' */ 297 ci->u.l.savedpc--; /* correct 'pc' */
289} 298}
@@ -430,7 +439,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
430 lua_assert(ci->top <= L->stack_last); 439 lua_assert(ci->top <= L->stack_last);
431 ci->u.l.savedpc = p->code; /* starting point */ 440 ci->u.l.savedpc = p->code; /* starting point */
432 ci->callstatus = CIST_LUA; 441 ci->callstatus = CIST_LUA;
433 if (L->hookmask & LUA_MASKCALL) 442 if (L->hookmask)
434 callhook(L, ci); 443 callhook(L, ci);
435 return 0; 444 return 0;
436 } 445 }
diff --git a/lstate.c b/lstate.c
index 7f67527b..54e390b5 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.143 2017/10/31 17:54:35 roberto Exp $ 2** $Id: lstate.c,v 2.146 2017/11/07 13:25:26 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -103,6 +103,7 @@ CallInfo *luaE_extendCI (lua_State *L) {
103 L->ci->next = ci; 103 L->ci->next = ci;
104 ci->previous = L->ci; 104 ci->previous = L->ci;
105 ci->next = NULL; 105 ci->next = NULL;
106 ci->u.l.trap = 0;
106 L->nci++; 107 L->nci++;
107 return ci; 108 return ci;
108} 109}
diff --git a/lstate.h b/lstate.h
index 4798474c..02715dfb 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.146 2017/11/02 11:28:56 roberto Exp $ 2** $Id: lstate.h,v 2.150 2017/11/07 13:25:26 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -91,6 +91,7 @@ typedef struct CallInfo {
91 union { 91 union {
92 struct { /* only for Lua functions */ 92 struct { /* only for Lua functions */
93 const Instruction *savedpc; 93 const Instruction *savedpc;
94 l_signalT trap;
94 } l; 95 } l;
95 struct { /* only for C functions */ 96 struct { /* only for C functions */
96 lua_KFunction k; /* continuation in case of yields */ 97 lua_KFunction k; /* continuation in case of yields */
diff --git a/lvm.c b/lvm.c
index c91fa638..a8285ac6 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.308 2017/11/08 14:50:23 roberto Exp roberto $ 2** $Id: lvm.c,v 2.309 2017/11/08 19:01:02 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*/
@@ -756,14 +756,16 @@ void luaV_finishOp (lua_State *L) {
756 756
757 757
758 758
759#define updatemask(L) (mask = L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) 759#define updatetrap(ci) (trap = ci->u.l.trap)
760
761#define updatebase(ci) (base = ci->func + 1)
760 762
761 763
762/* 764/*
763** Execute a jump instruction. The 'updatemask' allows signals to stop 765** Execute a jump instruction. The 'updatetrap' allows signals to stop
764** tight loops. (Without it, the local copy of 'mask' could never change.) 766** tight loops. (Without it, the local copy of 'trap' could never change.)
765*/ 767*/
766#define dojump(ci,i,e) { pc += GETARG_sJ(i) + e; updatemask(L); } 768#define dojump(ci,i,e) { pc += GETARG_sJ(i) + e; updatetrap(ci); }
767 769
768 770
769/* for test instructions, execute the jump instruction that follows it */ 771/* for test instructions, execute the jump instruction that follows it */
@@ -780,19 +782,24 @@ void luaV_finishOp (lua_State *L) {
780** Protect code that, in general, can raise errors, reallocate the 782** Protect code that, in general, can raise errors, reallocate the
781** stack, and change the hooks. 783** stack, and change the hooks.
782*/ 784*/
783#define Protect(exp) (savepc(L), (exp), base = ci->func + 1, updatemask(L)) 785#define Protect(exp) (savepc(L), (exp), updatetrap(ci))
784 786
785 787
786#define checkGC(L,c) \ 788#define checkGC(L,c) \
787 { luaC_condGC(L, L->top = (c), /* limit of live values */ \ 789 { luaC_condGC(L, L->top = (c), /* limit of live values */ \
788 Protect(L->top = ci->top)); /* restore top */ \ 790 (L->top = ci->top, updatetrap(ci))); /* restore top */ \
789 luai_threadyield(L); } 791 luai_threadyield(L); }
790 792
791 793
792/* fetch an instruction and prepare its execution */ 794/* fetch an instruction and prepare its execution */
793#define vmfetch() { \ 795#define vmfetch() { \
794 i = *(pc++); \ 796 i = *(pc++); \
795 if (mask) Protect(luaG_traceexec(L)); \ 797 if (trap) { \
798 if (!(L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT))) \
799 trap = ci->u.l.trap = 0; /* no need to stop again */ \
800 else { savepc(L); luaG_traceexec(L); } \
801 updatebase(ci); /* the trap may be just for that */ \
802 } \
796 ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ 803 ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
797} 804}
798 805
@@ -802,19 +809,19 @@ void luaV_finishOp (lua_State *L) {
802 809
803 810
804void luaV_execute (lua_State *L) { 811void luaV_execute (lua_State *L) {
805 CallInfo *ci = L->ci; 812 CallInfo *ci = L->ci; /* local copy of 'L->ci' */
806 LClosure *cl; 813 LClosure *cl;
807 TValue *k; 814 TValue *k;
808 StkId base; /* local copy of 'ci->func + 1' */ 815 StkId base; /* local copy of 'ci->func + 1' */
809 int mask; /* local copy of 'L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)' */ 816 int trap;
810 const Instruction *pc; /* local copy of 'ci->u.l.savedpc' */ 817 const Instruction *pc; /* local copy of 'ci->u.l.savedpc' */
811 ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ 818 ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */
812 newframe: /* reentry point when frame changes (call/return) */ 819 newframe: /* reentry point when frame changes (call/return) */
813 lua_assert(ci == L->ci); 820 lua_assert(ci == L->ci);
814 cl = clLvalue(s2v(ci->func)); /* local reference to function's closure */ 821 cl = clLvalue(s2v(ci->func)); /* local reference to function's closure */
815 k = cl->p->k; /* local reference to function's constant table */ 822 k = cl->p->k; /* local reference to function's constant table */
816 updatemask(L); 823 updatetrap(ci);
817 base = ci->func + 1; 824 updatebase(ci);
818 pc = ci->u.l.savedpc; 825 pc = ci->u.l.savedpc;
819 /* main loop of interpreter */ 826 /* main loop of interpreter */
820 for (;;) { 827 for (;;) {
@@ -1294,7 +1301,10 @@ void luaV_execute (lua_State *L) {
1294 StkId rb; 1301 StkId rb;
1295 L->top = base + c + 1; /* mark the end of concat operands */ 1302 L->top = base + c + 1; /* mark the end of concat operands */
1296 Protect(luaV_concat(L, c - b + 1)); 1303 Protect(luaV_concat(L, c - b + 1));
1297 ra = RA(i); /* 'luaV_concat' may invoke TMs and move the stack */ 1304 if (trap) { /* 'luaV_concat' may move the stack */
1305 updatebase(ci);
1306 ra = RA(i);
1307 }
1298 rb = base + b; 1308 rb = base + b;
1299 setobjs2s(L, ra, rb); 1309 setobjs2s(L, ra, rb);
1300 checkGC(L, (ra >= rb ? ra + 1 : rb)); 1310 checkGC(L, (ra >= rb ? ra + 1 : rb));
@@ -1390,7 +1400,7 @@ void luaV_execute (lua_State *L) {
1390 lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); 1400 lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
1391 savepc(L); 1401 savepc(L);
1392 if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */ 1402 if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */
1393 Protect((void)0); /* update 'base' */ 1403 updatetrap(ci);
1394 else { 1404 else {
1395 /* tail call: put called frame (n) in place of caller one (o) */ 1405 /* tail call: put called frame (n) in place of caller one (o) */
1396 CallInfo *nci = L->ci; /* called frame (new) */ 1406 CallInfo *nci = L->ci; /* called frame (new) */
@@ -1416,7 +1426,8 @@ void luaV_execute (lua_State *L) {
1416 } 1426 }
1417 vmcase(OP_RETURN) { 1427 vmcase(OP_RETURN) {
1418 int b = GETARG_B(i); 1428 int b = GETARG_B(i);
1419 if (cl->p->sizep > 0) luaF_close(L, base); 1429 if (cl->p->sizep > 0)
1430 luaF_close(L, base);
1420 savepc(L); 1431 savepc(L);
1421 b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); 1432 b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
1422 if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ 1433 if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */
@@ -1452,7 +1463,7 @@ void luaV_execute (lua_State *L) {
1452 setfltvalue(s2v(ra + 3), idx); /* ...and external index */ 1463 setfltvalue(s2v(ra + 3), idx); /* ...and external index */
1453 } 1464 }
1454 } 1465 }
1455 updatemask(L); 1466 updatetrap(ci);
1456 vmbreak; 1467 vmbreak;
1457 } 1468 }
1458 vmcase(OP_FORPREP) { 1469 vmcase(OP_FORPREP) {
@@ -1492,8 +1503,10 @@ void luaV_execute (lua_State *L) {
1492 L->top = cb + 3; /* func. + 2 args (state and index) */ 1503 L->top = cb + 3; /* func. + 2 args (state and index) */
1493 Protect(luaD_call(L, cb, GETARG_C(i))); 1504 Protect(luaD_call(L, cb, GETARG_C(i)));
1494 L->top = ci->top; 1505 L->top = ci->top;
1506 if (trap) /* keep 'base' correct for next instruction */
1507 updatebase(ci);
1495 i = *(pc++); /* go to next instruction */ 1508 i = *(pc++); /* go to next instruction */
1496 ra = RA(i); 1509 ra = RA(i); /* get its 'ra' */
1497 lua_assert(GET_OPCODE(i) == OP_TFORLOOP); 1510 lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
1498 goto l_tforloop; 1511 goto l_tforloop;
1499 } 1512 }