aboutsummaryrefslogtreecommitdiff
path: root/src/lj_dispatch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_dispatch.c')
-rw-r--r--src/lj_dispatch.c113
1 files changed, 89 insertions, 24 deletions
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c
index 54c86038..ded382aa 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>
38LJ_FUNCA_NORET void LJ_FASTCALL lj_ffh_coroutine_wrap_err(lua_State *L, 43LJ_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,
42static const ASMFunction dispatch_got[] = { 53static 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. */
92void lj_dispatch_update(global_State *g) 106void 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
@@ -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,41 @@ 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. */
524void LJ_FASTCALL lj_dispatch_stitch(jit_State *J, const BCIns *pc)
525{
526 ERRNO_SAVE
527 lua_State *L = J->L;
528 void *cf = cframe_raw(L->cframe);
529 const BCIns *oldpc = cframe_pc(cf);
530 setcframe_pc(cf, pc);
531 /* Before dispatch, have to bias PC by 1. */
532 L->top = L->base + cur_topslot(curr_proto(L), pc+1, cframe_multres_n(cf));
533 lj_trace_stitch(J, pc-1); /* Point to the CALL instruction. */
534 setcframe_pc(cf, oldpc);
535 ERRNO_RESTORE
536}
537#endif
538
539#if LJ_HASPROFILE
540/* Profile dispatch. */
541void LJ_FASTCALL lj_dispatch_profile(lua_State *L, const BCIns *pc)
542{
543 ERRNO_SAVE
544 GCfunc *fn = curr_func(L);
545 GCproto *pt = funcproto(fn);
546 void *cf = cframe_raw(L->cframe);
547 const BCIns *oldpc = cframe_pc(cf);
548 global_State *g;
549 setcframe_pc(cf, pc);
550 L->top = L->base + cur_topslot(pt, pc, cframe_multres_n(cf));
551 lj_profile_interpreter(L);
552 setcframe_pc(cf, oldpc);
553 g = G(L);
554 setgcref(g->cur_L, obj2gco(L));
555 setvmstate(g, INTERP);
556 ERRNO_RESTORE
557}
558#endif
559