summaryrefslogtreecommitdiff
path: root/src/lj_dispatch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_dispatch.c')
-rw-r--r--src/lj_dispatch.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c
index 42ffd2b8..b83912c5 100644
--- a/src/lj_dispatch.c
+++ b/src/lj_dispatch.c
@@ -62,6 +62,7 @@ void lj_dispatch_init_hotcount(global_State *g)
62#define DISPMODE_REC 0x02 /* Recording active. */ 62#define DISPMODE_REC 0x02 /* Recording active. */
63#define DISPMODE_INS 0x04 /* Override instruction dispatch. */ 63#define DISPMODE_INS 0x04 /* Override instruction dispatch. */
64#define DISPMODE_CALL 0x08 /* Override call dispatch. */ 64#define DISPMODE_CALL 0x08 /* Override call dispatch. */
65#define DISPMODE_RET 0x08 /* Override return dispatch. */
65 66
66/* Update dispatch table depending on various flags. */ 67/* Update dispatch table depending on various flags. */
67void lj_dispatch_update(global_State *g) 68void lj_dispatch_update(global_State *g)
@@ -74,6 +75,7 @@ void lj_dispatch_update(global_State *g)
74#endif 75#endif
75 mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0; 76 mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0;
76 mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0; 77 mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0;
78 mode |= (g->hookmask & LUA_MASKRET) ? DISPMODE_RET : 0;
77 if (oldmode != mode) { /* Mode changed? */ 79 if (oldmode != mode) { /* Mode changed? */
78 ASMFunction *disp = G2GG(g)->dispatch; 80 ASMFunction *disp = G2GG(g)->dispatch;
79 ASMFunction f_forl, f_iterl, f_loop, f_funcf, f_funcv; 81 ASMFunction f_forl, f_iterl, f_loop, f_funcf, f_funcv;
@@ -104,18 +106,37 @@ void lj_dispatch_update(global_State *g)
104 if (!(mode & (DISPMODE_REC|DISPMODE_INS))) { /* No ins dispatch? */ 106 if (!(mode & (DISPMODE_REC|DISPMODE_INS))) { /* No ins dispatch? */
105 /* Copy static dispatch table to dynamic dispatch table. */ 107 /* Copy static dispatch table to dynamic dispatch table. */
106 memcpy(&disp[0], &disp[GG_LEN_DDISP], GG_LEN_SDISP*sizeof(ASMFunction)); 108 memcpy(&disp[0], &disp[GG_LEN_DDISP], GG_LEN_SDISP*sizeof(ASMFunction));
109 /* Overwrite with dynamic return dispatch. */
110 if ((mode & DISPMODE_RET)) {
111 disp[BC_RETM] = lj_vm_rethook;
112 disp[BC_RET] = lj_vm_rethook;
113 disp[BC_RET0] = lj_vm_rethook;
114 disp[BC_RET1] = lj_vm_rethook;
115 }
107 } else { 116 } else {
108 /* The recording dispatch also checks for hooks. */ 117 /* The recording dispatch also checks for hooks. */
109 ASMFunction f = (mode & DISPMODE_REC) ? lj_vm_record : lj_vm_hook; 118 ASMFunction f = (mode & DISPMODE_REC) ? lj_vm_record : lj_vm_inshook;
110 uint32_t i; 119 uint32_t i;
111 for (i = 0; i < GG_LEN_SDISP; i++) 120 for (i = 0; i < GG_LEN_SDISP; i++)
112 disp[i] = f; 121 disp[i] = f;
113 } 122 }
114 } else if (!(mode & (DISPMODE_REC|DISPMODE_INS))) { 123 } else if (!(mode & (DISPMODE_REC|DISPMODE_INS))) {
115 /* Otherwise only set dynamic counting ins. */ 124 /* Otherwise set dynamic counting ins. */
116 disp[BC_FORL] = f_forl; 125 disp[BC_FORL] = f_forl;
117 disp[BC_ITERL] = f_iterl; 126 disp[BC_ITERL] = f_iterl;
118 disp[BC_LOOP] = f_loop; 127 disp[BC_LOOP] = f_loop;
128 /* Set dynamic return dispatch. */
129 if ((mode & DISPMODE_RET)) {
130 disp[BC_RETM] = lj_vm_rethook;
131 disp[BC_RET] = lj_vm_rethook;
132 disp[BC_RET0] = lj_vm_rethook;
133 disp[BC_RET1] = lj_vm_rethook;
134 } else {
135 disp[BC_RETM] = disp[GG_LEN_DDISP+BC_RETM];
136 disp[BC_RET] = disp[GG_LEN_DDISP+BC_RET];
137 disp[BC_RET0] = disp[GG_LEN_DDISP+BC_RET0];
138 disp[BC_RET1] = disp[GG_LEN_DDISP+BC_RET1];
139 }
119 } 140 }
120 141
121 /* Set dynamic call dispatch. */ 142 /* Set dynamic call dispatch. */
@@ -321,7 +342,7 @@ static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres)
321 } 342 }
322} 343}
323 344
324/* Instruction dispatch. Used by instr/line hooks or when recording. */ 345/* Instruction dispatch. Used by instr/line/return hooks or when recording. */
325void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc) 346void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc)
326{ 347{
327 GCfunc *fn = curr_func(L); 348 GCfunc *fn = curr_func(L);
@@ -348,17 +369,22 @@ void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc)
348 if ((g->hookmask & LUA_MASKCOUNT) && g->hookcount == 0) { 369 if ((g->hookmask & LUA_MASKCOUNT) && g->hookcount == 0) {
349 g->hookcount = g->hookcstart; 370 g->hookcount = g->hookcstart;
350 callhook(L, LUA_HOOKCOUNT, -1); 371 callhook(L, LUA_HOOKCOUNT, -1);
372 L->top = L->base + slots; /* Fix top again. */
351 } 373 }
352 if ((g->hookmask & LUA_MASKLINE)) { 374 if ((g->hookmask & LUA_MASKLINE)) {
353 BCPos npc = proto_bcpos(pt, pc) - 1; 375 BCPos npc = proto_bcpos(pt, pc) - 1;
354 BCPos opc = proto_bcpos(pt, oldpc) - 1; 376 BCPos opc = proto_bcpos(pt, oldpc) - 1;
355 BCLine line = proto_line(pt, npc); 377 BCLine line = proto_line(pt, npc);
356 if (npc == 0 || pc <= oldpc || 378 if (pc <= oldpc || opc >= pt->sizebc || line != proto_line(pt, opc)) {
357 opc >= pt->sizebc || line != proto_line(pt, opc)) {
358 L->top = L->base + slots; /* Fix top again after instruction hook. */
359 callhook(L, LUA_HOOKLINE, line); 379 callhook(L, LUA_HOOKLINE, line);
380 L->top = L->base + slots; /* Fix top again. */
360 } 381 }
361 } 382 }
383 if ((g->hookmask & LUA_MASKRET)) {
384 BCOp op = bc_op(pc[-1]);
385 if (op == BC_RETM || op == BC_RET || op == BC_RET0 || op == BC_RET1)
386 callhook(L, LUA_HOOKRET, -1);
387 }
362} 388}
363 389
364/* Initialize call. Ensure stack space and clear missing parameters. */ 390/* Initialize call. Ensure stack space and clear missing parameters. */