diff options
Diffstat (limited to 'src/lj_dispatch.c')
-rw-r--r-- | src/lj_dispatch.c | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c index d76dda41..01bc4239 100644 --- a/src/lj_dispatch.c +++ b/src/lj_dispatch.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #endif | 27 | #endif |
28 | #include "lj_trace.h" | 28 | #include "lj_trace.h" |
29 | #include "lj_dispatch.h" | 29 | #include "lj_dispatch.h" |
30 | #if LJ_HASPROFILE | ||
31 | #include "lj_profile.h" | ||
32 | #endif | ||
30 | #include "lj_vm.h" | 33 | #include "lj_vm.h" |
31 | #include "luajit.h" | 34 | #include "luajit.h" |
32 | 35 | ||
@@ -84,11 +87,12 @@ void lj_dispatch_init_hotcount(global_State *g) | |||
84 | #endif | 87 | #endif |
85 | 88 | ||
86 | /* Internal dispatch mode bits. */ | 89 | /* Internal dispatch mode bits. */ |
87 | #define DISPMODE_JIT 0x01 /* JIT compiler on. */ | 90 | #define DISPMODE_CALL 0x01 /* Override call dispatch. */ |
88 | #define DISPMODE_REC 0x02 /* Recording active. */ | 91 | #define DISPMODE_RET 0x02 /* Override return dispatch. */ |
89 | #define DISPMODE_INS 0x04 /* Override instruction dispatch. */ | 92 | #define DISPMODE_INS 0x04 /* Override instruction dispatch. */ |
90 | #define DISPMODE_CALL 0x08 /* Override call dispatch. */ | 93 | #define DISPMODE_JIT 0x10 /* JIT compiler on. */ |
91 | #define DISPMODE_RET 0x10 /* Override return dispatch. */ | 94 | #define DISPMODE_REC 0x20 /* Recording active. */ |
95 | #define DISPMODE_PROF 0x40 /* Profiling active. */ | ||
92 | 96 | ||
93 | /* Update dispatch table depending on various flags. */ | 97 | /* Update dispatch table depending on various flags. */ |
94 | void lj_dispatch_update(global_State *g) | 98 | void lj_dispatch_update(global_State *g) |
@@ -100,6 +104,9 @@ void lj_dispatch_update(global_State *g) | |||
100 | mode |= G2J(g)->state != LJ_TRACE_IDLE ? | 104 | mode |= G2J(g)->state != LJ_TRACE_IDLE ? |
101 | (DISPMODE_REC|DISPMODE_INS|DISPMODE_CALL) : 0; | 105 | (DISPMODE_REC|DISPMODE_INS|DISPMODE_CALL) : 0; |
102 | #endif | 106 | #endif |
107 | #if LJ_HASPROFILE | ||
108 | mode |= (g->hookmask & HOOK_PROFILE) ? (DISPMODE_PROF|DISPMODE_INS) : 0; | ||
109 | #endif | ||
103 | mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0; | 110 | mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0; |
104 | mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0; | 111 | mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0; |
105 | mode |= (g->hookmask & LUA_MASKRET) ? DISPMODE_RET : 0; | 112 | mode |= (g->hookmask & LUA_MASKRET) ? DISPMODE_RET : 0; |
@@ -128,9 +135,9 @@ void lj_dispatch_update(global_State *g) | |||
128 | disp[GG_LEN_DDISP+BC_LOOP] = f_loop; | 135 | disp[GG_LEN_DDISP+BC_LOOP] = f_loop; |
129 | 136 | ||
130 | /* Set dynamic instruction dispatch. */ | 137 | /* Set dynamic instruction dispatch. */ |
131 | if ((oldmode ^ mode) & (DISPMODE_REC|DISPMODE_INS)) { | 138 | if ((oldmode ^ mode) & (DISPMODE_PROF|DISPMODE_REC|DISPMODE_INS)) { |
132 | /* Need to update the whole table. */ | 139 | /* Need to update the whole table. */ |
133 | if (!(mode & (DISPMODE_REC|DISPMODE_INS))) { /* No ins dispatch? */ | 140 | if (!(mode & DISPMODE_INS)) { /* No ins dispatch? */ |
134 | /* Copy static dispatch table to dynamic dispatch table. */ | 141 | /* Copy static dispatch table to dynamic dispatch table. */ |
135 | memcpy(&disp[0], &disp[GG_LEN_DDISP], GG_LEN_SDISP*sizeof(ASMFunction)); | 142 | memcpy(&disp[0], &disp[GG_LEN_DDISP], GG_LEN_SDISP*sizeof(ASMFunction)); |
136 | /* Overwrite with dynamic return dispatch. */ | 143 | /* Overwrite with dynamic return dispatch. */ |
@@ -142,12 +149,13 @@ void lj_dispatch_update(global_State *g) | |||
142 | } | 149 | } |
143 | } else { | 150 | } else { |
144 | /* The recording dispatch also checks for hooks. */ | 151 | /* The recording dispatch also checks for hooks. */ |
145 | ASMFunction f = (mode & DISPMODE_REC) ? lj_vm_record : lj_vm_inshook; | 152 | ASMFunction f = (mode & DISPMODE_PROF) ? lj_vm_profhook : |
153 | (mode & DISPMODE_REC) ? lj_vm_record : lj_vm_inshook; | ||
146 | uint32_t i; | 154 | uint32_t i; |
147 | for (i = 0; i < GG_LEN_SDISP; i++) | 155 | for (i = 0; i < GG_LEN_SDISP; i++) |
148 | disp[i] = f; | 156 | disp[i] = f; |
149 | } | 157 | } |
150 | } else if (!(mode & (DISPMODE_REC|DISPMODE_INS))) { | 158 | } else if (!(mode & DISPMODE_INS)) { |
151 | /* Otherwise set dynamic counting ins. */ | 159 | /* Otherwise set dynamic counting ins. */ |
152 | disp[BC_FORL] = f_forl; | 160 | disp[BC_FORL] = f_forl; |
153 | disp[BC_ITERL] = f_iterl; | 161 | disp[BC_ITERL] = f_iterl; |
@@ -495,3 +503,34 @@ out: | |||
495 | return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */ | 503 | return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */ |
496 | } | 504 | } |
497 | 505 | ||
506 | #if LJ_HASPROFILE | ||
507 | /* Profile dispatch. */ | ||
508 | void LJ_FASTCALL lj_dispatch_profile(lua_State *L, const BCIns *pc) | ||
509 | { | ||
510 | ERRNO_SAVE | ||
511 | global_State *g = G(L); | ||
512 | uint8_t mask = g->hookmask; | ||
513 | g->hookmask = (mask & ~HOOK_PROFILE); | ||
514 | lj_dispatch_update(g); | ||
515 | if (!(mask & HOOK_VMEVENT)) { | ||
516 | GCfunc *fn = curr_func(L); | ||
517 | GCproto *pt = funcproto(fn); | ||
518 | void *cf = cframe_raw(L->cframe); | ||
519 | const BCIns *oldpc = cframe_pc(cf); | ||
520 | uint8_t oldh = hook_save(g); | ||
521 | BCReg slots; | ||
522 | hook_vmevent(g); | ||
523 | setcframe_pc(cf, pc); | ||
524 | slots = cur_topslot(pt, pc, cframe_multres_n(cf)); | ||
525 | L->top = L->base + slots; /* Fix top. */ | ||
526 | lj_profile_interpreter(L); | ||
527 | setgcref(g->cur_L, obj2gco(L)); | ||
528 | setcframe_pc(cf, oldpc); | ||
529 | hook_restore(g, oldh); | ||
530 | lj_trace_abort(g); | ||
531 | setvmstate(g, INTERP); | ||
532 | } | ||
533 | ERRNO_RESTORE | ||
534 | } | ||
535 | #endif | ||
536 | |||