diff options
Diffstat (limited to 'src/lj_record.c')
-rw-r--r-- | src/lj_record.c | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index ce9e20de..4ab474ad 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -233,7 +233,7 @@ static void canonicalize_slots(jit_State *J) | |||
233 | } | 233 | } |
234 | 234 | ||
235 | /* Stop recording. */ | 235 | /* Stop recording. */ |
236 | static void rec_stop(jit_State *J, TraceLink linktype, TraceNo lnk) | 236 | void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk) |
237 | { | 237 | { |
238 | lj_trace_end(J); | 238 | lj_trace_end(J); |
239 | J->cur.linktype = (uint8_t)linktype; | 239 | J->cur.linktype = (uint8_t)linktype; |
@@ -501,8 +501,7 @@ static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) | |||
501 | static LoopEvent rec_iterl(jit_State *J, const BCIns iterins) | 501 | static LoopEvent rec_iterl(jit_State *J, const BCIns iterins) |
502 | { | 502 | { |
503 | BCReg ra = bc_a(iterins); | 503 | BCReg ra = bc_a(iterins); |
504 | lua_assert(J->base[ra] != 0); | 504 | if (!tref_isnil(getslot(J, ra))) { /* Looping back? */ |
505 | if (!tref_isnil(J->base[ra])) { /* Looping back? */ | ||
506 | J->base[ra-1] = J->base[ra]; /* Copy result of ITERC to control var. */ | 505 | J->base[ra-1] = J->base[ra]; /* Copy result of ITERC to control var. */ |
507 | J->maxslot = ra-1+bc_b(J->pc[-1]); | 506 | J->maxslot = ra-1+bc_b(J->pc[-1]); |
508 | J->pc += bc_j(iterins)+1; | 507 | J->pc += bc_j(iterins)+1; |
@@ -540,12 +539,12 @@ static int innerloopleft(jit_State *J, const BCIns *pc) | |||
540 | /* Handle the case when an interpreted loop op is hit. */ | 539 | /* Handle the case when an interpreted loop op is hit. */ |
541 | static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) | 540 | static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) |
542 | { | 541 | { |
543 | if (J->parent == 0) { | 542 | if (J->parent == 0 && J->exitno == 0) { |
544 | if (pc == J->startpc && J->framedepth + J->retdepth == 0) { | 543 | if (pc == J->startpc && J->framedepth + J->retdepth == 0) { |
545 | /* Same loop? */ | 544 | /* Same loop? */ |
546 | if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */ | 545 | if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */ |
547 | lj_trace_err(J, LJ_TRERR_LLEAVE); | 546 | lj_trace_err(J, LJ_TRERR_LLEAVE); |
548 | rec_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping root trace. */ | 547 | lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */ |
549 | } else if (ev != LOOPEV_LEAVE) { /* Entering inner loop? */ | 548 | } else if (ev != LOOPEV_LEAVE) { /* Entering inner loop? */ |
550 | /* It's usually better to abort here and wait until the inner loop | 549 | /* It's usually better to abort here and wait until the inner loop |
551 | ** is traced. But if the inner loop repeatedly didn't loop back, | 550 | ** is traced. But if the inner loop repeatedly didn't loop back, |
@@ -570,15 +569,15 @@ static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) | |||
570 | /* Handle the case when an already compiled loop op is hit. */ | 569 | /* Handle the case when an already compiled loop op is hit. */ |
571 | static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev) | 570 | static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev) |
572 | { | 571 | { |
573 | if (J->parent == 0) { /* Root trace hit an inner loop. */ | 572 | if (J->parent == 0 && J->exitno == 0) { /* Root trace hit an inner loop. */ |
574 | /* Better let the inner loop spawn a side trace back here. */ | 573 | /* Better let the inner loop spawn a side trace back here. */ |
575 | lj_trace_err(J, LJ_TRERR_LINNER); | 574 | lj_trace_err(J, LJ_TRERR_LINNER); |
576 | } else if (ev != LOOPEV_LEAVE) { /* Side trace enters a compiled loop. */ | 575 | } else if (ev != LOOPEV_LEAVE) { /* Side trace enters a compiled loop. */ |
577 | J->instunroll = 0; /* Cannot continue across a compiled loop op. */ | 576 | J->instunroll = 0; /* Cannot continue across a compiled loop op. */ |
578 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) | 577 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) |
579 | rec_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Form an extra loop. */ | 578 | lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Form extra loop. */ |
580 | else | 579 | else |
581 | rec_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the loop. */ | 580 | lj_record_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the loop. */ |
582 | } /* Side trace continues across a loop that's left or not entered. */ | 581 | } /* Side trace continues across a loop that's left or not entered. */ |
583 | } | 582 | } |
584 | 583 | ||
@@ -643,6 +642,18 @@ static TRef rec_call_specialize(jit_State *J, GCfunc *fn, TRef tr) | |||
643 | (void)lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); /* Prevent GC of proto. */ | 642 | (void)lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); /* Prevent GC of proto. */ |
644 | return tr; | 643 | return tr; |
645 | } | 644 | } |
645 | } else { | ||
646 | /* Don't specialize to non-monomorphic builtins. */ | ||
647 | switch (fn->c.ffid) { | ||
648 | case FF_coroutine_wrap_aux: | ||
649 | case FF_string_gmatch_aux: | ||
650 | /* NYI: io_file_iter doesn't have an ffid, yet. */ | ||
651 | /* NYI: specialize to ffid? Not strictly necessary, trace will stop. */ | ||
652 | return tr; | ||
653 | default: | ||
654 | /* NYI: don't specialize to non-monomorphic C functions. */ | ||
655 | break; | ||
656 | } | ||
646 | } | 657 | } |
647 | /* Otherwise specialize to the function (closure) value itself. */ | 658 | /* Otherwise specialize to the function (closure) value itself. */ |
648 | kfunc = lj_ir_kfunc(J, fn); | 659 | kfunc = lj_ir_kfunc(J, fn); |
@@ -750,12 +761,13 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
750 | /* Return to lower frame via interpreter for unhandled cases. */ | 761 | /* Return to lower frame via interpreter for unhandled cases. */ |
751 | if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && | 762 | if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && |
752 | (!frame_islua(frame) || | 763 | (!frame_islua(frame) || |
753 | (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))))) { | 764 | (J->parent == 0 && J->exitno == 0 && |
765 | !bc_isret(bc_op(J->cur.startins))))) { | ||
754 | /* NYI: specialize to frame type and return directly, not via RET*. */ | 766 | /* NYI: specialize to frame type and return directly, not via RET*. */ |
755 | for (i = -1; i < (ptrdiff_t)rbase; i++) | 767 | for (i = -1; i < (ptrdiff_t)rbase; i++) |
756 | J->base[i] = 0; /* Purge dead slots. */ | 768 | J->base[i] = 0; /* Purge dead slots. */ |
757 | J->maxslot = rbase + (BCReg)gotresults; | 769 | J->maxslot = rbase + (BCReg)gotresults; |
758 | rec_stop(J, LJ_TRLINK_RETURN, 0); /* Return to interpreter. */ | 770 | lj_record_stop(J, LJ_TRLINK_RETURN, 0); /* Return to interpreter. */ |
759 | return; | 771 | return; |
760 | } | 772 | } |
761 | if (frame_isvarg(frame)) { | 773 | if (frame_isvarg(frame)) { |
@@ -779,7 +791,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
779 | if (check_downrec_unroll(J, pt)) { | 791 | if (check_downrec_unroll(J, pt)) { |
780 | J->maxslot = (BCReg)(rbase + gotresults); | 792 | J->maxslot = (BCReg)(rbase + gotresults); |
781 | lj_snap_purge(J); | 793 | lj_snap_purge(J); |
782 | rec_stop(J, LJ_TRLINK_DOWNREC, J->cur.traceno); /* Down-recursion. */ | 794 | lj_record_stop(J, LJ_TRLINK_DOWNREC, J->cur.traceno); /* Down-rec. */ |
783 | return; | 795 | return; |
784 | } | 796 | } |
785 | lj_snap_add(J); | 797 | lj_snap_add(J); |
@@ -792,7 +804,8 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
792 | lua_assert(J->baseslot > cbase+1); | 804 | lua_assert(J->baseslot > cbase+1); |
793 | J->baseslot -= cbase+1; | 805 | J->baseslot -= cbase+1; |
794 | J->base -= cbase+1; | 806 | J->base -= cbase+1; |
795 | } else if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) { | 807 | } else if (J->parent == 0 && J->exitno == 0 && |
808 | !bc_isret(bc_op(J->cur.startins))) { | ||
796 | /* Return to lower frame would leave the loop in a root trace. */ | 809 | /* Return to lower frame would leave the loop in a root trace. */ |
797 | lj_trace_err(J, LJ_TRERR_LLEAVE); | 810 | lj_trace_err(J, LJ_TRERR_LLEAVE); |
798 | } else { /* Return to lower frame. Guard for the target we return to. */ | 811 | } else { /* Return to lower frame. Guard for the target we return to. */ |
@@ -1480,9 +1493,9 @@ static void check_call_unroll(jit_State *J, TraceNo lnk) | |||
1480 | if (count + J->tailcalled > J->param[JIT_P_recunroll]) { | 1493 | if (count + J->tailcalled > J->param[JIT_P_recunroll]) { |
1481 | J->pc++; | 1494 | J->pc++; |
1482 | if (J->framedepth + J->retdepth == 0) | 1495 | if (J->framedepth + J->retdepth == 0) |
1483 | rec_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Tail-recursion. */ | 1496 | lj_record_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Tail-rec. */ |
1484 | else | 1497 | else |
1485 | rec_stop(J, LJ_TRLINK_UPREC, J->cur.traceno); /* Up-recursion. */ | 1498 | lj_record_stop(J, LJ_TRLINK_UPREC, J->cur.traceno); /* Up-recursion. */ |
1486 | } | 1499 | } |
1487 | } else { | 1500 | } else { |
1488 | if (count > J->param[JIT_P_callunroll]) { | 1501 | if (count > J->param[JIT_P_callunroll]) { |
@@ -1556,9 +1569,9 @@ static void rec_func_jit(jit_State *J, TraceNo lnk) | |||
1556 | } | 1569 | } |
1557 | J->instunroll = 0; /* Cannot continue across a compiled function. */ | 1570 | J->instunroll = 0; /* Cannot continue across a compiled function. */ |
1558 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) | 1571 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) |
1559 | rec_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Extra tail-recursion. */ | 1572 | lj_record_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Extra tail-rec. */ |
1560 | else | 1573 | else |
1561 | rec_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the function. */ | 1574 | lj_record_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the function. */ |
1562 | } | 1575 | } |
1563 | 1576 | ||
1564 | /* -- Vararg handling ----------------------------------------------------- */ | 1577 | /* -- Vararg handling ----------------------------------------------------- */ |
@@ -2165,7 +2178,7 @@ void lj_record_ins(jit_State *J) | |||
2165 | case BC_JFORI: | 2178 | case BC_JFORI: |
2166 | lua_assert(bc_op(pc[(ptrdiff_t)rc-BCBIAS_J]) == BC_JFORL); | 2179 | lua_assert(bc_op(pc[(ptrdiff_t)rc-BCBIAS_J]) == BC_JFORL); |
2167 | if (rec_for(J, pc, 0) != LOOPEV_LEAVE) /* Link to existing loop. */ | 2180 | if (rec_for(J, pc, 0) != LOOPEV_LEAVE) /* Link to existing loop. */ |
2168 | rec_stop(J, LJ_TRLINK_ROOT, bc_d(pc[(ptrdiff_t)rc-BCBIAS_J])); | 2181 | lj_record_stop(J, LJ_TRLINK_ROOT, bc_d(pc[(ptrdiff_t)rc-BCBIAS_J])); |
2169 | /* Continue tracing if the loop is not entered. */ | 2182 | /* Continue tracing if the loop is not entered. */ |
2170 | break; | 2183 | break; |
2171 | 2184 | ||
@@ -2299,6 +2312,12 @@ static const BCIns *rec_setup_root(jit_State *J) | |||
2299 | J->maxslot = J->pt->numparams; | 2312 | J->maxslot = J->pt->numparams; |
2300 | pc++; | 2313 | pc++; |
2301 | break; | 2314 | break; |
2315 | case BC_CALLM: | ||
2316 | case BC_CALL: | ||
2317 | case BC_ITERC: | ||
2318 | /* No bytecode range check for stitched traces. */ | ||
2319 | pc++; | ||
2320 | break; | ||
2302 | default: | 2321 | default: |
2303 | lua_assert(0); | 2322 | lua_assert(0); |
2304 | break; | 2323 | break; |
@@ -2366,7 +2385,7 @@ void lj_record_setup(jit_State *J) | |||
2366 | if (traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] || | 2385 | if (traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] || |
2367 | T->snap[J->exitno].count >= J->param[JIT_P_hotexit] + | 2386 | T->snap[J->exitno].count >= J->param[JIT_P_hotexit] + |
2368 | J->param[JIT_P_tryside]) { | 2387 | J->param[JIT_P_tryside]) { |
2369 | rec_stop(J, LJ_TRLINK_INTERP, 0); | 2388 | lj_record_stop(J, LJ_TRLINK_INTERP, 0); |
2370 | } | 2389 | } |
2371 | } else { /* Root trace. */ | 2390 | } else { /* Root trace. */ |
2372 | J->cur.root = 0; | 2391 | J->cur.root = 0; |
@@ -2378,6 +2397,8 @@ void lj_record_setup(jit_State *J) | |||
2378 | lj_snap_add(J); | 2397 | lj_snap_add(J); |
2379 | if (bc_op(J->cur.startins) == BC_FORL) | 2398 | if (bc_op(J->cur.startins) == BC_FORL) |
2380 | rec_for_loop(J, J->pc-1, &J->scev, 1); | 2399 | rec_for_loop(J, J->pc-1, &J->scev, 1); |
2400 | else if (bc_op(J->cur.startins) == BC_ITERC) | ||
2401 | J->startpc = NULL; | ||
2381 | if (1 + J->pt->framesize >= LJ_MAX_JSLOTS) | 2402 | if (1 + J->pt->framesize >= LJ_MAX_JSLOTS) |
2382 | lj_trace_err(J, LJ_TRERR_STACKOV); | 2403 | lj_trace_err(J, LJ_TRERR_STACKOV); |
2383 | } | 2404 | } |