diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-13 13:36:52 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-13 13:36:52 -0200 |
| commit | 5440b42f434ecb6fe7a8e0d19fb8e8baf82e90b7 (patch) | |
| tree | 6a54560da88065db590bf439c7af64fea88334bb | |
| parent | 7d4828cc9fdc982ec713922777e77240892474e8 (diff) | |
| download | lua-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.c | 23 | ||||
| -rw-r--r-- | ldo.c | 15 | ||||
| -rw-r--r-- | lstate.c | 3 | ||||
| -rw-r--r-- | lstate.h | 3 | ||||
| -rw-r--r-- | lvm.c | 47 |
5 files changed, 67 insertions, 24 deletions
| @@ -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 | */ | ||
| 118 | static 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 | ||
| @@ -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) { | |||
| 159 | static void correctstack (lua_State *L, StkId oldstack) { | 159 | static 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 | ||
| 279 | static void callhook (lua_State *L, CallInfo *ci) { | 283 | static 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 | } |
| @@ -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 | } |
| @@ -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 */ |
| @@ -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 | ||
| 804 | void luaV_execute (lua_State *L) { | 811 | void 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 | } |
