diff options
Diffstat (limited to 'src/lj_dispatch.c')
-rw-r--r-- | src/lj_dispatch.c | 85 |
1 files changed, 74 insertions, 11 deletions
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c index 644e9028..8553438c 100644 --- a/src/lj_dispatch.c +++ b/src/lj_dispatch.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include "lj_obj.h" | 9 | #include "lj_obj.h" |
10 | #include "lj_err.h" | 10 | #include "lj_err.h" |
11 | #include "lj_buf.h" | ||
11 | #include "lj_func.h" | 12 | #include "lj_func.h" |
12 | #include "lj_str.h" | 13 | #include "lj_str.h" |
13 | #include "lj_tab.h" | 14 | #include "lj_tab.h" |
@@ -17,6 +18,7 @@ | |||
17 | #include "lj_frame.h" | 18 | #include "lj_frame.h" |
18 | #include "lj_bc.h" | 19 | #include "lj_bc.h" |
19 | #include "lj_ff.h" | 20 | #include "lj_ff.h" |
21 | #include "lj_strfmt.h" | ||
20 | #if LJ_HASJIT | 22 | #if LJ_HASJIT |
21 | #include "lj_jit.h" | 23 | #include "lj_jit.h" |
22 | #endif | 24 | #endif |
@@ -25,6 +27,9 @@ | |||
25 | #endif | 27 | #endif |
26 | #include "lj_trace.h" | 28 | #include "lj_trace.h" |
27 | #include "lj_dispatch.h" | 29 | #include "lj_dispatch.h" |
30 | #if LJ_HASPROFILE | ||
31 | #include "lj_profile.h" | ||
32 | #endif | ||
28 | #include "lj_vm.h" | 33 | #include "lj_vm.h" |
29 | #include "luajit.h" | 34 | #include "luajit.h" |
30 | 35 | ||
@@ -37,6 +42,12 @@ LJ_STATIC_ASSERT(GG_NUM_ASMFF == FF_NUM_ASMFUNC); | |||
37 | #include <math.h> | 42 | #include <math.h> |
38 | LJ_FUNCA_NORET void LJ_FASTCALL lj_ffh_coroutine_wrap_err(lua_State *L, | 43 | LJ_FUNCA_NORET void LJ_FASTCALL lj_ffh_coroutine_wrap_err(lua_State *L, |
39 | lua_State *co); | 44 | lua_State *co); |
45 | #if !LJ_HASJIT | ||
46 | #define lj_dispatch_stitch lj_dispatch_ins | ||
47 | #endif | ||
48 | #if !LJ_HASPROFILE | ||
49 | #define lj_dispatch_profile lj_dispatch_ins | ||
50 | #endif | ||
40 | 51 | ||
41 | #define GOTFUNC(name) (ASMFunction)name, | 52 | #define GOTFUNC(name) (ASMFunction)name, |
42 | static const ASMFunction dispatch_got[] = { | 53 | static const ASMFunction dispatch_got[] = { |
@@ -64,7 +75,7 @@ void lj_dispatch_init(GG_State *GG) | |||
64 | for (i = 0; i < GG_NUM_ASMFF; i++) | 75 | for (i = 0; i < GG_NUM_ASMFF; i++) |
65 | GG->bcff[i] = BCINS_AD(BC__MAX+i, 0, 0); | 76 | GG->bcff[i] = BCINS_AD(BC__MAX+i, 0, 0); |
66 | #if LJ_TARGET_MIPS | 77 | #if LJ_TARGET_MIPS |
67 | memcpy(GG->got, dispatch_got, LJ_GOT__MAX*4); | 78 | memcpy(GG->got, dispatch_got, LJ_GOT__MAX*sizeof(ASMFunction *)); |
68 | #endif | 79 | #endif |
69 | } | 80 | } |
70 | 81 | ||
@@ -82,11 +93,12 @@ void lj_dispatch_init_hotcount(global_State *g) | |||
82 | #endif | 93 | #endif |
83 | 94 | ||
84 | /* Internal dispatch mode bits. */ | 95 | /* Internal dispatch mode bits. */ |
85 | #define DISPMODE_JIT 0x01 /* JIT compiler on. */ | 96 | #define DISPMODE_CALL 0x01 /* Override call dispatch. */ |
86 | #define DISPMODE_REC 0x02 /* Recording active. */ | 97 | #define DISPMODE_RET 0x02 /* Override return dispatch. */ |
87 | #define DISPMODE_INS 0x04 /* Override instruction dispatch. */ | 98 | #define DISPMODE_INS 0x04 /* Override instruction dispatch. */ |
88 | #define DISPMODE_CALL 0x08 /* Override call dispatch. */ | 99 | #define DISPMODE_JIT 0x10 /* JIT compiler on. */ |
89 | #define DISPMODE_RET 0x10 /* Override return dispatch. */ | 100 | #define DISPMODE_REC 0x20 /* Recording active. */ |
101 | #define DISPMODE_PROF 0x40 /* Profiling active. */ | ||
90 | 102 | ||
91 | /* Update dispatch table depending on various flags. */ | 103 | /* Update dispatch table depending on various flags. */ |
92 | void lj_dispatch_update(global_State *g) | 104 | void lj_dispatch_update(global_State *g) |
@@ -98,6 +110,9 @@ void lj_dispatch_update(global_State *g) | |||
98 | mode |= G2J(g)->state != LJ_TRACE_IDLE ? | 110 | mode |= G2J(g)->state != LJ_TRACE_IDLE ? |
99 | (DISPMODE_REC|DISPMODE_INS|DISPMODE_CALL) : 0; | 111 | (DISPMODE_REC|DISPMODE_INS|DISPMODE_CALL) : 0; |
100 | #endif | 112 | #endif |
113 | #if LJ_HASPROFILE | ||
114 | mode |= (g->hookmask & HOOK_PROFILE) ? (DISPMODE_PROF|DISPMODE_INS) : 0; | ||
115 | #endif | ||
101 | mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0; | 116 | mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0; |
102 | mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0; | 117 | mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0; |
103 | mode |= (g->hookmask & LUA_MASKRET) ? DISPMODE_RET : 0; | 118 | mode |= (g->hookmask & LUA_MASKRET) ? DISPMODE_RET : 0; |
@@ -126,9 +141,9 @@ void lj_dispatch_update(global_State *g) | |||
126 | disp[GG_LEN_DDISP+BC_LOOP] = f_loop; | 141 | disp[GG_LEN_DDISP+BC_LOOP] = f_loop; |
127 | 142 | ||
128 | /* Set dynamic instruction dispatch. */ | 143 | /* Set dynamic instruction dispatch. */ |
129 | if ((oldmode ^ mode) & (DISPMODE_REC|DISPMODE_INS)) { | 144 | if ((oldmode ^ mode) & (DISPMODE_PROF|DISPMODE_REC|DISPMODE_INS)) { |
130 | /* Need to update the whole table. */ | 145 | /* Need to update the whole table. */ |
131 | if (!(mode & (DISPMODE_REC|DISPMODE_INS))) { /* No ins dispatch? */ | 146 | if (!(mode & DISPMODE_INS)) { /* No ins dispatch? */ |
132 | /* Copy static dispatch table to dynamic dispatch table. */ | 147 | /* Copy static dispatch table to dynamic dispatch table. */ |
133 | memcpy(&disp[0], &disp[GG_LEN_DDISP], GG_LEN_SDISP*sizeof(ASMFunction)); | 148 | memcpy(&disp[0], &disp[GG_LEN_DDISP], GG_LEN_SDISP*sizeof(ASMFunction)); |
134 | /* Overwrite with dynamic return dispatch. */ | 149 | /* Overwrite with dynamic return dispatch. */ |
@@ -140,12 +155,13 @@ void lj_dispatch_update(global_State *g) | |||
140 | } | 155 | } |
141 | } else { | 156 | } else { |
142 | /* The recording dispatch also checks for hooks. */ | 157 | /* The recording dispatch also checks for hooks. */ |
143 | ASMFunction f = (mode & DISPMODE_REC) ? lj_vm_record : lj_vm_inshook; | 158 | ASMFunction f = (mode & DISPMODE_PROF) ? lj_vm_profhook : |
159 | (mode & DISPMODE_REC) ? lj_vm_record : lj_vm_inshook; | ||
144 | uint32_t i; | 160 | uint32_t i; |
145 | for (i = 0; i < GG_LEN_SDISP; i++) | 161 | for (i = 0; i < GG_LEN_SDISP; i++) |
146 | disp[i] = f; | 162 | disp[i] = f; |
147 | } | 163 | } |
148 | } else if (!(mode & (DISPMODE_REC|DISPMODE_INS))) { | 164 | } else if (!(mode & DISPMODE_INS)) { |
149 | /* Otherwise set dynamic counting ins. */ | 165 | /* Otherwise set dynamic counting ins. */ |
150 | disp[BC_FORL] = f_forl; | 166 | disp[BC_FORL] = f_forl; |
151 | disp[BC_ITERL] = f_iterl; | 167 | disp[BC_ITERL] = f_iterl; |
@@ -251,7 +267,7 @@ int luaJIT_setmode(lua_State *L, int idx, int mode) | |||
251 | case LUAJIT_MODE_FUNC: | 267 | case LUAJIT_MODE_FUNC: |
252 | case LUAJIT_MODE_ALLFUNC: | 268 | case LUAJIT_MODE_ALLFUNC: |
253 | case LUAJIT_MODE_ALLSUBFUNC: { | 269 | case LUAJIT_MODE_ALLSUBFUNC: { |
254 | cTValue *tv = idx == 0 ? frame_prev(L->base-1) : | 270 | cTValue *tv = idx == 0 ? frame_prev(L->base-1)-LJ_FR2 : |
255 | idx > 0 ? L->base + (idx-1) : L->top + idx; | 271 | idx > 0 ? L->base + (idx-1) : L->top + idx; |
256 | GCproto *pt; | 272 | GCproto *pt; |
257 | if ((idx == 0 || tvisfunc(tv)) && isluafunc(&gcval(tv)->fn)) | 273 | if ((idx == 0 || tvisfunc(tv)) && isluafunc(&gcval(tv)->fn)) |
@@ -352,10 +368,19 @@ static void callhook(lua_State *L, int event, BCLine line) | |||
352 | /* Top frame, nextframe = NULL. */ | 368 | /* Top frame, nextframe = NULL. */ |
353 | ar.i_ci = (int)((L->base-1) - tvref(L->stack)); | 369 | ar.i_ci = (int)((L->base-1) - tvref(L->stack)); |
354 | lj_state_checkstack(L, 1+LUA_MINSTACK); | 370 | lj_state_checkstack(L, 1+LUA_MINSTACK); |
371 | #if LJ_HASPROFILE && !LJ_PROFILE_SIGPROF | ||
372 | lj_profile_hook_enter(g); | ||
373 | #else | ||
355 | hook_enter(g); | 374 | hook_enter(g); |
375 | #endif | ||
356 | hookf(L, &ar); | 376 | hookf(L, &ar); |
357 | lua_assert(hook_active(g)); | 377 | lua_assert(hook_active(g)); |
378 | setgcref(g->cur_L, obj2gco(L)); | ||
379 | #if LJ_HASPROFILE && !LJ_PROFILE_SIGPROF | ||
380 | lj_profile_hook_leave(g); | ||
381 | #else | ||
358 | hook_leave(g); | 382 | hook_leave(g); |
383 | #endif | ||
359 | } | 384 | } |
360 | } | 385 | } |
361 | 386 | ||
@@ -368,7 +393,7 @@ static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres) | |||
368 | if (bc_op(ins) == BC_UCLO) | 393 | if (bc_op(ins) == BC_UCLO) |
369 | ins = pc[bc_j(ins)]; | 394 | ins = pc[bc_j(ins)]; |
370 | switch (bc_op(ins)) { | 395 | switch (bc_op(ins)) { |
371 | case BC_CALLM: case BC_CALLMT: return bc_a(ins) + bc_c(ins) + nres-1+1; | 396 | case BC_CALLM: case BC_CALLMT: return bc_a(ins) + bc_c(ins) + nres-1+1+LJ_FR2; |
372 | case BC_RETM: return bc_a(ins) + bc_d(ins) + nres-1; | 397 | case BC_RETM: return bc_a(ins) + bc_d(ins) + nres-1; |
373 | case BC_TSETM: return bc_a(ins) + nres-1; | 398 | case BC_TSETM: return bc_a(ins) + nres-1; |
374 | default: return pt->framesize; | 399 | default: return pt->framesize; |
@@ -492,3 +517,41 @@ out: | |||
492 | return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */ | 517 | return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */ |
493 | } | 518 | } |
494 | 519 | ||
520 | #if LJ_HASJIT | ||
521 | /* Stitch a new trace. */ | ||
522 | void LJ_FASTCALL lj_dispatch_stitch(jit_State *J, const BCIns *pc) | ||
523 | { | ||
524 | ERRNO_SAVE | ||
525 | lua_State *L = J->L; | ||
526 | void *cf = cframe_raw(L->cframe); | ||
527 | const BCIns *oldpc = cframe_pc(cf); | ||
528 | setcframe_pc(cf, pc); | ||
529 | /* Before dispatch, have to bias PC by 1. */ | ||
530 | L->top = L->base + cur_topslot(curr_proto(L), pc+1, cframe_multres_n(cf)); | ||
531 | lj_trace_stitch(J, pc-1); /* Point to the CALL instruction. */ | ||
532 | setcframe_pc(cf, oldpc); | ||
533 | ERRNO_RESTORE | ||
534 | } | ||
535 | #endif | ||
536 | |||
537 | #if LJ_HASPROFILE | ||
538 | /* Profile dispatch. */ | ||
539 | void LJ_FASTCALL lj_dispatch_profile(lua_State *L, const BCIns *pc) | ||
540 | { | ||
541 | ERRNO_SAVE | ||
542 | GCfunc *fn = curr_func(L); | ||
543 | GCproto *pt = funcproto(fn); | ||
544 | void *cf = cframe_raw(L->cframe); | ||
545 | const BCIns *oldpc = cframe_pc(cf); | ||
546 | global_State *g; | ||
547 | setcframe_pc(cf, pc); | ||
548 | L->top = L->base + cur_topslot(pt, pc, cframe_multres_n(cf)); | ||
549 | lj_profile_interpreter(L); | ||
550 | setcframe_pc(cf, oldpc); | ||
551 | g = G(L); | ||
552 | setgcref(g->cur_L, obj2gco(L)); | ||
553 | setvmstate(g, INTERP); | ||
554 | ERRNO_RESTORE | ||
555 | } | ||
556 | #endif | ||
557 | |||