aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-09-08 02:53:23 +0200
committerMike Pall <mike>2013-09-08 02:53:23 +0200
commitd1194a82eb24afa1c749a0a8080b67d168f9f201 (patch)
treefb3bebc2cbf5032a49653dd6a0bd31c420dd8083
parentd3d30d389b504495d054d71bdee0fe2677d4b44c (diff)
downloadluajit-d1194a82eb24afa1c749a0a8080b67d168f9f201.tar.gz
luajit-d1194a82eb24afa1c749a0a8080b67d168f9f201.tar.bz2
luajit-d1194a82eb24afa1c749a0a8080b67d168f9f201.zip
Low-overhead profiler, part 4: JIT compiler support.
-rw-r--r--src/Makefile.dep8
-rw-r--r--src/lj_asm.c1
-rw-r--r--src/lj_asm_arm.h10
-rw-r--r--src/lj_asm_mips.h11
-rw-r--r--src/lj_asm_ppc.h11
-rw-r--r--src/lj_asm_x86.h10
-rw-r--r--src/lj_ir.h1
-rw-r--r--src/lj_jit.h6
-rw-r--r--src/lj_opt_fold.c11
-rw-r--r--src/lj_profile.c17
-rw-r--r--src/lj_record.c60
-rw-r--r--src/lj_trace.c17
12 files changed, 151 insertions, 12 deletions
diff --git a/src/Makefile.dep b/src/Makefile.dep
index 7991bd16..3f080374 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -170,12 +170,12 @@ lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
170 lj_vm.h lj_vmevent.h 170 lj_vm.h lj_vmevent.h
171lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 171lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
172 lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \ 172 lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \
173 lj_jit.h lj_ir.h lj_profile.h luajit.h 173 lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h
174lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 174lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
175 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ 175 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \
176 lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h \ 176 lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \
177 lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h lj_record.h \ 177 lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \
178 lj_ffrecord.h lj_snap.h lj_vm.h 178 lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h
179lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 179lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
180 lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \ 180 lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \
181 lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \ 181 lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \
diff --git a/src/lj_asm.c b/src/lj_asm.c
index ee1cc5b5..2bf273e1 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -1565,6 +1565,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
1565 case IR_PHI: asm_phi(as, ir); break; 1565 case IR_PHI: asm_phi(as, ir); break;
1566 case IR_HIOP: asm_hiop(as, ir); break; 1566 case IR_HIOP: asm_hiop(as, ir); break;
1567 case IR_GCSTEP: asm_gcstep(as, ir); break; 1567 case IR_GCSTEP: asm_gcstep(as, ir); break;
1568 case IR_PROF: asm_prof(as, ir); break;
1568 1569
1569 /* Guarded assertions. */ 1570 /* Guarded assertions. */
1570 case IR_LT: case IR_GE: case IR_LE: case IR_GT: 1571 case IR_LT: case IR_GE: case IR_LE: case IR_GT:
diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h
index 497a5692..d736859c 100644
--- a/src/lj_asm_arm.h
+++ b/src/lj_asm_arm.h
@@ -1915,6 +1915,16 @@ static void asm_hiop(ASMState *as, IRIns *ir)
1915#endif 1915#endif
1916} 1916}
1917 1917
1918/* -- Profiling ----------------------------------------------------------- */
1919
1920static void asm_prof(ASMState *as, IRIns *ir)
1921{
1922 UNUSED(ir);
1923 asm_guardcc(as, CC_NE);
1924 emit_n(as, ARMI_TST|ARMI_K12|HOOK_PROFILE, RID_TMP);
1925 emit_lsptr(as, ARMI_LDRB, RID_TMP, (void *)&J2G(as->J)->hookmask);
1926}
1927
1918/* -- Stack handling ------------------------------------------------------ */ 1928/* -- Stack handling ------------------------------------------------------ */
1919 1929
1920/* Check Lua stack size for overflow. Use exit handler as fallback. */ 1930/* Check Lua stack size for overflow. Use exit handler as fallback. */
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
index 74eff10b..365538bb 100644
--- a/src/lj_asm_mips.h
+++ b/src/lj_asm_mips.h
@@ -1562,6 +1562,17 @@ static void asm_hiop(ASMState *as, IRIns *ir)
1562#endif 1562#endif
1563} 1563}
1564 1564
1565/* -- Profiling ----------------------------------------------------------- */
1566
1567static void asm_prof(ASMState *as, IRIns *ir)
1568{
1569 UNUSED(ir);
1570 asm_guard(as, MIPSI_BNE, RID_TMP, RID_ZERO);
1571 emit_tsi(as, MIPSI_ANDI, RID_TMP, RID_TMP, HOOK_PROFILE);
1572 emit_lsglptr(as, MIPSI_LBU, RID_TMP,
1573 (int32_t)offsetof(global_State, hookmask));
1574}
1575
1565/* -- Stack handling ------------------------------------------------------ */ 1576/* -- Stack handling ------------------------------------------------------ */
1566 1577
1567/* Check Lua stack size for overflow. Use exit handler as fallback. */ 1578/* Check Lua stack size for overflow. Use exit handler as fallback. */
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h
index 652dcca0..e0dcaed0 100644
--- a/src/lj_asm_ppc.h
+++ b/src/lj_asm_ppc.h
@@ -1738,6 +1738,17 @@ static void asm_hiop(ASMState *as, IRIns *ir)
1738#endif 1738#endif
1739} 1739}
1740 1740
1741/* -- Profiling ----------------------------------------------------------- */
1742
1743static void asm_prof(ASMState *as, IRIns *ir)
1744{
1745 UNUSED(ir);
1746 asm_guardcc(as, CC_NE);
1747 emit_asi(as, PPCI_ANDIDOT, RID_TMP, RID_TMP, HOOK_PROFILE);
1748 emit_lsglptr(as, PPCI_LBZ, RID_TMP,
1749 (int32_t)offsetof(global_State, hookmask));
1750}
1751
1741/* -- Stack handling ------------------------------------------------------ */ 1752/* -- Stack handling ------------------------------------------------------ */
1742 1753
1743/* Check Lua stack size for overflow. Use exit handler as fallback. */ 1754/* Check Lua stack size for overflow. Use exit handler as fallback. */
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h
index 82517600..8b72c5e8 100644
--- a/src/lj_asm_x86.h
+++ b/src/lj_asm_x86.h
@@ -2348,6 +2348,16 @@ static void asm_hiop(ASMState *as, IRIns *ir)
2348#endif 2348#endif
2349} 2349}
2350 2350
2351/* -- Profiling ----------------------------------------------------------- */
2352
2353static void asm_prof(ASMState *as, IRIns *ir)
2354{
2355 UNUSED(ir);
2356 asm_guardcc(as, CC_NE);
2357 emit_i8(as, HOOK_PROFILE);
2358 emit_rma(as, XO_GROUP3b, XOg_TEST, &J2G(as->J)->hookmask);
2359}
2360
2351/* -- Stack handling ------------------------------------------------------ */ 2361/* -- Stack handling ------------------------------------------------------ */
2352 2362
2353/* Check Lua stack size for overflow. Use exit handler as fallback. */ 2363/* Check Lua stack size for overflow. Use exit handler as fallback. */
diff --git a/src/lj_ir.h b/src/lj_ir.h
index 841153d8..54bbbdda 100644
--- a/src/lj_ir.h
+++ b/src/lj_ir.h
@@ -40,6 +40,7 @@
40 _(USE, S , ref, ___) \ 40 _(USE, S , ref, ___) \
41 _(PHI, S , ref, ref) \ 41 _(PHI, S , ref, ref) \
42 _(RENAME, S , ref, lit) \ 42 _(RENAME, S , ref, lit) \
43 _(PROF, S , ___, ___) \
43 \ 44 \
44 /* Constants. */ \ 45 /* Constants. */ \
45 _(KPRI, N , ___, ___) \ 46 _(KPRI, N , ___, ___) \
diff --git a/src/lj_jit.h b/src/lj_jit.h
index 2683b462..cfb04aa7 100644
--- a/src/lj_jit.h
+++ b/src/lj_jit.h
@@ -396,6 +396,12 @@ typedef struct jit_State {
396 size_t szallmcarea; /* Total size of all allocated mcode areas. */ 396 size_t szallmcarea; /* Total size of all allocated mcode areas. */
397 397
398 TValue errinfo; /* Additional info element for trace errors. */ 398 TValue errinfo; /* Additional info element for trace errors. */
399
400#if LJ_HASPROFILE
401 GCproto *prev_pt; /* Previous prototype. */
402 BCLine prev_line; /* Previous line. */
403 int prof_mode; /* Profiling mode: 0, 'f', 'l'. */
404#endif
399} 405}
400#if LJ_TARGET_ARM 406#if LJ_TARGET_ARM
401LJ_ALIGN(16) /* For DISPATCH-relative addresses in assembler part. */ 407LJ_ALIGN(16) /* For DISPATCH-relative addresses in assembler part. */
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c
index 1d37a7fd..84c5dc00 100644
--- a/src/lj_opt_fold.c
+++ b/src/lj_opt_fold.c
@@ -2285,6 +2285,17 @@ LJFOLDF(barrier_tnew_tdup)
2285 return DROPFOLD; 2285 return DROPFOLD;
2286} 2286}
2287 2287
2288/* -- Profiling ----------------------------------------------------------- */
2289
2290LJFOLD(PROF any any)
2291LJFOLDF(prof)
2292{
2293 IRRef ref = J->chain[IR_PROF];
2294 if (ref+1 == J->cur.nins) /* Drop neighbouring IR_PROF. */
2295 return ref;
2296 return EMITFOLD;
2297}
2298
2288/* -- Stores and allocations ---------------------------------------------- */ 2299/* -- Stores and allocations ---------------------------------------------- */
2289 2300
2290/* Stores and allocations cannot be folded or passed on to CSE in general. 2301/* Stores and allocations cannot be folded or passed on to CSE in general.
diff --git a/src/lj_profile.c b/src/lj_profile.c
index 0baad06c..a58aefc8 100644
--- a/src/lj_profile.c
+++ b/src/lj_profile.c
@@ -14,6 +14,10 @@
14#include "lj_frame.h" 14#include "lj_frame.h"
15#include "lj_debug.h" 15#include "lj_debug.h"
16#include "lj_dispatch.h" 16#include "lj_dispatch.h"
17#if LJ_HASJIT
18#include "lj_jit.h"
19#include "lj_trace.h"
20#endif
17#include "lj_profile.h" 21#include "lj_profile.h"
18 22
19#include "luajit.h" 23#include "luajit.h"
@@ -218,13 +222,20 @@ LUA_API void luaJIT_profile_start(lua_State *L, const char *mode,
218 ProfileState *ps = &profile_state; 222 ProfileState *ps = &profile_state;
219 int interval = LJ_PROFILE_INTERVAL_DEFAULT; 223 int interval = LJ_PROFILE_INTERVAL_DEFAULT;
220 while (*mode) { 224 while (*mode) {
221 switch (*mode++) { 225 int m = *mode++;
226 switch (m) {
222 case 'i': 227 case 'i':
223 interval = 0; 228 interval = 0;
224 while (*mode >= '0' && *mode <= '9') 229 while (*mode >= '0' && *mode <= '9')
225 interval = interval * 10 + (*mode++ - '0'); 230 interval = interval * 10 + (*mode++ - '0');
226 if (interval <= 0) interval = 1; 231 if (interval <= 0) interval = 1;
227 break; 232 break;
233#if LJ_HASJIT
234 case 'l': case 'f':
235 L2J(L)->prof_mode = m;
236 lj_trace_flushall(L);
237 break;
238#endif
228 default: /* Ignore unknown mode chars. */ 239 default: /* Ignore unknown mode chars. */
229 break; 240 break;
230 } 241 }
@@ -251,6 +262,10 @@ LUA_API void luaJIT_profile_stop(lua_State *L)
251 profile_timer_stop(ps); 262 profile_timer_stop(ps);
252 g->hookmask &= ~HOOK_PROFILE; 263 g->hookmask &= ~HOOK_PROFILE;
253 lj_dispatch_update(g); 264 lj_dispatch_update(g);
265#if LJ_HASJIT
266 G2J(g)->prof_mode = 0;
267 lj_trace_flushall(L);
268#endif
254 lj_buf_free(g, &ps->sb); 269 lj_buf_free(g, &ps->sb);
255 setmref(ps->sb.b, NULL); 270 setmref(ps->sb.b, NULL);
256 setmref(ps->sb.e, NULL); 271 setmref(ps->sb.e, NULL);
diff --git a/src/lj_record.c b/src/lj_record.c
index bdf0212a..3dcb0a85 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -20,6 +20,9 @@
20#endif 20#endif
21#include "lj_bc.h" 21#include "lj_bc.h"
22#include "lj_ff.h" 22#include "lj_ff.h"
23#if LJ_HASPROFILE
24#include "lj_debug.h"
25#endif
23#include "lj_ir.h" 26#include "lj_ir.h"
24#include "lj_jit.h" 27#include "lj_jit.h"
25#include "lj_ircall.h" 28#include "lj_ircall.h"
@@ -579,6 +582,52 @@ static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev)
579 } /* Side trace continues across a loop that's left or not entered. */ 582 } /* Side trace continues across a loop that's left or not entered. */
580} 583}
581 584
585/* -- Record profiler hook checks ----------------------------------------- */
586
587#if LJ_HASPROFILE
588
589/* Need to insert profiler hook check? */
590static int rec_profile_need(jit_State *J, GCproto *pt, const BCIns *pc)
591{
592 GCproto *ppt;
593 lua_assert(J->prof_mode == 'f' || J->prof_mode == 'l');
594 if (!pt)
595 return 0;
596 ppt = J->prev_pt;
597 J->prev_pt = pt;
598 if (pt != ppt && ppt) {
599 J->prev_line = -1;
600 return 1;
601 }
602 if (J->prof_mode == 'l') {
603 BCLine line = lj_debug_line(pt, proto_bcpos(pt, pc));
604 BCLine pline = J->prev_line;
605 J->prev_line = line;
606 if (pline != line)
607 return 1;
608 }
609 return 0;
610}
611
612static void rec_profile_ins(jit_State *J, const BCIns *pc)
613{
614 if (J->prof_mode && rec_profile_need(J, J->pt, pc)) {
615 emitir(IRTG(IR_PROF, IRT_NIL), 0, 0);
616 lj_snap_add(J);
617 }
618}
619
620static void rec_profile_ret(jit_State *J)
621{
622 if (J->prof_mode == 'f') {
623 emitir(IRTG(IR_PROF, IRT_NIL), 0, 0);
624 J->prev_pt = NULL;
625 lj_snap_add(J);
626 }
627}
628
629#endif
630
582/* -- Record calls and returns -------------------------------------------- */ 631/* -- Record calls and returns -------------------------------------------- */
583 632
584/* Specialize to the runtime value of the called function or its prototype. */ 633/* Specialize to the runtime value of the called function or its prototype. */
@@ -1770,6 +1819,10 @@ void lj_record_ins(jit_State *J)
1770 rec_check_ir(J); 1819 rec_check_ir(J);
1771#endif 1820#endif
1772 1821
1822#if LJ_HASPROFILE
1823 rec_profile_ins(J, pc);
1824#endif
1825
1773 /* Keep a copy of the runtime values of var/num/str operands. */ 1826 /* Keep a copy of the runtime values of var/num/str operands. */
1774#define rav (&ix.valv) 1827#define rav (&ix.valv)
1775#define rbv (&ix.tabv) 1828#define rbv (&ix.tabv)
@@ -2074,6 +2127,9 @@ void lj_record_ins(jit_State *J)
2074 rc = (BCReg)(J->L->top - J->L->base) - ra + 1; 2127 rc = (BCReg)(J->L->top - J->L->base) - ra + 1;
2075 /* fallthrough */ 2128 /* fallthrough */
2076 case BC_RET: case BC_RET0: case BC_RET1: 2129 case BC_RET: case BC_RET0: case BC_RET1:
2130#if LJ_HASPROFILE
2131 rec_profile_ret(J);
2132#endif
2077 lj_record_ret(J, ra, (ptrdiff_t)rc-1); 2133 lj_record_ret(J, ra, (ptrdiff_t)rc-1);
2078 break; 2134 break;
2079 2135
@@ -2303,6 +2359,10 @@ void lj_record_setup(jit_State *J)
2303 if (1 + J->pt->framesize >= LJ_MAX_JSLOTS) 2359 if (1 + J->pt->framesize >= LJ_MAX_JSLOTS)
2304 lj_trace_err(J, LJ_TRERR_STACKOV); 2360 lj_trace_err(J, LJ_TRERR_STACKOV);
2305 } 2361 }
2362#if LJ_HASPROFILE
2363 J->prev_pt = NULL;
2364 J->prev_line = -1;
2365#endif
2306#ifdef LUAJIT_ENABLE_CHECKHOOK 2366#ifdef LUAJIT_ENABLE_CHECKHOOK
2307 /* Regularly check for instruction/line hooks from compiled code and 2367 /* Regularly check for instruction/line hooks from compiled code and
2308 ** exit to the interpreter if the hooks are set. 2368 ** exit to the interpreter if the hooks are set.
diff --git a/src/lj_trace.c b/src/lj_trace.c
index c70fc247..2b8d931f 100644
--- a/src/lj_trace.c
+++ b/src/lj_trace.c
@@ -766,17 +766,20 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
766 if (errcode) 766 if (errcode)
767 return -errcode; /* Return negated error code. */ 767 return -errcode; /* Return negated error code. */
768 768
769 lj_vmevent_send(L, TEXIT, 769 if (!(LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE)))
770 lj_state_checkstack(L, 4+RID_NUM_GPR+RID_NUM_FPR+LUA_MINSTACK); 770 lj_vmevent_send(L, TEXIT,
771 setintV(L->top++, J->parent); 771 lj_state_checkstack(L, 4+RID_NUM_GPR+RID_NUM_FPR+LUA_MINSTACK);
772 setintV(L->top++, J->exitno); 772 setintV(L->top++, J->parent);
773 trace_exit_regs(L, ex); 773 setintV(L->top++, J->exitno);
774 ); 774 trace_exit_regs(L, ex);
775 );
775 776
776 pc = exd.pc; 777 pc = exd.pc;
777 cf = cframe_raw(L->cframe); 778 cf = cframe_raw(L->cframe);
778 setcframe_pc(cf, pc); 779 setcframe_pc(cf, pc);
779 if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) { 780 if (LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE)) {
781 /* Just exit to interpreter. */
782 } else if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) {
780 if (!(G(L)->hookmask & HOOK_GC)) 783 if (!(G(L)->hookmask & HOOK_GC))
781 lj_gc_step(L); /* Exited because of GC: drive GC forward. */ 784 lj_gc_step(L); /* Exited because of GC: drive GC forward. */
782 } else { 785 } else {