diff options
Diffstat (limited to 'src/lj_trace.c')
-rw-r--r-- | src/lj_trace.c | 131 |
1 files changed, 108 insertions, 23 deletions
diff --git a/src/lj_trace.c b/src/lj_trace.c index 311baa73..a43c8c4e 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c | |||
@@ -117,15 +117,26 @@ static void perftools_addtrace(GCtrace *T) | |||
117 | } | 117 | } |
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | /* Allocate space for copy of trace. */ | 120 | /* Allocate space for copy of T. */ |
121 | static GCtrace *trace_save_alloc(jit_State *J) | 121 | GCtrace * LJ_FASTCALL lj_trace_alloc(lua_State *L, GCtrace *T) |
122 | { | 122 | { |
123 | size_t sztr = ((sizeof(GCtrace)+7)&~7); | 123 | size_t sztr = ((sizeof(GCtrace)+7)&~7); |
124 | size_t szins = (J->cur.nins-J->cur.nk)*sizeof(IRIns); | 124 | size_t szins = (T->nins-T->nk)*sizeof(IRIns); |
125 | size_t sz = sztr + szins + | 125 | size_t sz = sztr + szins + |
126 | J->cur.nsnap*sizeof(SnapShot) + | 126 | T->nsnap*sizeof(SnapShot) + |
127 | J->cur.nsnapmap*sizeof(SnapEntry); | 127 | T->nsnapmap*sizeof(SnapEntry); |
128 | return lj_mem_newt(J->L, (MSize)sz, GCtrace); | 128 | GCtrace *T2 = lj_mem_newt(L, (MSize)sz, GCtrace); |
129 | char *p = (char *)T2 + sztr; | ||
130 | T2->gct = ~LJ_TTRACE; | ||
131 | T2->marked = 0; | ||
132 | T2->traceno = 0; | ||
133 | T2->ir = (IRIns *)p - T->nk; | ||
134 | T2->nins = T->nins; | ||
135 | T2->nk = T->nk; | ||
136 | T2->nsnap = T->nsnap; | ||
137 | T2->nsnapmap = T->nsnapmap; | ||
138 | memcpy(p, T->ir + T->nk, szins); | ||
139 | return T2; | ||
129 | } | 140 | } |
130 | 141 | ||
131 | /* Save current trace by copying and compacting it. */ | 142 | /* Save current trace by copying and compacting it. */ |
@@ -139,12 +150,12 @@ static void trace_save(jit_State *J, GCtrace *T) | |||
139 | setgcrefp(J2G(J)->gc.root, T); | 150 | setgcrefp(J2G(J)->gc.root, T); |
140 | newwhite(J2G(J), T); | 151 | newwhite(J2G(J), T); |
141 | T->gct = ~LJ_TTRACE; | 152 | T->gct = ~LJ_TTRACE; |
142 | T->ir = (IRIns *)p - J->cur.nk; | 153 | T->ir = (IRIns *)p - J->cur.nk; /* The IR has already been copied above. */ |
143 | memcpy(p, J->cur.ir+J->cur.nk, szins); | ||
144 | p += szins; | 154 | p += szins; |
145 | TRACE_APPENDVEC(snap, nsnap, SnapShot) | 155 | TRACE_APPENDVEC(snap, nsnap, SnapShot) |
146 | TRACE_APPENDVEC(snapmap, nsnapmap, SnapEntry) | 156 | TRACE_APPENDVEC(snapmap, nsnapmap, SnapEntry) |
147 | J->cur.traceno = 0; | 157 | J->cur.traceno = 0; |
158 | J->curfinal = NULL; | ||
148 | setgcrefp(J->trace[T->traceno], T); | 159 | setgcrefp(J->trace[T->traceno], T); |
149 | lj_gc_barriertrace(J2G(J), T->traceno); | 160 | lj_gc_barriertrace(J2G(J), T->traceno); |
150 | lj_gdbjit_addtrace(J, T); | 161 | lj_gdbjit_addtrace(J, T); |
@@ -274,7 +285,7 @@ int lj_trace_flushall(lua_State *L) | |||
274 | if (T->root == 0) | 285 | if (T->root == 0) |
275 | trace_flushroot(J, T); | 286 | trace_flushroot(J, T); |
276 | lj_gdbjit_deltrace(J, T); | 287 | lj_gdbjit_deltrace(J, T); |
277 | T->traceno = 0; | 288 | T->traceno = T->link = 0; /* Blacklist the link for cont_stitch. */ |
278 | setgcrefnull(J->trace[i]); | 289 | setgcrefnull(J->trace[i]); |
279 | } | 290 | } |
280 | } | 291 | } |
@@ -296,13 +307,42 @@ void lj_trace_initstate(global_State *g) | |||
296 | { | 307 | { |
297 | jit_State *J = G2J(g); | 308 | jit_State *J = G2J(g); |
298 | TValue *tv; | 309 | TValue *tv; |
299 | /* Initialize SIMD constants. */ | 310 | |
311 | /* Initialize aligned SIMD constants. */ | ||
300 | tv = LJ_KSIMD(J, LJ_KSIMD_ABS); | 312 | tv = LJ_KSIMD(J, LJ_KSIMD_ABS); |
301 | tv[0].u64 = U64x(7fffffff,ffffffff); | 313 | tv[0].u64 = U64x(7fffffff,ffffffff); |
302 | tv[1].u64 = U64x(7fffffff,ffffffff); | 314 | tv[1].u64 = U64x(7fffffff,ffffffff); |
303 | tv = LJ_KSIMD(J, LJ_KSIMD_NEG); | 315 | tv = LJ_KSIMD(J, LJ_KSIMD_NEG); |
304 | tv[0].u64 = U64x(80000000,00000000); | 316 | tv[0].u64 = U64x(80000000,00000000); |
305 | tv[1].u64 = U64x(80000000,00000000); | 317 | tv[1].u64 = U64x(80000000,00000000); |
318 | |||
319 | /* Initialize 32/64 bit constants. */ | ||
320 | #if LJ_TARGET_X86ORX64 | ||
321 | J->k64[LJ_K64_TOBIT].u64 = U64x(43380000,00000000); | ||
322 | #if LJ_32 | ||
323 | J->k64[LJ_K64_M2P64_31].u64 = U64x(c1e00000,00000000); | ||
324 | #endif | ||
325 | J->k64[LJ_K64_2P64].u64 = U64x(43f00000,00000000); | ||
326 | J->k32[LJ_K32_M2P64_31] = LJ_64 ? 0xdf800000 : 0xcf000000; | ||
327 | #endif | ||
328 | #if LJ_TARGET_X86ORX64 || LJ_TARGET_MIPS64 | ||
329 | J->k64[LJ_K64_M2P64].u64 = U64x(c3f00000,00000000); | ||
330 | #endif | ||
331 | #if LJ_TARGET_PPC | ||
332 | J->k32[LJ_K32_2P52_2P31] = 0x59800004; | ||
333 | J->k32[LJ_K32_2P52] = 0x59800000; | ||
334 | #endif | ||
335 | #if LJ_TARGET_PPC || LJ_TARGET_MIPS | ||
336 | J->k32[LJ_K32_2P31] = 0x4f000000; | ||
337 | #endif | ||
338 | #if LJ_TARGET_MIPS | ||
339 | J->k64[LJ_K64_2P31].u64 = U64x(41e00000,00000000); | ||
340 | #if LJ_64 | ||
341 | J->k64[LJ_K64_2P63].u64 = U64x(43e00000,00000000); | ||
342 | J->k32[LJ_K32_2P63] = 0x5f000000; | ||
343 | J->k32[LJ_K32_M2P64] = 0xdf800000; | ||
344 | #endif | ||
345 | #endif | ||
306 | } | 346 | } |
307 | 347 | ||
308 | /* Free everything associated with the JIT compiler state. */ | 348 | /* Free everything associated with the JIT compiler state. */ |
@@ -317,7 +357,6 @@ void lj_trace_freestate(global_State *g) | |||
317 | } | 357 | } |
318 | #endif | 358 | #endif |
319 | lj_mcode_free(J); | 359 | lj_mcode_free(J); |
320 | lj_ir_k64_freeall(J); | ||
321 | lj_mem_freevec(g, J->snapmapbuf, J->sizesnapmap, SnapEntry); | 360 | lj_mem_freevec(g, J->snapmapbuf, J->sizesnapmap, SnapEntry); |
322 | lj_mem_freevec(g, J->snapbuf, J->sizesnap, SnapShot); | 361 | lj_mem_freevec(g, J->snapbuf, J->sizesnap, SnapShot); |
323 | lj_mem_freevec(g, J->irbuf + J->irbotlim, J->irtoplim - J->irbotlim, IRIns); | 362 | lj_mem_freevec(g, J->irbuf + J->irbotlim, J->irtoplim - J->irbotlim, IRIns); |
@@ -367,7 +406,7 @@ static void trace_start(jit_State *J) | |||
367 | TraceNo traceno; | 406 | TraceNo traceno; |
368 | 407 | ||
369 | if ((J->pt->flags & PROTO_NOJIT)) { /* JIT disabled for this proto? */ | 408 | if ((J->pt->flags & PROTO_NOJIT)) { /* JIT disabled for this proto? */ |
370 | if (J->parent == 0) { | 409 | if (J->parent == 0 && J->exitno == 0) { |
371 | /* Lazy bytecode patching to disable hotcount events. */ | 410 | /* Lazy bytecode patching to disable hotcount events. */ |
372 | lua_assert(bc_op(*J->pc) == BC_FORL || bc_op(*J->pc) == BC_ITERL || | 411 | lua_assert(bc_op(*J->pc) == BC_FORL || bc_op(*J->pc) == BC_ITERL || |
373 | bc_op(*J->pc) == BC_LOOP || bc_op(*J->pc) == BC_FUNCF); | 412 | bc_op(*J->pc) == BC_LOOP || bc_op(*J->pc) == BC_FUNCF); |
@@ -401,6 +440,8 @@ static void trace_start(jit_State *J) | |||
401 | J->guardemit.irt = 0; | 440 | J->guardemit.irt = 0; |
402 | J->postproc = LJ_POST_NONE; | 441 | J->postproc = LJ_POST_NONE; |
403 | lj_resetsplit(J); | 442 | lj_resetsplit(J); |
443 | J->retryrec = 0; | ||
444 | J->ktrace = 0; | ||
404 | setgcref(J->cur.startpt, obj2gco(J->pt)); | 445 | setgcref(J->cur.startpt, obj2gco(J->pt)); |
405 | 446 | ||
406 | L = J->L; | 447 | L = J->L; |
@@ -412,6 +453,12 @@ static void trace_start(jit_State *J) | |||
412 | if (J->parent) { | 453 | if (J->parent) { |
413 | setintV(L->top++, J->parent); | 454 | setintV(L->top++, J->parent); |
414 | setintV(L->top++, J->exitno); | 455 | setintV(L->top++, J->exitno); |
456 | } else { | ||
457 | BCOp op = bc_op(*J->pc); | ||
458 | if (op == BC_CALLM || op == BC_CALL || op == BC_ITERC) { | ||
459 | setintV(L->top++, J->exitno); /* Parent of stitched trace. */ | ||
460 | setintV(L->top++, -1); | ||
461 | } | ||
415 | } | 462 | } |
416 | ); | 463 | ); |
417 | lj_record_setup(J); | 464 | lj_record_setup(J); |
@@ -424,7 +471,7 @@ static void trace_stop(jit_State *J) | |||
424 | BCOp op = bc_op(J->cur.startins); | 471 | BCOp op = bc_op(J->cur.startins); |
425 | GCproto *pt = &gcref(J->cur.startpt)->pt; | 472 | GCproto *pt = &gcref(J->cur.startpt)->pt; |
426 | TraceNo traceno = J->cur.traceno; | 473 | TraceNo traceno = J->cur.traceno; |
427 | GCtrace *T = trace_save_alloc(J); /* Do this first. May throw OOM. */ | 474 | GCtrace *T = J->curfinal; |
428 | lua_State *L; | 475 | lua_State *L; |
429 | 476 | ||
430 | switch (op) { | 477 | switch (op) { |
@@ -461,6 +508,12 @@ static void trace_stop(jit_State *J) | |||
461 | root->nextside = (TraceNo1)traceno; | 508 | root->nextside = (TraceNo1)traceno; |
462 | } | 509 | } |
463 | break; | 510 | break; |
511 | case BC_CALLM: | ||
512 | case BC_CALL: | ||
513 | case BC_ITERC: | ||
514 | /* Trace stitching: patch link of previous trace. */ | ||
515 | traceref(J, J->exitno)->link = traceno; | ||
516 | break; | ||
464 | default: | 517 | default: |
465 | lua_assert(0); | 518 | lua_assert(0); |
466 | break; | 519 | break; |
@@ -475,6 +528,7 @@ static void trace_stop(jit_State *J) | |||
475 | lj_vmevent_send(L, TRACE, | 528 | lj_vmevent_send(L, TRACE, |
476 | setstrV(L, L->top++, lj_str_newlit(L, "stop")); | 529 | setstrV(L, L->top++, lj_str_newlit(L, "stop")); |
477 | setintV(L->top++, traceno); | 530 | setintV(L->top++, traceno); |
531 | setfuncV(L, L->top++, J->fn); | ||
478 | ); | 532 | ); |
479 | } | 533 | } |
480 | 534 | ||
@@ -502,6 +556,10 @@ static int trace_abort(jit_State *J) | |||
502 | 556 | ||
503 | J->postproc = LJ_POST_NONE; | 557 | J->postproc = LJ_POST_NONE; |
504 | lj_mcode_abort(J); | 558 | lj_mcode_abort(J); |
559 | if (J->curfinal) { | ||
560 | lj_trace_free(J2G(J), J->curfinal); | ||
561 | J->curfinal = NULL; | ||
562 | } | ||
505 | if (tvisnumber(L->top-1)) | 563 | if (tvisnumber(L->top-1)) |
506 | e = (TraceError)numberVint(L->top-1); | 564 | e = (TraceError)numberVint(L->top-1); |
507 | if (e == LJ_TRERR_MCODELM) { | 565 | if (e == LJ_TRERR_MCODELM) { |
@@ -510,8 +568,17 @@ static int trace_abort(jit_State *J) | |||
510 | return 1; /* Retry ASM with new MCode area. */ | 568 | return 1; /* Retry ASM with new MCode area. */ |
511 | } | 569 | } |
512 | /* Penalize or blacklist starting bytecode instruction. */ | 570 | /* Penalize or blacklist starting bytecode instruction. */ |
513 | if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) | 571 | if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) { |
514 | penalty_pc(J, &gcref(J->cur.startpt)->pt, mref(J->cur.startpc, BCIns), e); | 572 | if (J->exitno == 0) { |
573 | BCIns *startpc = mref(J->cur.startpc, BCIns); | ||
574 | if (e == LJ_TRERR_RETRY) | ||
575 | hotcount_set(J2GG(J), startpc+1, 1); /* Immediate retry. */ | ||
576 | else | ||
577 | penalty_pc(J, &gcref(J->cur.startpt)->pt, startpc, e); | ||
578 | } else { | ||
579 | traceref(J, J->exitno)->link = J->exitno; /* Self-link is blacklisted. */ | ||
580 | } | ||
581 | } | ||
515 | 582 | ||
516 | /* Is there anything to abort? */ | 583 | /* Is there anything to abort? */ |
517 | traceno = J->cur.traceno; | 584 | traceno = J->cur.traceno; |
@@ -680,6 +747,7 @@ static void trace_hotside(jit_State *J, const BCIns *pc) | |||
680 | { | 747 | { |
681 | SnapShot *snap = &traceref(J, J->parent)->snap[J->exitno]; | 748 | SnapShot *snap = &traceref(J, J->parent)->snap[J->exitno]; |
682 | if (!(J2G(J)->hookmask & (HOOK_GC|HOOK_VMEVENT)) && | 749 | if (!(J2G(J)->hookmask & (HOOK_GC|HOOK_VMEVENT)) && |
750 | isluafunc(curr_func(J->L)) && | ||
683 | snap->count != SNAPCOUNT_DONE && | 751 | snap->count != SNAPCOUNT_DONE && |
684 | ++snap->count >= J->param[JIT_P_hotexit]) { | 752 | ++snap->count >= J->param[JIT_P_hotexit]) { |
685 | lua_assert(J->state == LJ_TRACE_IDLE); | 753 | lua_assert(J->state == LJ_TRACE_IDLE); |
@@ -689,6 +757,20 @@ static void trace_hotside(jit_State *J, const BCIns *pc) | |||
689 | } | 757 | } |
690 | } | 758 | } |
691 | 759 | ||
760 | /* Stitch a new trace to the previous trace. */ | ||
761 | void LJ_FASTCALL lj_trace_stitch(jit_State *J, const BCIns *pc) | ||
762 | { | ||
763 | /* Only start a new trace if not recording or inside __gc call or vmevent. */ | ||
764 | if (J->state == LJ_TRACE_IDLE && | ||
765 | !(J2G(J)->hookmask & (HOOK_GC|HOOK_VMEVENT))) { | ||
766 | J->parent = 0; /* Have to treat it like a root trace. */ | ||
767 | /* J->exitno is set to the invoking trace. */ | ||
768 | J->state = LJ_TRACE_START; | ||
769 | lj_trace_ins(J, pc); | ||
770 | } | ||
771 | } | ||
772 | |||
773 | |||
692 | /* Tiny struct to pass data to protected call. */ | 774 | /* Tiny struct to pass data to protected call. */ |
693 | typedef struct ExitDataCP { | 775 | typedef struct ExitDataCP { |
694 | jit_State *J; | 776 | jit_State *J; |
@@ -775,17 +857,20 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | |||
775 | if (errcode) | 857 | if (errcode) |
776 | return -errcode; /* Return negated error code. */ | 858 | return -errcode; /* Return negated error code. */ |
777 | 859 | ||
778 | lj_vmevent_send(L, TEXIT, | 860 | if (!(LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE))) |
779 | lj_state_checkstack(L, 4+RID_NUM_GPR+RID_NUM_FPR+LUA_MINSTACK); | 861 | lj_vmevent_send(L, TEXIT, |
780 | setintV(L->top++, J->parent); | 862 | lj_state_checkstack(L, 4+RID_NUM_GPR+RID_NUM_FPR+LUA_MINSTACK); |
781 | setintV(L->top++, J->exitno); | 863 | setintV(L->top++, J->parent); |
782 | trace_exit_regs(L, ex); | 864 | setintV(L->top++, J->exitno); |
783 | ); | 865 | trace_exit_regs(L, ex); |
866 | ); | ||
784 | 867 | ||
785 | pc = exd.pc; | 868 | pc = exd.pc; |
786 | cf = cframe_raw(L->cframe); | 869 | cf = cframe_raw(L->cframe); |
787 | setcframe_pc(cf, pc); | 870 | setcframe_pc(cf, pc); |
788 | if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) { | 871 | if (LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE)) { |
872 | /* Just exit to interpreter. */ | ||
873 | } else if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) { | ||
789 | if (!(G(L)->hookmask & HOOK_GC)) | 874 | if (!(G(L)->hookmask & HOOK_GC)) |
790 | lj_gc_step(L); /* Exited because of GC: drive GC forward. */ | 875 | lj_gc_step(L); /* Exited because of GC: drive GC forward. */ |
791 | } else { | 876 | } else { |
@@ -809,7 +894,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | |||
809 | ERRNO_RESTORE | 894 | ERRNO_RESTORE |
810 | switch (bc_op(*pc)) { | 895 | switch (bc_op(*pc)) { |
811 | case BC_CALLM: case BC_CALLMT: | 896 | case BC_CALLM: case BC_CALLMT: |
812 | return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc)); | 897 | return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc) - LJ_FR2); |
813 | case BC_RETM: | 898 | case BC_RETM: |
814 | return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc)); | 899 | return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc)); |
815 | case BC_TSETM: | 900 | case BC_TSETM: |