diff options
Diffstat (limited to 'src/lj_dispatch.c')
| -rw-r--r-- | src/lj_dispatch.c | 117 |
1 files changed, 92 insertions, 25 deletions
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c index 99d7f089..636fb033 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[] = { |
| @@ -57,6 +68,8 @@ void lj_dispatch_init(GG_State *GG) | |||
| 57 | /* The JIT engine is off by default. luaopen_jit() turns it on. */ | 68 | /* The JIT engine is off by default. luaopen_jit() turns it on. */ |
| 58 | disp[BC_FORL] = disp[BC_IFORL]; | 69 | disp[BC_FORL] = disp[BC_IFORL]; |
| 59 | disp[BC_ITERL] = disp[BC_IITERL]; | 70 | disp[BC_ITERL] = disp[BC_IITERL]; |
| 71 | /* Workaround for stable v2.1 bytecode. TODO: Replace with BC_IITERN. */ | ||
| 72 | disp[BC_ITERN] = &lj_vm_IITERN; | ||
| 60 | disp[BC_LOOP] = disp[BC_ILOOP]; | 73 | disp[BC_LOOP] = disp[BC_ILOOP]; |
| 61 | disp[BC_FUNCF] = disp[BC_IFUNCF]; | 74 | disp[BC_FUNCF] = disp[BC_IFUNCF]; |
| 62 | disp[BC_FUNCV] = disp[BC_IFUNCV]; | 75 | disp[BC_FUNCV] = disp[BC_IFUNCV]; |
| @@ -64,7 +77,7 @@ void lj_dispatch_init(GG_State *GG) | |||
| 64 | for (i = 0; i < GG_NUM_ASMFF; i++) | 77 | for (i = 0; i < GG_NUM_ASMFF; i++) |
| 65 | GG->bcff[i] = BCINS_AD(BC__MAX+i, 0, 0); | 78 | GG->bcff[i] = BCINS_AD(BC__MAX+i, 0, 0); |
| 66 | #if LJ_TARGET_MIPS | 79 | #if LJ_TARGET_MIPS |
| 67 | memcpy(GG->got, dispatch_got, LJ_GOT__MAX*4); | 80 | memcpy(GG->got, dispatch_got, LJ_GOT__MAX*sizeof(ASMFunction *)); |
| 68 | #endif | 81 | #endif |
| 69 | } | 82 | } |
| 70 | 83 | ||
| @@ -82,11 +95,12 @@ void lj_dispatch_init_hotcount(global_State *g) | |||
| 82 | #endif | 95 | #endif |
| 83 | 96 | ||
| 84 | /* Internal dispatch mode bits. */ | 97 | /* Internal dispatch mode bits. */ |
| 85 | #define DISPMODE_JIT 0x01 /* JIT compiler on. */ | 98 | #define DISPMODE_CALL 0x01 /* Override call dispatch. */ |
| 86 | #define DISPMODE_REC 0x02 /* Recording active. */ | 99 | #define DISPMODE_RET 0x02 /* Override return dispatch. */ |
| 87 | #define DISPMODE_INS 0x04 /* Override instruction dispatch. */ | 100 | #define DISPMODE_INS 0x04 /* Override instruction dispatch. */ |
| 88 | #define DISPMODE_CALL 0x08 /* Override call dispatch. */ | 101 | #define DISPMODE_JIT 0x10 /* JIT compiler on. */ |
| 89 | #define DISPMODE_RET 0x10 /* Override return dispatch. */ | 102 | #define DISPMODE_REC 0x20 /* Recording active. */ |
| 103 | #define DISPMODE_PROF 0x40 /* Profiling active. */ | ||
| 90 | 104 | ||
| 91 | /* Update dispatch table depending on various flags. */ | 105 | /* Update dispatch table depending on various flags. */ |
| 92 | void lj_dispatch_update(global_State *g) | 106 | void lj_dispatch_update(global_State *g) |
| @@ -98,24 +112,29 @@ void lj_dispatch_update(global_State *g) | |||
| 98 | mode |= G2J(g)->state != LJ_TRACE_IDLE ? | 112 | mode |= G2J(g)->state != LJ_TRACE_IDLE ? |
| 99 | (DISPMODE_REC|DISPMODE_INS|DISPMODE_CALL) : 0; | 113 | (DISPMODE_REC|DISPMODE_INS|DISPMODE_CALL) : 0; |
| 100 | #endif | 114 | #endif |
| 115 | #if LJ_HASPROFILE | ||
| 116 | mode |= (g->hookmask & HOOK_PROFILE) ? (DISPMODE_PROF|DISPMODE_INS) : 0; | ||
| 117 | #endif | ||
| 101 | mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0; | 118 | mode |= (g->hookmask & (LUA_MASKLINE|LUA_MASKCOUNT)) ? DISPMODE_INS : 0; |
| 102 | mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0; | 119 | mode |= (g->hookmask & LUA_MASKCALL) ? DISPMODE_CALL : 0; |
| 103 | mode |= (g->hookmask & LUA_MASKRET) ? DISPMODE_RET : 0; | 120 | mode |= (g->hookmask & LUA_MASKRET) ? DISPMODE_RET : 0; |
| 104 | if (oldmode != mode) { /* Mode changed? */ | 121 | if (oldmode != mode) { /* Mode changed? */ |
| 105 | ASMFunction *disp = G2GG(g)->dispatch; | 122 | ASMFunction *disp = G2GG(g)->dispatch; |
| 106 | ASMFunction f_forl, f_iterl, f_loop, f_funcf, f_funcv; | 123 | ASMFunction f_forl, f_iterl, f_itern, f_loop, f_funcf, f_funcv; |
| 107 | g->dispatchmode = mode; | 124 | g->dispatchmode = mode; |
| 108 | 125 | ||
| 109 | /* Hotcount if JIT is on, but not while recording. */ | 126 | /* Hotcount if JIT is on, but not while recording. */ |
| 110 | if ((mode & (DISPMODE_JIT|DISPMODE_REC)) == DISPMODE_JIT) { | 127 | if ((mode & (DISPMODE_JIT|DISPMODE_REC)) == DISPMODE_JIT) { |
| 111 | f_forl = makeasmfunc(lj_bc_ofs[BC_FORL]); | 128 | f_forl = makeasmfunc(lj_bc_ofs[BC_FORL]); |
| 112 | f_iterl = makeasmfunc(lj_bc_ofs[BC_ITERL]); | 129 | f_iterl = makeasmfunc(lj_bc_ofs[BC_ITERL]); |
| 130 | f_itern = makeasmfunc(lj_bc_ofs[BC_ITERN]); | ||
| 113 | f_loop = makeasmfunc(lj_bc_ofs[BC_LOOP]); | 131 | f_loop = makeasmfunc(lj_bc_ofs[BC_LOOP]); |
| 114 | f_funcf = makeasmfunc(lj_bc_ofs[BC_FUNCF]); | 132 | f_funcf = makeasmfunc(lj_bc_ofs[BC_FUNCF]); |
| 115 | f_funcv = makeasmfunc(lj_bc_ofs[BC_FUNCV]); | 133 | f_funcv = makeasmfunc(lj_bc_ofs[BC_FUNCV]); |
| 116 | } else { /* Otherwise use the non-hotcounting instructions. */ | 134 | } else { /* Otherwise use the non-hotcounting instructions. */ |
| 117 | f_forl = disp[GG_LEN_DDISP+BC_IFORL]; | 135 | f_forl = disp[GG_LEN_DDISP+BC_IFORL]; |
| 118 | f_iterl = disp[GG_LEN_DDISP+BC_IITERL]; | 136 | f_iterl = disp[GG_LEN_DDISP+BC_IITERL]; |
| 137 | f_itern = &lj_vm_IITERN; | ||
| 119 | f_loop = disp[GG_LEN_DDISP+BC_ILOOP]; | 138 | f_loop = disp[GG_LEN_DDISP+BC_ILOOP]; |
| 120 | f_funcf = makeasmfunc(lj_bc_ofs[BC_IFUNCF]); | 139 | f_funcf = makeasmfunc(lj_bc_ofs[BC_IFUNCF]); |
| 121 | f_funcv = makeasmfunc(lj_bc_ofs[BC_IFUNCV]); | 140 | f_funcv = makeasmfunc(lj_bc_ofs[BC_IFUNCV]); |
| @@ -123,12 +142,13 @@ void lj_dispatch_update(global_State *g) | |||
| 123 | /* Init static counting instruction dispatch first (may be copied below). */ | 142 | /* Init static counting instruction dispatch first (may be copied below). */ |
| 124 | disp[GG_LEN_DDISP+BC_FORL] = f_forl; | 143 | disp[GG_LEN_DDISP+BC_FORL] = f_forl; |
| 125 | disp[GG_LEN_DDISP+BC_ITERL] = f_iterl; | 144 | disp[GG_LEN_DDISP+BC_ITERL] = f_iterl; |
| 145 | disp[GG_LEN_DDISP+BC_ITERN] = f_itern; | ||
| 126 | disp[GG_LEN_DDISP+BC_LOOP] = f_loop; | 146 | disp[GG_LEN_DDISP+BC_LOOP] = f_loop; |
| 127 | 147 | ||
| 128 | /* Set dynamic instruction dispatch. */ | 148 | /* Set dynamic instruction dispatch. */ |
| 129 | if ((oldmode ^ mode) & (DISPMODE_REC|DISPMODE_INS)) { | 149 | if ((oldmode ^ mode) & (DISPMODE_PROF|DISPMODE_REC|DISPMODE_INS)) { |
| 130 | /* Need to update the whole table. */ | 150 | /* Need to update the whole table. */ |
| 131 | if (!(mode & (DISPMODE_REC|DISPMODE_INS))) { /* No ins dispatch? */ | 151 | if (!(mode & DISPMODE_INS)) { /* No ins dispatch? */ |
| 132 | /* Copy static dispatch table to dynamic dispatch table. */ | 152 | /* Copy static dispatch table to dynamic dispatch table. */ |
| 133 | memcpy(&disp[0], &disp[GG_LEN_DDISP], GG_LEN_SDISP*sizeof(ASMFunction)); | 153 | memcpy(&disp[0], &disp[GG_LEN_DDISP], GG_LEN_SDISP*sizeof(ASMFunction)); |
| 134 | /* Overwrite with dynamic return dispatch. */ | 154 | /* Overwrite with dynamic return dispatch. */ |
| @@ -140,15 +160,17 @@ void lj_dispatch_update(global_State *g) | |||
| 140 | } | 160 | } |
| 141 | } else { | 161 | } else { |
| 142 | /* The recording dispatch also checks for hooks. */ | 162 | /* The recording dispatch also checks for hooks. */ |
| 143 | ASMFunction f = (mode & DISPMODE_REC) ? lj_vm_record : lj_vm_inshook; | 163 | ASMFunction f = (mode & DISPMODE_PROF) ? lj_vm_profhook : |
| 164 | (mode & DISPMODE_REC) ? lj_vm_record : lj_vm_inshook; | ||
| 144 | uint32_t i; | 165 | uint32_t i; |
| 145 | for (i = 0; i < GG_LEN_SDISP; i++) | 166 | for (i = 0; i < GG_LEN_SDISP; i++) |
| 146 | disp[i] = f; | 167 | disp[i] = f; |
| 147 | } | 168 | } |
| 148 | } else if (!(mode & (DISPMODE_REC|DISPMODE_INS))) { | 169 | } else if (!(mode & DISPMODE_INS)) { |
| 149 | /* Otherwise set dynamic counting ins. */ | 170 | /* Otherwise set dynamic counting ins. */ |
| 150 | disp[BC_FORL] = f_forl; | 171 | disp[BC_FORL] = f_forl; |
| 151 | disp[BC_ITERL] = f_iterl; | 172 | disp[BC_ITERL] = f_iterl; |
| 173 | disp[BC_ITERN] = f_itern; | ||
| 152 | disp[BC_LOOP] = f_loop; | 174 | disp[BC_LOOP] = f_loop; |
| 153 | /* Set dynamic return dispatch. */ | 175 | /* Set dynamic return dispatch. */ |
| 154 | if ((mode & DISPMODE_RET)) { | 176 | if ((mode & DISPMODE_RET)) { |
| @@ -236,22 +258,15 @@ int luaJIT_setmode(lua_State *L, int idx, int mode) | |||
| 236 | } else { | 258 | } else { |
| 237 | if (!(mode & LUAJIT_MODE_ON)) | 259 | if (!(mode & LUAJIT_MODE_ON)) |
| 238 | G2J(g)->flags &= ~(uint32_t)JIT_F_ON; | 260 | G2J(g)->flags &= ~(uint32_t)JIT_F_ON; |
| 239 | #if LJ_TARGET_X86ORX64 | ||
| 240 | else if ((G2J(g)->flags & JIT_F_SSE2)) | ||
| 241 | G2J(g)->flags |= (uint32_t)JIT_F_ON; | ||
| 242 | else | ||
| 243 | return 0; /* Don't turn on JIT compiler without SSE2 support. */ | ||
| 244 | #else | ||
| 245 | else | 261 | else |
| 246 | G2J(g)->flags |= (uint32_t)JIT_F_ON; | 262 | G2J(g)->flags |= (uint32_t)JIT_F_ON; |
| 247 | #endif | ||
| 248 | lj_dispatch_update(g); | 263 | lj_dispatch_update(g); |
| 249 | } | 264 | } |
| 250 | break; | 265 | break; |
| 251 | case LUAJIT_MODE_FUNC: | 266 | case LUAJIT_MODE_FUNC: |
| 252 | case LUAJIT_MODE_ALLFUNC: | 267 | case LUAJIT_MODE_ALLFUNC: |
| 253 | case LUAJIT_MODE_ALLSUBFUNC: { | 268 | case LUAJIT_MODE_ALLSUBFUNC: { |
| 254 | cTValue *tv = idx == 0 ? frame_prev(L->base-1) : | 269 | cTValue *tv = idx == 0 ? frame_prev(L->base-1)-LJ_FR2 : |
| 255 | idx > 0 ? L->base + (idx-1) : L->top + idx; | 270 | idx > 0 ? L->base + (idx-1) : L->top + idx; |
| 256 | GCproto *pt; | 271 | GCproto *pt; |
| 257 | if ((idx == 0 || tvisfunc(tv)) && isluafunc(&gcval(tv)->fn)) | 272 | if ((idx == 0 || tvisfunc(tv)) && isluafunc(&gcval(tv)->fn)) |
| @@ -286,7 +301,7 @@ int luaJIT_setmode(lua_State *L, int idx, int mode) | |||
| 286 | if (idx != 0) { | 301 | if (idx != 0) { |
| 287 | cTValue *tv = idx > 0 ? L->base + (idx-1) : L->top + idx; | 302 | cTValue *tv = idx > 0 ? L->base + (idx-1) : L->top + idx; |
| 288 | if (tvislightud(tv)) | 303 | if (tvislightud(tv)) |
| 289 | g->wrapf = (lua_CFunction)lightudV(tv); | 304 | g->wrapf = (lua_CFunction)lightudV(g, tv); |
| 290 | else | 305 | else |
| 291 | return 0; /* Failed. */ | 306 | return 0; /* Failed. */ |
| 292 | } else { | 307 | } else { |
| @@ -352,10 +367,19 @@ static void callhook(lua_State *L, int event, BCLine line) | |||
| 352 | /* Top frame, nextframe = NULL. */ | 367 | /* Top frame, nextframe = NULL. */ |
| 353 | ar.i_ci = (int)((L->base-1) - tvref(L->stack)); | 368 | ar.i_ci = (int)((L->base-1) - tvref(L->stack)); |
| 354 | lj_state_checkstack(L, 1+LUA_MINSTACK); | 369 | lj_state_checkstack(L, 1+LUA_MINSTACK); |
| 370 | #if LJ_HASPROFILE && !LJ_PROFILE_SIGPROF | ||
| 371 | lj_profile_hook_enter(g); | ||
| 372 | #else | ||
| 355 | hook_enter(g); | 373 | hook_enter(g); |
| 374 | #endif | ||
| 356 | hookf(L, &ar); | 375 | hookf(L, &ar); |
| 357 | lua_assert(hook_active(g)); | 376 | lj_assertG(hook_active(g), "active hook flag removed"); |
| 377 | setgcref(g->cur_L, obj2gco(L)); | ||
| 378 | #if LJ_HASPROFILE && !LJ_PROFILE_SIGPROF | ||
| 379 | lj_profile_hook_leave(g); | ||
| 380 | #else | ||
| 358 | hook_leave(g); | 381 | hook_leave(g); |
| 382 | #endif | ||
| 359 | } | 383 | } |
| 360 | } | 384 | } |
| 361 | 385 | ||
| @@ -368,7 +392,7 @@ static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres) | |||
| 368 | if (bc_op(ins) == BC_UCLO) | 392 | if (bc_op(ins) == BC_UCLO) |
| 369 | ins = pc[bc_j(ins)]; | 393 | ins = pc[bc_j(ins)]; |
| 370 | switch (bc_op(ins)) { | 394 | switch (bc_op(ins)) { |
| 371 | case BC_CALLM: case BC_CALLMT: return bc_a(ins) + bc_c(ins) + nres-1+1; | 395 | 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; | 396 | case BC_RETM: return bc_a(ins) + bc_d(ins) + nres-1; |
| 373 | case BC_TSETM: return bc_a(ins) + nres-1; | 397 | case BC_TSETM: return bc_a(ins) + nres-1; |
| 374 | default: return pt->framesize; | 398 | default: return pt->framesize; |
| @@ -397,7 +421,8 @@ void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc) | |||
| 397 | #endif | 421 | #endif |
| 398 | J->L = L; | 422 | J->L = L; |
| 399 | lj_trace_ins(J, pc-1); /* The interpreter bytecode PC is offset by 1. */ | 423 | lj_trace_ins(J, pc-1); /* The interpreter bytecode PC is offset by 1. */ |
| 400 | lua_assert(L->top - L->base == delta); | 424 | lj_assertG(L->top - L->base == delta, |
| 425 | "unbalanced stack after tracing of instruction"); | ||
| 401 | } | 426 | } |
| 402 | } | 427 | } |
| 403 | #endif | 428 | #endif |
| @@ -428,7 +453,7 @@ static int call_init(lua_State *L, GCfunc *fn) | |||
| 428 | int numparams = pt->numparams; | 453 | int numparams = pt->numparams; |
| 429 | int gotparams = (int)(L->top - L->base); | 454 | int gotparams = (int)(L->top - L->base); |
| 430 | int need = pt->framesize; | 455 | int need = pt->framesize; |
| 431 | if ((pt->flags & PROTO_VARARG)) need += 1+gotparams; | 456 | if ((pt->flags & PROTO_VARARG)) need += 1+LJ_FR2+gotparams; |
| 432 | lj_state_checkstack(L, (MSize)need); | 457 | lj_state_checkstack(L, (MSize)need); |
| 433 | numparams -= gotparams; | 458 | numparams -= gotparams; |
| 434 | return numparams >= 0 ? numparams : 0; | 459 | return numparams >= 0 ? numparams : 0; |
| @@ -457,7 +482,8 @@ ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns *pc) | |||
| 457 | #endif | 482 | #endif |
| 458 | pc = (const BCIns *)((uintptr_t)pc & ~(uintptr_t)1); | 483 | pc = (const BCIns *)((uintptr_t)pc & ~(uintptr_t)1); |
| 459 | lj_trace_hot(J, pc); | 484 | lj_trace_hot(J, pc); |
| 460 | lua_assert(L->top - L->base == delta); | 485 | lj_assertG(L->top - L->base == delta, |
| 486 | "unbalanced stack after hot call"); | ||
| 461 | goto out; | 487 | goto out; |
| 462 | } else if (J->state != LJ_TRACE_IDLE && | 488 | } else if (J->state != LJ_TRACE_IDLE && |
| 463 | !(g->hookmask & (HOOK_GC|HOOK_VMEVENT))) { | 489 | !(g->hookmask & (HOOK_GC|HOOK_VMEVENT))) { |
| @@ -466,7 +492,8 @@ ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns *pc) | |||
| 466 | #endif | 492 | #endif |
| 467 | /* Record the FUNC* bytecodes, too. */ | 493 | /* Record the FUNC* bytecodes, too. */ |
| 468 | lj_trace_ins(J, pc-1); /* The interpreter bytecode PC is offset by 1. */ | 494 | lj_trace_ins(J, pc-1); /* The interpreter bytecode PC is offset by 1. */ |
| 469 | lua_assert(L->top - L->base == delta); | 495 | lj_assertG(L->top - L->base == delta, |
| 496 | "unbalanced stack after hot instruction"); | ||
| 470 | } | 497 | } |
| 471 | #endif | 498 | #endif |
| 472 | if ((g->hookmask & LUA_MASKCALL)) { | 499 | if ((g->hookmask & LUA_MASKCALL)) { |
| @@ -492,3 +519,43 @@ out: | |||
| 492 | return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */ | 519 | return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */ |
| 493 | } | 520 | } |
| 494 | 521 | ||
| 522 | #if LJ_HASJIT | ||
| 523 | /* Stitch a new trace. */ | ||
| 524 | void LJ_FASTCALL lj_dispatch_stitch(jit_State *J, const BCIns *pc) | ||
| 525 | { | ||
| 526 | if (!(J2G(J)->hookmask & HOOK_VMEVENT)) { | ||
| 527 | ERRNO_SAVE | ||
| 528 | lua_State *L = J->L; | ||
| 529 | void *cf = cframe_raw(L->cframe); | ||
| 530 | const BCIns *oldpc = cframe_pc(cf); | ||
| 531 | setcframe_pc(cf, pc); | ||
| 532 | /* Before dispatch, have to bias PC by 1. */ | ||
| 533 | L->top = L->base + cur_topslot(curr_proto(L), pc+1, cframe_multres_n(cf)); | ||
| 534 | lj_trace_stitch(J, pc-1); /* Point to the CALL instruction. */ | ||
| 535 | setcframe_pc(cf, oldpc); | ||
| 536 | ERRNO_RESTORE | ||
| 537 | } | ||
| 538 | } | ||
| 539 | #endif | ||
| 540 | |||
| 541 | #if LJ_HASPROFILE | ||
| 542 | /* Profile dispatch. */ | ||
| 543 | void LJ_FASTCALL lj_dispatch_profile(lua_State *L, const BCIns *pc) | ||
| 544 | { | ||
| 545 | ERRNO_SAVE | ||
| 546 | GCfunc *fn = curr_func(L); | ||
| 547 | GCproto *pt = funcproto(fn); | ||
| 548 | void *cf = cframe_raw(L->cframe); | ||
| 549 | const BCIns *oldpc = cframe_pc(cf); | ||
| 550 | global_State *g; | ||
| 551 | setcframe_pc(cf, pc); | ||
| 552 | L->top = L->base + cur_topslot(pt, pc, cframe_multres_n(cf)); | ||
| 553 | lj_profile_interpreter(L); | ||
| 554 | setcframe_pc(cf, oldpc); | ||
| 555 | g = G(L); | ||
| 556 | setgcref(g->cur_L, obj2gco(L)); | ||
| 557 | setvmstate(g, INTERP); | ||
| 558 | ERRNO_RESTORE | ||
| 559 | } | ||
| 560 | #endif | ||
| 561 | |||
