aboutsummaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_record.c')
-rw-r--r--src/lj_record.c57
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. */
236static void rec_stop(jit_State *J, TraceLink linktype, TraceNo lnk) 236void 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)
501static LoopEvent rec_iterl(jit_State *J, const BCIns iterins) 501static 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. */
541static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) 540static 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. */
571static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev) 570static 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 }