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.c109
1 files changed, 89 insertions, 20 deletions
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c
index 72211dca..42ffd2b8 100644
--- a/src/lj_dispatch.c
+++ b/src/lj_dispatch.c
@@ -57,21 +57,30 @@ void lj_dispatch_init_hotcount(global_State *g)
57} 57}
58#endif 58#endif
59 59
60/* Internal dispatch mode bits. */
61#define DISPMODE_JIT 0x01 /* JIT compiler on. */
62#define DISPMODE_REC 0x02 /* Recording active. */
63#define DISPMODE_INS 0x04 /* Override instruction dispatch. */
64#define DISPMODE_CALL 0x08 /* Override call dispatch. */
65
60/* Update dispatch table depending on various flags. */ 66/* Update dispatch table depending on various flags. */
61void lj_dispatch_update(global_State *g) 67void lj_dispatch_update(global_State *g)
62{ 68{
63 uint8_t oldmode = g->dispatchmode; 69 uint8_t oldmode = g->dispatchmode;
64 uint8_t mode = 0; 70 uint8_t mode = 0;
65#if LJ_HASJIT 71#if LJ_HASJIT
66 mode |= (G2J(g)->flags & JIT_F_ON) ? 1 : 0; 72 mode |= (G2J(g)->flags & JIT_F_ON) ? DISPMODE_JIT : 0;
67 mode |= G2J(g)->state != LJ_TRACE_IDLE ? 6 : 0; 73 mode |= G2J(g)->state != LJ_TRACE_IDLE ? (DISPMODE_REC|DISPMODE_INS) : 0;
68#endif 74#endif
69 mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? 2 : 0; 75 mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0;
76 mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0;
70 if (oldmode != mode) { /* Mode changed? */ 77 if (oldmode != mode) { /* Mode changed? */
71 ASMFunction *disp = G2GG(g)->dispatch; 78 ASMFunction *disp = G2GG(g)->dispatch;
72 ASMFunction f_forl, f_iterl, f_loop, f_funcf, f_funcv; 79 ASMFunction f_forl, f_iterl, f_loop, f_funcf, f_funcv;
73 g->dispatchmode = mode; 80 g->dispatchmode = mode;
74 if ((mode & 5) == 1) { /* Hotcount if JIT is on, but not when recording. */ 81
82 /* Hotcount if JIT is on, but not while recording. */
83 if ((mode & (DISPMODE_JIT|DISPMODE_REC)) == DISPMODE_JIT) {
75 f_forl = makeasmfunc(lj_bc_ofs[BC_FORL]); 84 f_forl = makeasmfunc(lj_bc_ofs[BC_FORL]);
76 f_iterl = makeasmfunc(lj_bc_ofs[BC_ITERL]); 85 f_iterl = makeasmfunc(lj_bc_ofs[BC_ITERL]);
77 f_loop = makeasmfunc(lj_bc_ofs[BC_LOOP]); 86 f_loop = makeasmfunc(lj_bc_ofs[BC_LOOP]);
@@ -81,38 +90,53 @@ void lj_dispatch_update(global_State *g)
81 f_forl = disp[GG_LEN_DDISP+BC_IFORL]; 90 f_forl = disp[GG_LEN_DDISP+BC_IFORL];
82 f_iterl = disp[GG_LEN_DDISP+BC_IITERL]; 91 f_iterl = disp[GG_LEN_DDISP+BC_IITERL];
83 f_loop = disp[GG_LEN_DDISP+BC_ILOOP]; 92 f_loop = disp[GG_LEN_DDISP+BC_ILOOP];
84 f_funcf = disp[GG_LEN_DDISP+BC_IFUNCF]; 93 f_funcf = makeasmfunc(lj_bc_ofs[BC_IFUNCF]);
85 f_funcv = disp[GG_LEN_DDISP+BC_IFUNCV]; 94 f_funcv = makeasmfunc(lj_bc_ofs[BC_IFUNCV]);
86 } 95 }
87 /* Set static counting ins first (may be copied below). */ 96 /* Init static counting instruction dispatch first (may be copied below). */
88 disp[GG_LEN_DDISP+BC_FORL] = f_forl; 97 disp[GG_LEN_DDISP+BC_FORL] = f_forl;
89 disp[GG_LEN_DDISP+BC_ITERL] = f_iterl; 98 disp[GG_LEN_DDISP+BC_ITERL] = f_iterl;
90 disp[GG_LEN_DDISP+BC_LOOP] = f_loop; 99 disp[GG_LEN_DDISP+BC_LOOP] = f_loop;
91 disp[GG_LEN_DDISP+BC_FUNCF] = f_funcf; 100
92 disp[GG_LEN_DDISP+BC_FUNCV] = f_funcv; 101 /* Set dynamic instruction dispatch. */
93 if ((oldmode & 6) != (mode & 6)) { /* Need to change whole table? */ 102 if ((oldmode ^ mode) & (DISPMODE_REC|DISPMODE_INS)) {
94 if ((mode & 6) == 0) { /* No hooks and no recording? */ 103 /* Need to update the whole table. */
104 if (!(mode & (DISPMODE_REC|DISPMODE_INS))) { /* No ins dispatch? */
95 /* Copy static dispatch table to dynamic dispatch table. */ 105 /* Copy static dispatch table to dynamic dispatch table. */
96 memcpy(&disp[0], &disp[GG_LEN_DDISP], GG_LEN_SDISP*sizeof(ASMFunction)); 106 memcpy(&disp[0], &disp[GG_LEN_DDISP], GG_LEN_SDISP*sizeof(ASMFunction));
97 } else { 107 } else {
98 /* The recording dispatch also checks for hooks. */ 108 /* The recording dispatch also checks for hooks. */
99 ASMFunction f = (mode & 6) == 6 ? lj_vm_record : lj_vm_hook; 109 ASMFunction f = (mode & DISPMODE_REC) ? lj_vm_record : lj_vm_hook;
100 uint32_t i; 110 uint32_t i;
101 for (i = 0; i < BC_FUNCF; i++) 111 for (i = 0; i < GG_LEN_SDISP; i++)
102 disp[i] = f; 112 disp[i] = f;
103 /* NYI: call hooks for function headers. */
104 memcpy(&disp[BC_FUNCF], &disp[GG_LEN_DDISP+BC_FUNCF],
105 (GG_LEN_SDISP-BC_FUNCF)*sizeof(ASMFunction));
106 } 113 }
107 } else if ((mode & 6) == 0) { /* Set dynamic counting ins. */ 114 } else if (!(mode & (DISPMODE_REC|DISPMODE_INS))) {
115 /* Otherwise only set dynamic counting ins. */
108 disp[BC_FORL] = f_forl; 116 disp[BC_FORL] = f_forl;
109 disp[BC_ITERL] = f_iterl; 117 disp[BC_ITERL] = f_iterl;
110 disp[BC_LOOP] = f_loop; 118 disp[BC_LOOP] = f_loop;
119 }
120
121 /* Set dynamic call dispatch. */
122 if ((oldmode ^ mode) & DISPMODE_CALL) { /* Update the whole table? */
123 uint32_t i;
124 if ((mode & 8) == 0) { /* No call hooks? */
125 for (i = GG_LEN_SDISP; i < GG_LEN_DDISP; i++)
126 disp[i] = makeasmfunc(lj_bc_ofs[i]);
127 } else {
128 for (i = GG_LEN_SDISP; i < GG_LEN_DDISP; i++)
129 disp[i] = lj_vm_callhook;
130 }
131 }
132 if (!(mode & DISPMODE_CALL)) { /* Overwrite dynamic counting ins. */
111 disp[BC_FUNCF] = f_funcf; 133 disp[BC_FUNCF] = f_funcf;
112 disp[BC_FUNCV] = f_funcv; 134 disp[BC_FUNCV] = f_funcv;
113 } 135 }
136
114#if LJ_HASJIT 137#if LJ_HASJIT
115 if ((mode & 1) && !(oldmode & 1)) /* JIT off to on transition. */ 138 /* Reset hotcounts for JIT off to on transition. */
139 if ((mode & DISPMODE_JIT) && !(oldmode & DISPMODE_JIT))
116 lj_dispatch_init_hotcount(g); 140 lj_dispatch_init_hotcount(g);
117#endif 141#endif
118 } 142 }
@@ -279,7 +303,7 @@ static void callhook(lua_State *L, int event, BCLine line)
279 } 303 }
280} 304}
281 305
282/* -- Instruction dispatch callbacks -------------------------------------- */ 306/* -- Dispatch callbacks -------------------------------------------------- */
283 307
284/* Calculate number of used stack slots in the current frame. */ 308/* Calculate number of used stack slots in the current frame. */
285static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres) 309static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres)
@@ -297,7 +321,7 @@ static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres)
297 } 321 }
298} 322}
299 323
300/* Instruction dispatch callback for instr/line hooks or when recording. */ 324/* Instruction dispatch. Used by instr/line hooks or when recording. */
301void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc) 325void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc)
302{ 326{
303 GCfunc *fn = curr_func(L); 327 GCfunc *fn = curr_func(L);
@@ -337,3 +361,48 @@ void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc)
337 } 361 }
338} 362}
339 363
364/* Initialize call. Ensure stack space and clear missing parameters. */
365static void call_init(lua_State *L, GCfunc *fn)
366{
367 if (isluafunc(fn)) {
368 MSize numparams = funcproto(fn)->numparams;
369 TValue *o;
370 lj_state_checkstack(L, numparams);
371 for (o = L->base + numparams; L->top < o; L->top++)
372 setnilV(L->top); /* Clear missing parameters. */
373 } else {
374 lj_state_checkstack(L, LUA_MINSTACK);
375 }
376}
377
378/* Call dispatch. Used by call hooks and hot calls. */
379ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns *pc)
380{
381 GCfunc *fn = curr_func(L);
382 BCOp op;
383 global_State *g = G(L);
384#if LJ_HASJIT
385 jit_State *J = G2J(g);
386#endif
387 call_init(L, fn);
388#if LJ_HASJIT
389 if (J->L) { /* Marker for hot call. */
390 lj_trace_hot(J, pc);
391 goto out;
392 }
393#endif
394 if ((g->hookmask & LUA_MASKCALL))
395 callhook(L, LUA_HOOKCALL, -1);
396#if LJ_HASJIT
397out:
398#endif
399 op = bc_op(pc[-1]); /* Get FUNC* op. */
400#if LJ_HASJIT
401 /* Use the non-hotcounting variants if JIT is off or while recording. */
402 if ((!(J->flags & JIT_F_ON) || J->state != LJ_TRACE_IDLE) &&
403 (op == BC_FUNCF || op == BC_FUNCV))
404 op = (BCOp)((int)op+(int)BC_IFUNCF-(int)BC_FUNCF);
405#endif
406 return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */
407}
408