diff options
Diffstat (limited to 'src/lj_record.c')
-rw-r--r-- | src/lj_record.c | 656 |
1 files changed, 521 insertions, 135 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index 69822f54..8eec0071 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" |
@@ -48,7 +51,7 @@ static void rec_check_ir(jit_State *J) | |||
48 | { | 51 | { |
49 | IRRef i, nins = J->cur.nins, nk = J->cur.nk; | 52 | IRRef i, nins = J->cur.nins, nk = J->cur.nk; |
50 | lua_assert(nk <= REF_BIAS && nins >= REF_BIAS && nins < 65536); | 53 | lua_assert(nk <= REF_BIAS && nins >= REF_BIAS && nins < 65536); |
51 | for (i = nins-1; i >= nk; i--) { | 54 | for (i = nk; i < nins; i++) { |
52 | IRIns *ir = IR(i); | 55 | IRIns *ir = IR(i); |
53 | uint32_t mode = lj_ir_mode[ir->o]; | 56 | uint32_t mode = lj_ir_mode[ir->o]; |
54 | IRRef op1 = ir->op1; | 57 | IRRef op1 = ir->op1; |
@@ -58,7 +61,10 @@ static void rec_check_ir(jit_State *J) | |||
58 | case IRMref: lua_assert(op1 >= nk); | 61 | case IRMref: lua_assert(op1 >= nk); |
59 | lua_assert(i >= REF_BIAS ? op1 < i : op1 > i); break; | 62 | lua_assert(i >= REF_BIAS ? op1 < i : op1 > i); break; |
60 | case IRMlit: break; | 63 | case IRMlit: break; |
61 | case IRMcst: lua_assert(i < REF_BIAS); continue; | 64 | case IRMcst: lua_assert(i < REF_BIAS); |
65 | if (irt_is64(ir->t) && ir->o != IR_KNULL) | ||
66 | i++; | ||
67 | continue; | ||
62 | } | 68 | } |
63 | switch (irm_op2(mode)) { | 69 | switch (irm_op2(mode)) { |
64 | case IRMnone: lua_assert(op2 == 0); break; | 70 | case IRMnone: lua_assert(op2 == 0); break; |
@@ -81,30 +87,48 @@ static void rec_check_slots(jit_State *J) | |||
81 | BCReg s, nslots = J->baseslot + J->maxslot; | 87 | BCReg s, nslots = J->baseslot + J->maxslot; |
82 | int32_t depth = 0; | 88 | int32_t depth = 0; |
83 | cTValue *base = J->L->base - J->baseslot; | 89 | cTValue *base = J->L->base - J->baseslot; |
84 | lua_assert(J->baseslot >= 1); | 90 | lua_assert(J->baseslot >= 1+LJ_FR2); |
85 | lua_assert(J->baseslot == 1 || (J->slot[J->baseslot-1] & TREF_FRAME)); | 91 | lua_assert(J->baseslot == 1+LJ_FR2 || (J->slot[J->baseslot-1] & TREF_FRAME)); |
86 | lua_assert(nslots <= LJ_MAX_JSLOTS); | 92 | lua_assert(nslots <= LJ_MAX_JSLOTS); |
87 | for (s = 0; s < nslots; s++) { | 93 | for (s = 0; s < nslots; s++) { |
88 | TRef tr = J->slot[s]; | 94 | TRef tr = J->slot[s]; |
89 | if (tr) { | 95 | if (tr) { |
90 | cTValue *tv = &base[s]; | 96 | cTValue *tv = &base[s]; |
91 | IRRef ref = tref_ref(tr); | 97 | IRRef ref = tref_ref(tr); |
92 | IRIns *ir; | 98 | IRIns *ir = NULL; /* Silence compiler. */ |
93 | lua_assert(ref >= J->cur.nk && ref < J->cur.nins); | 99 | if (!LJ_FR2 || ref || !(tr & (TREF_FRAME | TREF_CONT))) { |
94 | ir = IR(ref); | 100 | lua_assert(ref >= J->cur.nk && ref < J->cur.nins); |
95 | lua_assert(irt_t(ir->t) == tref_t(tr)); | 101 | ir = IR(ref); |
102 | lua_assert(irt_t(ir->t) == tref_t(tr)); | ||
103 | } | ||
96 | if (s == 0) { | 104 | if (s == 0) { |
97 | lua_assert(tref_isfunc(tr)); | 105 | lua_assert(tref_isfunc(tr)); |
106 | #if LJ_FR2 | ||
107 | } else if (s == 1) { | ||
108 | lua_assert((tr & ~TREF_FRAME) == 0); | ||
109 | #endif | ||
98 | } else if ((tr & TREF_FRAME)) { | 110 | } else if ((tr & TREF_FRAME)) { |
99 | GCfunc *fn = gco2func(frame_gc(tv)); | 111 | GCfunc *fn = gco2func(frame_gc(tv)); |
100 | BCReg delta = (BCReg)(tv - frame_prev(tv)); | 112 | BCReg delta = (BCReg)(tv - frame_prev(tv)); |
113 | #if LJ_FR2 | ||
114 | if (ref) | ||
115 | lua_assert(ir_knum(ir)->u64 == tv->u64); | ||
116 | tr = J->slot[s-1]; | ||
117 | ir = IR(tref_ref(tr)); | ||
118 | #endif | ||
101 | lua_assert(tref_isfunc(tr)); | 119 | lua_assert(tref_isfunc(tr)); |
102 | if (tref_isk(tr)) lua_assert(fn == ir_kfunc(ir)); | 120 | if (tref_isk(tr)) lua_assert(fn == ir_kfunc(ir)); |
103 | lua_assert(s > delta ? (J->slot[s-delta] & TREF_FRAME) : (s == delta)); | 121 | lua_assert(s > delta + LJ_FR2 ? (J->slot[s-delta] & TREF_FRAME) |
122 | : (s == delta + LJ_FR2)); | ||
104 | depth++; | 123 | depth++; |
105 | } else if ((tr & TREF_CONT)) { | 124 | } else if ((tr & TREF_CONT)) { |
125 | #if LJ_FR2 | ||
126 | if (ref) | ||
127 | lua_assert(ir_knum(ir)->u64 == tv->u64); | ||
128 | #else | ||
106 | lua_assert(ir_kptr(ir) == gcrefp(tv->gcr, void)); | 129 | lua_assert(ir_kptr(ir) == gcrefp(tv->gcr, void)); |
107 | lua_assert((J->slot[s+1] & TREF_FRAME)); | 130 | #endif |
131 | lua_assert((J->slot[s+1+LJ_FR2] & TREF_FRAME)); | ||
108 | depth++; | 132 | depth++; |
109 | } else { | 133 | } else { |
110 | if (tvisnumber(tv)) | 134 | if (tvisnumber(tv)) |
@@ -156,10 +180,10 @@ static TRef sload(jit_State *J, int32_t slot) | |||
156 | /* Get TRef for current function. */ | 180 | /* Get TRef for current function. */ |
157 | static TRef getcurrf(jit_State *J) | 181 | static TRef getcurrf(jit_State *J) |
158 | { | 182 | { |
159 | if (J->base[-1]) | 183 | if (J->base[-1-LJ_FR2]) |
160 | return J->base[-1]; | 184 | return J->base[-1-LJ_FR2]; |
161 | lua_assert(J->baseslot == 1); | 185 | lua_assert(J->baseslot == 1+LJ_FR2); |
162 | return sloadt(J, -1, IRT_FUNC, IRSLOAD_READONLY); | 186 | return sloadt(J, -1-LJ_FR2, IRT_FUNC, IRSLOAD_READONLY); |
163 | } | 187 | } |
164 | 188 | ||
165 | /* Compare for raw object equality. | 189 | /* Compare for raw object equality. |
@@ -230,8 +254,12 @@ static void canonicalize_slots(jit_State *J) | |||
230 | } | 254 | } |
231 | 255 | ||
232 | /* Stop recording. */ | 256 | /* Stop recording. */ |
233 | static void rec_stop(jit_State *J, TraceLink linktype, TraceNo lnk) | 257 | void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk) |
234 | { | 258 | { |
259 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
260 | if (J->retryrec) | ||
261 | lj_trace_err(J, LJ_TRERR_RETRY); | ||
262 | #endif | ||
235 | lj_trace_end(J); | 263 | lj_trace_end(J); |
236 | J->cur.linktype = (uint8_t)linktype; | 264 | J->cur.linktype = (uint8_t)linktype; |
237 | J->cur.link = (uint16_t)lnk; | 265 | J->cur.link = (uint16_t)lnk; |
@@ -499,8 +527,7 @@ static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) | |||
499 | static LoopEvent rec_iterl(jit_State *J, const BCIns iterins) | 527 | static LoopEvent rec_iterl(jit_State *J, const BCIns iterins) |
500 | { | 528 | { |
501 | BCReg ra = bc_a(iterins); | 529 | BCReg ra = bc_a(iterins); |
502 | lua_assert(J->base[ra] != 0); | 530 | if (!tref_isnil(getslot(J, ra))) { /* Looping back? */ |
503 | if (!tref_isnil(J->base[ra])) { /* Looping back? */ | ||
504 | J->base[ra-1] = J->base[ra]; /* Copy result of ITERC to control var. */ | 531 | J->base[ra-1] = J->base[ra]; /* Copy result of ITERC to control var. */ |
505 | J->maxslot = ra-1+bc_b(J->pc[-1]); | 532 | J->maxslot = ra-1+bc_b(J->pc[-1]); |
506 | J->pc += bc_j(iterins)+1; | 533 | J->pc += bc_j(iterins)+1; |
@@ -538,12 +565,12 @@ static int innerloopleft(jit_State *J, const BCIns *pc) | |||
538 | /* Handle the case when an interpreted loop op is hit. */ | 565 | /* Handle the case when an interpreted loop op is hit. */ |
539 | static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) | 566 | static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) |
540 | { | 567 | { |
541 | if (J->parent == 0) { | 568 | if (J->parent == 0 && J->exitno == 0) { |
542 | if (pc == J->startpc && J->framedepth + J->retdepth == 0) { | 569 | if (pc == J->startpc && J->framedepth + J->retdepth == 0) { |
543 | /* Same loop? */ | 570 | /* Same loop? */ |
544 | if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */ | 571 | if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */ |
545 | lj_trace_err(J, LJ_TRERR_LLEAVE); | 572 | lj_trace_err(J, LJ_TRERR_LLEAVE); |
546 | rec_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping root trace. */ | 573 | lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */ |
547 | } else if (ev != LOOPEV_LEAVE) { /* Entering inner loop? */ | 574 | } else if (ev != LOOPEV_LEAVE) { /* Entering inner loop? */ |
548 | /* It's usually better to abort here and wait until the inner loop | 575 | /* It's usually better to abort here and wait until the inner loop |
549 | ** is traced. But if the inner loop repeatedly didn't loop back, | 576 | ** is traced. But if the inner loop repeatedly didn't loop back, |
@@ -568,18 +595,64 @@ static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) | |||
568 | /* Handle the case when an already compiled loop op is hit. */ | 595 | /* Handle the case when an already compiled loop op is hit. */ |
569 | static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev) | 596 | static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev) |
570 | { | 597 | { |
571 | if (J->parent == 0) { /* Root trace hit an inner loop. */ | 598 | if (J->parent == 0 && J->exitno == 0) { /* Root trace hit an inner loop. */ |
572 | /* Better let the inner loop spawn a side trace back here. */ | 599 | /* Better let the inner loop spawn a side trace back here. */ |
573 | lj_trace_err(J, LJ_TRERR_LINNER); | 600 | lj_trace_err(J, LJ_TRERR_LINNER); |
574 | } else if (ev != LOOPEV_LEAVE) { /* Side trace enters a compiled loop. */ | 601 | } else if (ev != LOOPEV_LEAVE) { /* Side trace enters a compiled loop. */ |
575 | J->instunroll = 0; /* Cannot continue across a compiled loop op. */ | 602 | J->instunroll = 0; /* Cannot continue across a compiled loop op. */ |
576 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) | 603 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) |
577 | rec_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Form an extra loop. */ | 604 | lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Form extra loop. */ |
578 | else | 605 | else |
579 | rec_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the loop. */ | 606 | lj_record_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the loop. */ |
580 | } /* Side trace continues across a loop that's left or not entered. */ | 607 | } /* Side trace continues across a loop that's left or not entered. */ |
581 | } | 608 | } |
582 | 609 | ||
610 | /* -- Record profiler hook checks ----------------------------------------- */ | ||
611 | |||
612 | #if LJ_HASPROFILE | ||
613 | |||
614 | /* Need to insert profiler hook check? */ | ||
615 | static int rec_profile_need(jit_State *J, GCproto *pt, const BCIns *pc) | ||
616 | { | ||
617 | GCproto *ppt; | ||
618 | lua_assert(J->prof_mode == 'f' || J->prof_mode == 'l'); | ||
619 | if (!pt) | ||
620 | return 0; | ||
621 | ppt = J->prev_pt; | ||
622 | J->prev_pt = pt; | ||
623 | if (pt != ppt && ppt) { | ||
624 | J->prev_line = -1; | ||
625 | return 1; | ||
626 | } | ||
627 | if (J->prof_mode == 'l') { | ||
628 | BCLine line = lj_debug_line(pt, proto_bcpos(pt, pc)); | ||
629 | BCLine pline = J->prev_line; | ||
630 | J->prev_line = line; | ||
631 | if (pline != line) | ||
632 | return 1; | ||
633 | } | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static void rec_profile_ins(jit_State *J, const BCIns *pc) | ||
638 | { | ||
639 | if (J->prof_mode && rec_profile_need(J, J->pt, pc)) { | ||
640 | emitir(IRTG(IR_PROF, IRT_NIL), 0, 0); | ||
641 | lj_snap_add(J); | ||
642 | } | ||
643 | } | ||
644 | |||
645 | static void rec_profile_ret(jit_State *J) | ||
646 | { | ||
647 | if (J->prof_mode == 'f') { | ||
648 | emitir(IRTG(IR_PROF, IRT_NIL), 0, 0); | ||
649 | J->prev_pt = NULL; | ||
650 | lj_snap_add(J); | ||
651 | } | ||
652 | } | ||
653 | |||
654 | #endif | ||
655 | |||
583 | /* -- Record calls and returns -------------------------------------------- */ | 656 | /* -- Record calls and returns -------------------------------------------- */ |
584 | 657 | ||
585 | /* Specialize to the runtime value of the called function or its prototype. */ | 658 | /* Specialize to the runtime value of the called function or its prototype. */ |
@@ -590,11 +663,26 @@ static TRef rec_call_specialize(jit_State *J, GCfunc *fn, TRef tr) | |||
590 | GCproto *pt = funcproto(fn); | 663 | GCproto *pt = funcproto(fn); |
591 | /* Too many closures created? Probably not a monomorphic function. */ | 664 | /* Too many closures created? Probably not a monomorphic function. */ |
592 | if (pt->flags >= PROTO_CLC_POLY) { /* Specialize to prototype instead. */ | 665 | if (pt->flags >= PROTO_CLC_POLY) { /* Specialize to prototype instead. */ |
593 | TRef trpt = emitir(IRT(IR_FLOAD, IRT_P32), tr, IRFL_FUNC_PC); | 666 | TRef trpt = emitir(IRT(IR_FLOAD, IRT_PGC), tr, IRFL_FUNC_PC); |
594 | emitir(IRTG(IR_EQ, IRT_P32), trpt, lj_ir_kptr(J, proto_bc(pt))); | 667 | emitir(IRTG(IR_EQ, IRT_PGC), trpt, lj_ir_kptr(J, proto_bc(pt))); |
595 | (void)lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); /* Prevent GC of proto. */ | 668 | (void)lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); /* Prevent GC of proto. */ |
596 | return tr; | 669 | return tr; |
597 | } | 670 | } |
671 | } else { | ||
672 | /* Don't specialize to non-monomorphic builtins. */ | ||
673 | switch (fn->c.ffid) { | ||
674 | case FF_coroutine_wrap_aux: | ||
675 | case FF_string_gmatch_aux: | ||
676 | /* NYI: io_file_iter doesn't have an ffid, yet. */ | ||
677 | { /* Specialize to the ffid. */ | ||
678 | TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), tr, IRFL_FUNC_FFID); | ||
679 | emitir(IRTG(IR_EQ, IRT_INT), trid, lj_ir_kint(J, fn->c.ffid)); | ||
680 | } | ||
681 | return tr; | ||
682 | default: | ||
683 | /* NYI: don't specialize to non-monomorphic C functions. */ | ||
684 | break; | ||
685 | } | ||
598 | } | 686 | } |
599 | /* Otherwise specialize to the function (closure) value itself. */ | 687 | /* Otherwise specialize to the function (closure) value itself. */ |
600 | kfunc = lj_ir_kfunc(J, fn); | 688 | kfunc = lj_ir_kfunc(J, fn); |
@@ -607,21 +695,31 @@ static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs) | |||
607 | { | 695 | { |
608 | RecordIndex ix; | 696 | RecordIndex ix; |
609 | TValue *functv = &J->L->base[func]; | 697 | TValue *functv = &J->L->base[func]; |
610 | TRef *fbase = &J->base[func]; | 698 | TRef kfunc, *fbase = &J->base[func]; |
611 | ptrdiff_t i; | 699 | ptrdiff_t i; |
612 | for (i = 0; i <= nargs; i++) | 700 | (void)getslot(J, func); /* Ensure func has a reference. */ |
613 | (void)getslot(J, func+i); /* Ensure func and all args have a reference. */ | 701 | for (i = 1; i <= nargs; i++) |
702 | (void)getslot(J, func+LJ_FR2+i); /* Ensure all args have a reference. */ | ||
614 | if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */ | 703 | if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */ |
615 | ix.tab = fbase[0]; | 704 | ix.tab = fbase[0]; |
616 | copyTV(J->L, &ix.tabv, functv); | 705 | copyTV(J->L, &ix.tabv, functv); |
617 | if (!lj_record_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj)) | 706 | if (!lj_record_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj)) |
618 | lj_trace_err(J, LJ_TRERR_NOMM); | 707 | lj_trace_err(J, LJ_TRERR_NOMM); |
619 | for (i = ++nargs; i > 0; i--) /* Shift arguments up. */ | 708 | for (i = ++nargs; i > LJ_FR2; i--) /* Shift arguments up. */ |
620 | fbase[i] = fbase[i-1]; | 709 | fbase[i+LJ_FR2] = fbase[i+LJ_FR2-1]; |
710 | #if LJ_FR2 | ||
711 | fbase[2] = fbase[0]; | ||
712 | #endif | ||
621 | fbase[0] = ix.mobj; /* Replace function. */ | 713 | fbase[0] = ix.mobj; /* Replace function. */ |
622 | functv = &ix.mobjv; | 714 | functv = &ix.mobjv; |
623 | } | 715 | } |
624 | fbase[0] = TREF_FRAME | rec_call_specialize(J, funcV(functv), fbase[0]); | 716 | kfunc = rec_call_specialize(J, funcV(functv), fbase[0]); |
717 | #if LJ_FR2 | ||
718 | fbase[0] = kfunc; | ||
719 | fbase[1] = TREF_FRAME; | ||
720 | #else | ||
721 | fbase[0] = kfunc | TREF_FRAME; | ||
722 | #endif | ||
625 | J->maxslot = (BCReg)nargs; | 723 | J->maxslot = (BCReg)nargs; |
626 | } | 724 | } |
627 | 725 | ||
@@ -631,8 +729,8 @@ void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs) | |||
631 | rec_call_setup(J, func, nargs); | 729 | rec_call_setup(J, func, nargs); |
632 | /* Bump frame. */ | 730 | /* Bump frame. */ |
633 | J->framedepth++; | 731 | J->framedepth++; |
634 | J->base += func+1; | 732 | J->base += func+1+LJ_FR2; |
635 | J->baseslot += func+1; | 733 | J->baseslot += func+1+LJ_FR2; |
636 | if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS) | 734 | if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS) |
637 | lj_trace_err(J, LJ_TRERR_STACKOV); | 735 | lj_trace_err(J, LJ_TRERR_STACKOV); |
638 | } | 736 | } |
@@ -650,7 +748,9 @@ void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs) | |||
650 | func += cbase; | 748 | func += cbase; |
651 | } | 749 | } |
652 | /* Move func + args down. */ | 750 | /* Move func + args down. */ |
653 | memmove(&J->base[-1], &J->base[func], sizeof(TRef)*(J->maxslot+1)); | 751 | if (LJ_FR2 && J->baseslot == 2) |
752 | J->base[func+1] = TREF_FRAME; | ||
753 | memmove(&J->base[-1-LJ_FR2], &J->base[func], sizeof(TRef)*(J->maxslot+1+LJ_FR2)); | ||
654 | /* Note: the new TREF_FRAME is now at J->base[-1] (even for slot #0). */ | 754 | /* Note: the new TREF_FRAME is now at J->base[-1] (even for slot #0). */ |
655 | /* Tailcalls can form a loop, so count towards the loop unroll limit. */ | 755 | /* Tailcalls can form a loop, so count towards the loop unroll limit. */ |
656 | if (++J->tailcalled > J->loopunroll) | 756 | if (++J->tailcalled > J->loopunroll) |
@@ -680,6 +780,8 @@ static int check_downrec_unroll(jit_State *J, GCproto *pt) | |||
680 | return 0; | 780 | return 0; |
681 | } | 781 | } |
682 | 782 | ||
783 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot); | ||
784 | |||
683 | /* Record return. */ | 785 | /* Record return. */ |
684 | void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | 786 | void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) |
685 | { | 787 | { |
@@ -691,7 +793,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
691 | BCReg cbase = (BCReg)frame_delta(frame); | 793 | BCReg cbase = (BCReg)frame_delta(frame); |
692 | if (--J->framedepth <= 0) | 794 | if (--J->framedepth <= 0) |
693 | lj_trace_err(J, LJ_TRERR_NYIRETL); | 795 | lj_trace_err(J, LJ_TRERR_NYIRETL); |
694 | lua_assert(J->baseslot > 1); | 796 | lua_assert(J->baseslot > 1+LJ_FR2); |
695 | gotresults++; | 797 | gotresults++; |
696 | rbase += cbase; | 798 | rbase += cbase; |
697 | J->baseslot -= (BCReg)cbase; | 799 | J->baseslot -= (BCReg)cbase; |
@@ -702,19 +804,20 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
702 | /* Return to lower frame via interpreter for unhandled cases. */ | 804 | /* Return to lower frame via interpreter for unhandled cases. */ |
703 | if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && | 805 | if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && |
704 | (!frame_islua(frame) || | 806 | (!frame_islua(frame) || |
705 | (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))))) { | 807 | (J->parent == 0 && J->exitno == 0 && |
808 | !bc_isret(bc_op(J->cur.startins))))) { | ||
706 | /* NYI: specialize to frame type and return directly, not via RET*. */ | 809 | /* NYI: specialize to frame type and return directly, not via RET*. */ |
707 | for (i = 0; i < (ptrdiff_t)rbase; i++) | 810 | for (i = 0; i < (ptrdiff_t)rbase; i++) |
708 | J->base[i] = 0; /* Purge dead slots. */ | 811 | J->base[i] = 0; /* Purge dead slots. */ |
709 | J->maxslot = rbase + (BCReg)gotresults; | 812 | J->maxslot = rbase + (BCReg)gotresults; |
710 | rec_stop(J, LJ_TRLINK_RETURN, 0); /* Return to interpreter. */ | 813 | lj_record_stop(J, LJ_TRLINK_RETURN, 0); /* Return to interpreter. */ |
711 | return; | 814 | return; |
712 | } | 815 | } |
713 | if (frame_isvarg(frame)) { | 816 | if (frame_isvarg(frame)) { |
714 | BCReg cbase = (BCReg)frame_delta(frame); | 817 | BCReg cbase = (BCReg)frame_delta(frame); |
715 | if (--J->framedepth < 0) /* NYI: return of vararg func to lower frame. */ | 818 | if (--J->framedepth < 0) /* NYI: return of vararg func to lower frame. */ |
716 | lj_trace_err(J, LJ_TRERR_NYIRETL); | 819 | lj_trace_err(J, LJ_TRERR_NYIRETL); |
717 | lua_assert(J->baseslot > 1); | 820 | lua_assert(J->baseslot > 1+LJ_FR2); |
718 | rbase += cbase; | 821 | rbase += cbase; |
719 | J->baseslot -= (BCReg)cbase; | 822 | J->baseslot -= (BCReg)cbase; |
720 | J->base -= cbase; | 823 | J->base -= cbase; |
@@ -724,27 +827,28 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
724 | BCIns callins = *(frame_pc(frame)-1); | 827 | BCIns callins = *(frame_pc(frame)-1); |
725 | ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults; | 828 | ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults; |
726 | BCReg cbase = bc_a(callins); | 829 | BCReg cbase = bc_a(callins); |
727 | GCproto *pt = funcproto(frame_func(frame - (cbase+1))); | 830 | GCproto *pt = funcproto(frame_func(frame - (cbase+1+LJ_FR2))); |
728 | if ((pt->flags & PROTO_NOJIT)) | 831 | if ((pt->flags & PROTO_NOJIT)) |
729 | lj_trace_err(J, LJ_TRERR_CJITOFF); | 832 | lj_trace_err(J, LJ_TRERR_CJITOFF); |
730 | if (J->framedepth == 0 && J->pt && frame == J->L->base - 1) { | 833 | if (J->framedepth == 0 && J->pt && frame == J->L->base - 1) { |
731 | if (check_downrec_unroll(J, pt)) { | 834 | if (check_downrec_unroll(J, pt)) { |
732 | J->maxslot = (BCReg)(rbase + gotresults); | 835 | J->maxslot = (BCReg)(rbase + gotresults); |
733 | lj_snap_purge(J); | 836 | lj_snap_purge(J); |
734 | rec_stop(J, LJ_TRLINK_DOWNREC, J->cur.traceno); /* Down-recursion. */ | 837 | lj_record_stop(J, LJ_TRLINK_DOWNREC, J->cur.traceno); /* Down-rec. */ |
735 | return; | 838 | return; |
736 | } | 839 | } |
737 | lj_snap_add(J); | 840 | lj_snap_add(J); |
738 | } | 841 | } |
739 | for (i = 0; i < nresults; i++) /* Adjust results. */ | 842 | for (i = 0; i < nresults; i++) /* Adjust results. */ |
740 | J->base[i-1] = i < gotresults ? J->base[rbase+i] : TREF_NIL; | 843 | J->base[i-1-LJ_FR2] = i < gotresults ? J->base[rbase+i] : TREF_NIL; |
741 | J->maxslot = cbase+(BCReg)nresults; | 844 | J->maxslot = cbase+(BCReg)nresults; |
742 | if (J->framedepth > 0) { /* Return to a frame that is part of the trace. */ | 845 | if (J->framedepth > 0) { /* Return to a frame that is part of the trace. */ |
743 | J->framedepth--; | 846 | J->framedepth--; |
744 | lua_assert(J->baseslot > cbase+1); | 847 | lua_assert(J->baseslot > cbase+1+LJ_FR2); |
745 | J->baseslot -= cbase+1; | 848 | J->baseslot -= cbase+1+LJ_FR2; |
746 | J->base -= cbase+1; | 849 | J->base -= cbase+1+LJ_FR2; |
747 | } else if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) { | 850 | } else if (J->parent == 0 && J->exitno == 0 && |
851 | !bc_isret(bc_op(J->cur.startins))) { | ||
748 | /* Return to lower frame would leave the loop in a root trace. */ | 852 | /* Return to lower frame would leave the loop in a root trace. */ |
749 | lj_trace_err(J, LJ_TRERR_LLEAVE); | 853 | lj_trace_err(J, LJ_TRERR_LLEAVE); |
750 | } else if (J->needsnap) { /* Tailcalled to ff with side-effects. */ | 854 | } else if (J->needsnap) { /* Tailcalled to ff with side-effects. */ |
@@ -752,13 +856,13 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
752 | } else { /* Return to lower frame. Guard for the target we return to. */ | 856 | } else { /* Return to lower frame. Guard for the target we return to. */ |
753 | TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); | 857 | TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); |
754 | TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame)); | 858 | TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame)); |
755 | emitir(IRTG(IR_RETF, IRT_P32), trpt, trpc); | 859 | emitir(IRTG(IR_RETF, IRT_PGC), trpt, trpc); |
756 | J->retdepth++; | 860 | J->retdepth++; |
757 | J->needsnap = 1; | 861 | J->needsnap = 1; |
758 | lua_assert(J->baseslot == 1); | 862 | lua_assert(J->baseslot == 1+LJ_FR2); |
759 | /* Shift result slots up and clear the slots of the new frame below. */ | 863 | /* Shift result slots up and clear the slots of the new frame below. */ |
760 | memmove(J->base + cbase, J->base-1, sizeof(TRef)*nresults); | 864 | memmove(J->base + cbase, J->base-1-LJ_FR2, sizeof(TRef)*nresults); |
761 | memset(J->base-1, 0, sizeof(TRef)*(cbase+1)); | 865 | memset(J->base-1-LJ_FR2, 0, sizeof(TRef)*(cbase+1+LJ_FR2)); |
762 | } | 866 | } |
763 | } else if (frame_iscont(frame)) { /* Return to continuation frame. */ | 867 | } else if (frame_iscont(frame)) { /* Return to continuation frame. */ |
764 | ASMFunction cont = frame_contf(frame); | 868 | ASMFunction cont = frame_contf(frame); |
@@ -767,16 +871,40 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
767 | lj_trace_err(J, LJ_TRERR_NYIRETL); | 871 | lj_trace_err(J, LJ_TRERR_NYIRETL); |
768 | J->baseslot -= (BCReg)cbase; | 872 | J->baseslot -= (BCReg)cbase; |
769 | J->base -= cbase; | 873 | J->base -= cbase; |
770 | J->maxslot = cbase-2; | 874 | J->maxslot = cbase-(2<<LJ_FR2); |
771 | if (cont == lj_cont_ra) { | 875 | if (cont == lj_cont_ra) { |
772 | /* Copy result to destination slot. */ | 876 | /* Copy result to destination slot. */ |
773 | BCReg dst = bc_a(*(frame_contpc(frame)-1)); | 877 | BCReg dst = bc_a(*(frame_contpc(frame)-1)); |
774 | J->base[dst] = gotresults ? J->base[cbase+rbase] : TREF_NIL; | 878 | J->base[dst] = gotresults ? J->base[cbase+rbase] : TREF_NIL; |
775 | if (dst >= J->maxslot) J->maxslot = dst+1; | 879 | if (dst >= J->maxslot) { |
880 | J->maxslot = dst+1; | ||
881 | } | ||
776 | } else if (cont == lj_cont_nop) { | 882 | } else if (cont == lj_cont_nop) { |
777 | /* Nothing to do here. */ | 883 | /* Nothing to do here. */ |
778 | } else if (cont == lj_cont_cat) { | 884 | } else if (cont == lj_cont_cat) { |
779 | lua_assert(0); | 885 | BCReg bslot = bc_b(*(frame_contpc(frame)-1)); |
886 | TRef tr = gotresults ? J->base[cbase+rbase] : TREF_NIL; | ||
887 | if (bslot != J->maxslot) { /* Concatenate the remainder. */ | ||
888 | TValue *b = J->L->base, save; /* Simulate lower frame and result. */ | ||
889 | J->base[J->maxslot] = tr; | ||
890 | copyTV(J->L, &save, b-(2<<LJ_FR2)); | ||
891 | if (gotresults) | ||
892 | copyTV(J->L, b-(2<<LJ_FR2), b+rbase); | ||
893 | else | ||
894 | setnilV(b-(2<<LJ_FR2)); | ||
895 | J->L->base = b - cbase; | ||
896 | tr = rec_cat(J, bslot, cbase-(2<<LJ_FR2)); | ||
897 | b = J->L->base + cbase; /* Undo. */ | ||
898 | J->L->base = b; | ||
899 | copyTV(J->L, b-(2<<LJ_FR2), &save); | ||
900 | } | ||
901 | if (tr) { /* Store final result. */ | ||
902 | BCReg dst = bc_a(*(frame_contpc(frame)-1)); | ||
903 | J->base[dst] = tr; | ||
904 | if (dst >= J->maxslot) { | ||
905 | J->maxslot = dst+1; | ||
906 | } | ||
907 | } /* Otherwise continue with another __concat call. */ | ||
780 | } else { | 908 | } else { |
781 | /* Result type already specialized. */ | 909 | /* Result type already specialized. */ |
782 | lua_assert(cont == lj_cont_condf || cont == lj_cont_condt); | 910 | lua_assert(cont == lj_cont_condf || cont == lj_cont_condt); |
@@ -784,7 +912,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
784 | } else { | 912 | } else { |
785 | lj_trace_err(J, LJ_TRERR_NYIRETL); /* NYI: handle return to C frame. */ | 913 | lj_trace_err(J, LJ_TRERR_NYIRETL); /* NYI: handle return to C frame. */ |
786 | } | 914 | } |
787 | lua_assert(J->baseslot >= 1); | 915 | lua_assert(J->baseslot >= 1+LJ_FR2); |
788 | } | 916 | } |
789 | 917 | ||
790 | /* -- Metamethod handling ------------------------------------------------- */ | 918 | /* -- Metamethod handling ------------------------------------------------- */ |
@@ -792,19 +920,17 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
792 | /* Prepare to record call to metamethod. */ | 920 | /* Prepare to record call to metamethod. */ |
793 | static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) | 921 | static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) |
794 | { | 922 | { |
795 | BCReg s, top = curr_proto(J->L)->framesize; | 923 | BCReg s, top = cont == lj_cont_cat ? J->maxslot : curr_proto(J->L)->framesize; |
796 | TRef trcont; | 924 | #if LJ_FR2 |
797 | setcont(&J->L->base[top], cont); | 925 | J->base[top] = lj_ir_k64(J, IR_KNUM, u64ptr(contptr(cont))); |
798 | #if LJ_64 | 926 | J->base[top+1] = TREF_CONT; |
799 | trcont = lj_ir_kptr(J, (void *)((int64_t)cont - (int64_t)lj_vm_asm_begin)); | ||
800 | #else | 927 | #else |
801 | trcont = lj_ir_kptr(J, (void *)cont); | 928 | J->base[top] = lj_ir_kptr(J, contptr(cont)) | TREF_CONT; |
802 | #endif | 929 | #endif |
803 | J->base[top] = trcont | TREF_CONT; | ||
804 | J->framedepth++; | 930 | J->framedepth++; |
805 | for (s = J->maxslot; s < top; s++) | 931 | for (s = J->maxslot; s < top; s++) |
806 | J->base[s] = 0; /* Clear frame gap to avoid resurrecting previous refs. */ | 932 | J->base[s] = 0; /* Clear frame gap to avoid resurrecting previous refs. */ |
807 | return top+1; | 933 | return top+1+LJ_FR2; |
808 | } | 934 | } |
809 | 935 | ||
810 | /* Record metamethod lookup. */ | 936 | /* Record metamethod lookup. */ |
@@ -823,7 +949,7 @@ int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm) | |||
823 | cTValue *mo; | 949 | cTValue *mo; |
824 | if (LJ_HASFFI && udtype == UDTYPE_FFI_CLIB) { | 950 | if (LJ_HASFFI && udtype == UDTYPE_FFI_CLIB) { |
825 | /* Specialize to the C library namespace object. */ | 951 | /* Specialize to the C library namespace object. */ |
826 | emitir(IRTG(IR_EQ, IRT_P32), ix->tab, lj_ir_kptr(J, udataV(&ix->tabv))); | 952 | emitir(IRTG(IR_EQ, IRT_PGC), ix->tab, lj_ir_kptr(J, udataV(&ix->tabv))); |
827 | } else { | 953 | } else { |
828 | /* Specialize to the type of userdata. */ | 954 | /* Specialize to the type of userdata. */ |
829 | TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), ix->tab, IRFL_UDATA_UDTYPE); | 955 | TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), ix->tab, IRFL_UDATA_UDTYPE); |
@@ -852,7 +978,13 @@ int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm) | |||
852 | } | 978 | } |
853 | /* The cdata metatable is treated as immutable. */ | 979 | /* The cdata metatable is treated as immutable. */ |
854 | if (LJ_HASFFI && tref_iscdata(ix->tab)) goto immutable_mt; | 980 | if (LJ_HASFFI && tref_iscdata(ix->tab)) goto immutable_mt; |
981 | #if LJ_GC64 | ||
982 | /* TODO: fix ARM32 asm_fload(), so we can use this for all archs. */ | ||
983 | ix->mt = mix.tab = lj_ir_ggfload(J, IRT_TAB, | ||
984 | GG_OFS(g.gcroot[GCROOT_BASEMT+itypemap(&ix->tabv)])); | ||
985 | #else | ||
855 | ix->mt = mix.tab = lj_ir_ktab(J, mt); | 986 | ix->mt = mix.tab = lj_ir_ktab(J, mt); |
987 | #endif | ||
856 | goto nocheck; | 988 | goto nocheck; |
857 | } | 989 | } |
858 | ix->mt = mt ? mix.tab : TREF_NIL; | 990 | ix->mt = mt ? mix.tab : TREF_NIL; |
@@ -879,12 +1011,12 @@ nocheck: | |||
879 | static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) | 1011 | static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) |
880 | { | 1012 | { |
881 | /* Set up metamethod call first to save ix->tab and ix->tabv. */ | 1013 | /* Set up metamethod call first to save ix->tab and ix->tabv. */ |
882 | BCReg func = rec_mm_prep(J, lj_cont_ra); | 1014 | BCReg func = rec_mm_prep(J, mm == MM_concat ? lj_cont_cat : lj_cont_ra); |
883 | TRef *base = J->base + func; | 1015 | TRef *base = J->base + func; |
884 | TValue *basev = J->L->base + func; | 1016 | TValue *basev = J->L->base + func; |
885 | base[1] = ix->tab; base[2] = ix->key; | 1017 | base[1+LJ_FR2] = ix->tab; base[2+LJ_FR2] = ix->key; |
886 | copyTV(J->L, basev+1, &ix->tabv); | 1018 | copyTV(J->L, basev+1+LJ_FR2, &ix->tabv); |
887 | copyTV(J->L, basev+2, &ix->keyv); | 1019 | copyTV(J->L, basev+2+LJ_FR2, &ix->keyv); |
888 | if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */ | 1020 | if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */ |
889 | if (mm != MM_unm) { | 1021 | if (mm != MM_unm) { |
890 | ix->tab = ix->key; | 1022 | ix->tab = ix->key; |
@@ -896,6 +1028,9 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) | |||
896 | } | 1028 | } |
897 | ok: | 1029 | ok: |
898 | base[0] = ix->mobj; | 1030 | base[0] = ix->mobj; |
1031 | #if LJ_FR2 | ||
1032 | base[1] = 0; | ||
1033 | #endif | ||
899 | copyTV(J->L, basev+0, &ix->mobjv); | 1034 | copyTV(J->L, basev+0, &ix->mobjv); |
900 | lj_record_call(J, func, 2); | 1035 | lj_record_call(J, func, 2); |
901 | return 0; /* No result yet. */ | 1036 | return 0; /* No result yet. */ |
@@ -912,6 +1047,8 @@ static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv) | |||
912 | TRef *base = J->base + func; | 1047 | TRef *base = J->base + func; |
913 | TValue *basev = J->L->base + func; | 1048 | TValue *basev = J->L->base + func; |
914 | base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv); | 1049 | base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv); |
1050 | base += LJ_FR2; | ||
1051 | basev += LJ_FR2; | ||
915 | base[1] = tr; copyTV(J->L, basev+1, tv); | 1052 | base[1] = tr; copyTV(J->L, basev+1, tv); |
916 | #if LJ_52 | 1053 | #if LJ_52 |
917 | base[2] = tr; copyTV(J->L, basev+2, tv); | 1054 | base[2] = tr; copyTV(J->L, basev+2, tv); |
@@ -931,10 +1068,10 @@ static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv) | |||
931 | static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op) | 1068 | static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op) |
932 | { | 1069 | { |
933 | BCReg func = rec_mm_prep(J, (op&1) ? lj_cont_condf : lj_cont_condt); | 1070 | BCReg func = rec_mm_prep(J, (op&1) ? lj_cont_condf : lj_cont_condt); |
934 | TRef *base = J->base + func; | 1071 | TRef *base = J->base + func + LJ_FR2; |
935 | TValue *tv = J->L->base + func; | 1072 | TValue *tv = J->L->base + func + LJ_FR2; |
936 | base[0] = ix->mobj; base[1] = ix->val; base[2] = ix->key; | 1073 | base[-LJ_FR2] = ix->mobj; base[1] = ix->val; base[2] = ix->key; |
937 | copyTV(J->L, tv+0, &ix->mobjv); | 1074 | copyTV(J->L, tv-LJ_FR2, &ix->mobjv); |
938 | copyTV(J->L, tv+1, &ix->valv); | 1075 | copyTV(J->L, tv+1, &ix->valv); |
939 | copyTV(J->L, tv+2, &ix->keyv); | 1076 | copyTV(J->L, tv+2, &ix->keyv); |
940 | lj_record_call(J, func, 2); | 1077 | lj_record_call(J, func, 2); |
@@ -1041,6 +1178,72 @@ static void rec_mm_comp_cdata(jit_State *J, RecordIndex *ix, int op, MMS mm) | |||
1041 | 1178 | ||
1042 | /* -- Indexed access ------------------------------------------------------ */ | 1179 | /* -- Indexed access ------------------------------------------------------ */ |
1043 | 1180 | ||
1181 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
1182 | /* Bump table allocations in bytecode when they grow during recording. */ | ||
1183 | static void rec_idx_bump(jit_State *J, RecordIndex *ix) | ||
1184 | { | ||
1185 | RBCHashEntry *rbc = &J->rbchash[(ix->tab & (RBCHASH_SLOTS-1))]; | ||
1186 | if (tref_ref(ix->tab) == rbc->ref) { | ||
1187 | const BCIns *pc = mref(rbc->pc, const BCIns); | ||
1188 | GCtab *tb = tabV(&ix->tabv); | ||
1189 | uint32_t nhbits; | ||
1190 | IRIns *ir; | ||
1191 | if (!tvisnil(&ix->keyv)) | ||
1192 | (void)lj_tab_set(J->L, tb, &ix->keyv); /* Grow table right now. */ | ||
1193 | nhbits = tb->hmask > 0 ? lj_fls(tb->hmask)+1 : 0; | ||
1194 | ir = IR(tref_ref(ix->tab)); | ||
1195 | if (ir->o == IR_TNEW) { | ||
1196 | uint32_t ah = bc_d(*pc); | ||
1197 | uint32_t asize = ah & 0x7ff, hbits = ah >> 11; | ||
1198 | if (nhbits > hbits) hbits = nhbits; | ||
1199 | if (tb->asize > asize) { | ||
1200 | asize = tb->asize <= 0x7ff ? tb->asize : 0x7ff; | ||
1201 | } | ||
1202 | if ((asize | (hbits<<11)) != ah) { /* Has the size changed? */ | ||
1203 | /* Patch bytecode, but continue recording (for more patching). */ | ||
1204 | setbc_d(pc, (asize | (hbits<<11))); | ||
1205 | /* Patching TNEW operands is only safe if the trace is aborted. */ | ||
1206 | ir->op1 = asize; ir->op2 = hbits; | ||
1207 | J->retryrec = 1; /* Abort the trace at the end of recording. */ | ||
1208 | } | ||
1209 | } else if (ir->o == IR_TDUP) { | ||
1210 | GCtab *tpl = gco2tab(proto_kgc(&gcref(rbc->pt)->pt, ~(ptrdiff_t)bc_d(*pc))); | ||
1211 | /* Grow template table, but preserve keys with nil values. */ | ||
1212 | if ((tb->asize > tpl->asize && (1u << nhbits)-1 == tpl->hmask) || | ||
1213 | (tb->asize == tpl->asize && (1u << nhbits)-1 > tpl->hmask)) { | ||
1214 | Node *node = noderef(tpl->node); | ||
1215 | uint32_t i, hmask = tpl->hmask, asize; | ||
1216 | TValue *array; | ||
1217 | for (i = 0; i <= hmask; i++) { | ||
1218 | if (!tvisnil(&node[i].key) && tvisnil(&node[i].val)) | ||
1219 | settabV(J->L, &node[i].val, tpl); | ||
1220 | } | ||
1221 | if (!tvisnil(&ix->keyv) && tref_isk(ix->key)) { | ||
1222 | TValue *o = lj_tab_set(J->L, tpl, &ix->keyv); | ||
1223 | if (tvisnil(o)) settabV(J->L, o, tpl); | ||
1224 | } | ||
1225 | lj_tab_resize(J->L, tpl, tb->asize, nhbits); | ||
1226 | node = noderef(tpl->node); | ||
1227 | hmask = tpl->hmask; | ||
1228 | for (i = 0; i <= hmask; i++) { | ||
1229 | /* This is safe, since template tables only hold immutable values. */ | ||
1230 | if (tvistab(&node[i].val)) | ||
1231 | setnilV(&node[i].val); | ||
1232 | } | ||
1233 | /* The shape of the table may have changed. Clean up array part, too. */ | ||
1234 | asize = tpl->asize; | ||
1235 | array = tvref(tpl->array); | ||
1236 | for (i = 0; i < asize; i++) { | ||
1237 | if (tvistab(&array[i])) | ||
1238 | setnilV(&array[i]); | ||
1239 | } | ||
1240 | J->retryrec = 1; /* Abort the trace at the end of recording. */ | ||
1241 | } | ||
1242 | } | ||
1243 | } | ||
1244 | } | ||
1245 | #endif | ||
1246 | |||
1044 | /* Record bounds-check. */ | 1247 | /* Record bounds-check. */ |
1045 | static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) | 1248 | static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) |
1046 | { | 1249 | { |
@@ -1080,11 +1283,14 @@ static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) | |||
1080 | } | 1283 | } |
1081 | 1284 | ||
1082 | /* Record indexed key lookup. */ | 1285 | /* Record indexed key lookup. */ |
1083 | static TRef rec_idx_key(jit_State *J, RecordIndex *ix) | 1286 | static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref, |
1287 | IRType1 *rbguard) | ||
1084 | { | 1288 | { |
1085 | TRef key; | 1289 | TRef key; |
1086 | GCtab *t = tabV(&ix->tabv); | 1290 | GCtab *t = tabV(&ix->tabv); |
1087 | ix->oldv = lj_tab_get(J->L, t, &ix->keyv); /* Lookup previous value. */ | 1291 | ix->oldv = lj_tab_get(J->L, t, &ix->keyv); /* Lookup previous value. */ |
1292 | *rbref = 0; | ||
1293 | rbguard->irt = 0; | ||
1088 | 1294 | ||
1089 | /* Integer keys are looked up in the array part first. */ | 1295 | /* Integer keys are looked up in the array part first. */ |
1090 | key = ix->key; | 1296 | key = ix->key; |
@@ -1098,8 +1304,8 @@ static TRef rec_idx_key(jit_State *J, RecordIndex *ix) | |||
1098 | if ((MSize)k < t->asize) { /* Currently an array key? */ | 1304 | if ((MSize)k < t->asize) { /* Currently an array key? */ |
1099 | TRef arrayref; | 1305 | TRef arrayref; |
1100 | rec_idx_abc(J, asizeref, ikey, t->asize); | 1306 | rec_idx_abc(J, asizeref, ikey, t->asize); |
1101 | arrayref = emitir(IRT(IR_FLOAD, IRT_P32), ix->tab, IRFL_TAB_ARRAY); | 1307 | arrayref = emitir(IRT(IR_FLOAD, IRT_PGC), ix->tab, IRFL_TAB_ARRAY); |
1102 | return emitir(IRT(IR_AREF, IRT_P32), arrayref, ikey); | 1308 | return emitir(IRT(IR_AREF, IRT_PGC), arrayref, ikey); |
1103 | } else { /* Currently not in array (may be an array extension)? */ | 1309 | } else { /* Currently not in array (may be an array extension)? */ |
1104 | emitir(IRTGI(IR_ULE), asizeref, ikey); /* Inv. bounds check. */ | 1310 | emitir(IRTGI(IR_ULE), asizeref, ikey); /* Inv. bounds check. */ |
1105 | if (k == 0 && tref_isk(key)) | 1311 | if (k == 0 && tref_isk(key)) |
@@ -1134,16 +1340,18 @@ static TRef rec_idx_key(jit_State *J, RecordIndex *ix) | |||
1134 | MSize hslot = (MSize)((char *)ix->oldv - (char *)&noderef(t->node)[0].val); | 1340 | MSize hslot = (MSize)((char *)ix->oldv - (char *)&noderef(t->node)[0].val); |
1135 | if (t->hmask > 0 && hslot <= t->hmask*(MSize)sizeof(Node) && | 1341 | if (t->hmask > 0 && hslot <= t->hmask*(MSize)sizeof(Node) && |
1136 | hslot <= 65535*(MSize)sizeof(Node)) { | 1342 | hslot <= 65535*(MSize)sizeof(Node)) { |
1137 | TRef node, kslot; | 1343 | TRef node, kslot, hm; |
1138 | TRef hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK); | 1344 | *rbref = J->cur.nins; /* Mark possible rollback point. */ |
1345 | *rbguard = J->guardemit; | ||
1346 | hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK); | ||
1139 | emitir(IRTGI(IR_EQ), hm, lj_ir_kint(J, (int32_t)t->hmask)); | 1347 | emitir(IRTGI(IR_EQ), hm, lj_ir_kint(J, (int32_t)t->hmask)); |
1140 | node = emitir(IRT(IR_FLOAD, IRT_P32), ix->tab, IRFL_TAB_NODE); | 1348 | node = emitir(IRT(IR_FLOAD, IRT_PGC), ix->tab, IRFL_TAB_NODE); |
1141 | kslot = lj_ir_kslot(J, key, hslot / sizeof(Node)); | 1349 | kslot = lj_ir_kslot(J, key, hslot / sizeof(Node)); |
1142 | return emitir(IRTG(IR_HREFK, IRT_P32), node, kslot); | 1350 | return emitir(IRTG(IR_HREFK, IRT_PGC), node, kslot); |
1143 | } | 1351 | } |
1144 | } | 1352 | } |
1145 | /* Fall back to a regular hash lookup. */ | 1353 | /* Fall back to a regular hash lookup. */ |
1146 | return emitir(IRT(IR_HREF, IRT_P32), ix->tab, key); | 1354 | return emitir(IRT(IR_HREF, IRT_PGC), ix->tab, key); |
1147 | } | 1355 | } |
1148 | 1356 | ||
1149 | /* Determine whether a key is NOT one of the fast metamethod names. */ | 1357 | /* Determine whether a key is NOT one of the fast metamethod names. */ |
@@ -1168,6 +1376,8 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1168 | { | 1376 | { |
1169 | TRef xref; | 1377 | TRef xref; |
1170 | IROp xrefop, loadop; | 1378 | IROp xrefop, loadop; |
1379 | IRRef rbref; | ||
1380 | IRType1 rbguard; | ||
1171 | cTValue *oldv; | 1381 | cTValue *oldv; |
1172 | 1382 | ||
1173 | while (!tref_istab(ix->tab)) { /* Handle non-table lookup. */ | 1383 | while (!tref_istab(ix->tab)) { /* Handle non-table lookup. */ |
@@ -1178,10 +1388,10 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1178 | handlemm: | 1388 | handlemm: |
1179 | if (tref_isfunc(ix->mobj)) { /* Handle metamethod call. */ | 1389 | if (tref_isfunc(ix->mobj)) { /* Handle metamethod call. */ |
1180 | BCReg func = rec_mm_prep(J, ix->val ? lj_cont_nop : lj_cont_ra); | 1390 | BCReg func = rec_mm_prep(J, ix->val ? lj_cont_nop : lj_cont_ra); |
1181 | TRef *base = J->base + func; | 1391 | TRef *base = J->base + func + LJ_FR2; |
1182 | TValue *tv = J->L->base + func; | 1392 | TValue *tv = J->L->base + func + LJ_FR2; |
1183 | base[0] = ix->mobj; base[1] = ix->tab; base[2] = ix->key; | 1393 | base[-LJ_FR2] = ix->mobj; base[1] = ix->tab; base[2] = ix->key; |
1184 | setfuncV(J->L, tv+0, funcV(&ix->mobjv)); | 1394 | setfuncV(J->L, tv-LJ_FR2, funcV(&ix->mobjv)); |
1185 | copyTV(J->L, tv+1, &ix->tabv); | 1395 | copyTV(J->L, tv+1, &ix->tabv); |
1186 | copyTV(J->L, tv+2, &ix->keyv); | 1396 | copyTV(J->L, tv+2, &ix->keyv); |
1187 | if (ix->val) { | 1397 | if (ix->val) { |
@@ -1213,7 +1423,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1213 | } | 1423 | } |
1214 | 1424 | ||
1215 | /* Record the key lookup. */ | 1425 | /* Record the key lookup. */ |
1216 | xref = rec_idx_key(J, ix); | 1426 | xref = rec_idx_key(J, ix, &rbref, &rbguard); |
1217 | xrefop = IR(tref_ref(xref))->o; | 1427 | xrefop = IR(tref_ref(xref))->o; |
1218 | loadop = xrefop == IR_AREF ? IR_ALOAD : IR_HLOAD; | 1428 | loadop = xrefop == IR_AREF ? IR_ALOAD : IR_HLOAD; |
1219 | /* The lj_meta_tset() inconsistency is gone, but better play safe. */ | 1429 | /* The lj_meta_tset() inconsistency is gone, but better play safe. */ |
@@ -1223,11 +1433,15 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1223 | IRType t = itype2irt(oldv); | 1433 | IRType t = itype2irt(oldv); |
1224 | TRef res; | 1434 | TRef res; |
1225 | if (oldv == niltvg(J2G(J))) { | 1435 | if (oldv == niltvg(J2G(J))) { |
1226 | emitir(IRTG(IR_EQ, IRT_P32), xref, lj_ir_kkptr(J, niltvg(J2G(J)))); | 1436 | emitir(IRTG(IR_EQ, IRT_PGC), xref, lj_ir_kkptr(J, niltvg(J2G(J)))); |
1227 | res = TREF_NIL; | 1437 | res = TREF_NIL; |
1228 | } else { | 1438 | } else { |
1229 | res = emitir(IRTG(loadop, t), xref, 0); | 1439 | res = emitir(IRTG(loadop, t), xref, 0); |
1230 | } | 1440 | } |
1441 | if (tref_ref(res) < rbref) { /* HREFK + load forwarded? */ | ||
1442 | lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */ | ||
1443 | J->guardemit = rbguard; | ||
1444 | } | ||
1231 | if (t == IRT_NIL && ix->idxchain && lj_record_mm_lookup(J, ix, MM_index)) | 1445 | if (t == IRT_NIL && ix->idxchain && lj_record_mm_lookup(J, ix, MM_index)) |
1232 | goto handlemm; | 1446 | goto handlemm; |
1233 | if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitives. */ | 1447 | if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitives. */ |
@@ -1235,6 +1449,10 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1235 | } else { /* Indexed store. */ | 1449 | } else { /* Indexed store. */ |
1236 | GCtab *mt = tabref(tabV(&ix->tabv)->metatable); | 1450 | GCtab *mt = tabref(tabV(&ix->tabv)->metatable); |
1237 | int keybarrier = tref_isgcv(ix->key) && !tref_isnil(ix->val); | 1451 | int keybarrier = tref_isgcv(ix->key) && !tref_isnil(ix->val); |
1452 | if (tref_ref(xref) < rbref) { /* HREFK forwarded? */ | ||
1453 | lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */ | ||
1454 | J->guardemit = rbguard; | ||
1455 | } | ||
1238 | if (tvisnil(oldv)) { /* Previous value was nil? */ | 1456 | if (tvisnil(oldv)) { /* Previous value was nil? */ |
1239 | /* Need to duplicate the hasmm check for the early guards. */ | 1457 | /* Need to duplicate the hasmm check for the early guards. */ |
1240 | int hasmm = 0; | 1458 | int hasmm = 0; |
@@ -1245,7 +1463,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1245 | if (hasmm) | 1463 | if (hasmm) |
1246 | emitir(IRTG(loadop, IRT_NIL), xref, 0); /* Guard for nil value. */ | 1464 | emitir(IRTG(loadop, IRT_NIL), xref, 0); /* Guard for nil value. */ |
1247 | else if (xrefop == IR_HREF) | 1465 | else if (xrefop == IR_HREF) |
1248 | emitir(IRTG(oldv == niltvg(J2G(J)) ? IR_EQ : IR_NE, IRT_P32), | 1466 | emitir(IRTG(oldv == niltvg(J2G(J)) ? IR_EQ : IR_NE, IRT_PGC), |
1249 | xref, lj_ir_kkptr(J, niltvg(J2G(J)))); | 1467 | xref, lj_ir_kkptr(J, niltvg(J2G(J)))); |
1250 | if (ix->idxchain && lj_record_mm_lookup(J, ix, MM_newindex)) { | 1468 | if (ix->idxchain && lj_record_mm_lookup(J, ix, MM_newindex)) { |
1251 | lua_assert(hasmm); | 1469 | lua_assert(hasmm); |
@@ -1256,13 +1474,17 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1256 | TRef key = ix->key; | 1474 | TRef key = ix->key; |
1257 | if (tref_isinteger(key)) /* NEWREF needs a TValue as a key. */ | 1475 | if (tref_isinteger(key)) /* NEWREF needs a TValue as a key. */ |
1258 | key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT); | 1476 | key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT); |
1259 | xref = emitir(IRT(IR_NEWREF, IRT_P32), ix->tab, key); | 1477 | xref = emitir(IRT(IR_NEWREF, IRT_PGC), ix->tab, key); |
1260 | keybarrier = 0; /* NEWREF already takes care of the key barrier. */ | 1478 | keybarrier = 0; /* NEWREF already takes care of the key barrier. */ |
1479 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
1480 | if ((J->flags & JIT_F_OPT_SINK)) /* Avoid a separate flag. */ | ||
1481 | rec_idx_bump(J, ix); | ||
1482 | #endif | ||
1261 | } | 1483 | } |
1262 | } else if (!lj_opt_fwd_wasnonnil(J, loadop, tref_ref(xref))) { | 1484 | } else if (!lj_opt_fwd_wasnonnil(J, loadop, tref_ref(xref))) { |
1263 | /* Cannot derive that the previous value was non-nil, must do checks. */ | 1485 | /* Cannot derive that the previous value was non-nil, must do checks. */ |
1264 | if (xrefop == IR_HREF) /* Guard against store to niltv. */ | 1486 | if (xrefop == IR_HREF) /* Guard against store to niltv. */ |
1265 | emitir(IRTG(IR_NE, IRT_P32), xref, lj_ir_kkptr(J, niltvg(J2G(J)))); | 1487 | emitir(IRTG(IR_NE, IRT_PGC), xref, lj_ir_kkptr(J, niltvg(J2G(J)))); |
1266 | if (ix->idxchain) { /* Metamethod lookup required? */ | 1488 | if (ix->idxchain) { /* Metamethod lookup required? */ |
1267 | /* A check for NULL metatable is cheaper (hoistable) than a load. */ | 1489 | /* A check for NULL metatable is cheaper (hoistable) than a load. */ |
1268 | if (!mt) { | 1490 | if (!mt) { |
@@ -1284,7 +1506,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1284 | emitir(IRT(IR_TBAR, IRT_NIL), ix->tab, 0); | 1506 | emitir(IRT(IR_TBAR, IRT_NIL), ix->tab, 0); |
1285 | /* Invalidate neg. metamethod cache for stores with certain string keys. */ | 1507 | /* Invalidate neg. metamethod cache for stores with certain string keys. */ |
1286 | if (!nommstr(J, ix->key)) { | 1508 | if (!nommstr(J, ix->key)) { |
1287 | TRef fref = emitir(IRT(IR_FREF, IRT_P32), ix->tab, IRFL_TAB_NOMM); | 1509 | TRef fref = emitir(IRT(IR_FREF, IRT_PGC), ix->tab, IRFL_TAB_NOMM); |
1288 | emitir(IRT(IR_FSTORE, IRT_U8), fref, lj_ir_kint(J, 0)); | 1510 | emitir(IRT(IR_FSTORE, IRT_U8), fref, lj_ir_kint(J, 0)); |
1289 | } | 1511 | } |
1290 | J->needsnap = 1; | 1512 | J->needsnap = 1; |
@@ -1292,6 +1514,31 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1292 | } | 1514 | } |
1293 | } | 1515 | } |
1294 | 1516 | ||
1517 | static void rec_tsetm(jit_State *J, BCReg ra, BCReg rn, int32_t i) | ||
1518 | { | ||
1519 | RecordIndex ix; | ||
1520 | cTValue *basev = J->L->base; | ||
1521 | GCtab *t = tabV(&basev[ra-1]); | ||
1522 | settabV(J->L, &ix.tabv, t); | ||
1523 | ix.tab = getslot(J, ra-1); | ||
1524 | ix.idxchain = 0; | ||
1525 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
1526 | if ((J->flags & JIT_F_OPT_SINK)) { | ||
1527 | if (t->asize < i+rn-ra) | ||
1528 | lj_tab_reasize(J->L, t, i+rn-ra); | ||
1529 | setnilV(&ix.keyv); | ||
1530 | rec_idx_bump(J, &ix); | ||
1531 | } | ||
1532 | #endif | ||
1533 | for (; ra < rn; i++, ra++) { | ||
1534 | setintV(&ix.keyv, i); | ||
1535 | ix.key = lj_ir_kint(J, i); | ||
1536 | copyTV(J->L, &ix.valv, &basev[ra]); | ||
1537 | ix.val = getslot(J, ra); | ||
1538 | lj_record_idx(J, &ix); | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1295 | /* -- Upvalue access ------------------------------------------------------ */ | 1542 | /* -- Upvalue access ------------------------------------------------------ */ |
1296 | 1543 | ||
1297 | /* Check whether upvalue is immutable and ok to constify. */ | 1544 | /* Check whether upvalue is immutable and ok to constify. */ |
@@ -1334,7 +1581,11 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val) | |||
1334 | goto noconstify; | 1581 | goto noconstify; |
1335 | kfunc = lj_ir_kfunc(J, J->fn); | 1582 | kfunc = lj_ir_kfunc(J, J->fn); |
1336 | emitir(IRTG(IR_EQ, IRT_FUNC), fn, kfunc); | 1583 | emitir(IRTG(IR_EQ, IRT_FUNC), fn, kfunc); |
1337 | J->base[-1] = TREF_FRAME | kfunc; | 1584 | #if LJ_FR2 |
1585 | J->base[-2] = kfunc; | ||
1586 | #else | ||
1587 | J->base[-1] = kfunc | TREF_FRAME; | ||
1588 | #endif | ||
1338 | fn = kfunc; | 1589 | fn = kfunc; |
1339 | } | 1590 | } |
1340 | tr = lj_record_constify(J, uvval(uvp)); | 1591 | tr = lj_record_constify(J, uvval(uvp)); |
@@ -1345,16 +1596,16 @@ noconstify: | |||
1345 | /* Note: this effectively limits LJ_MAX_UPVAL to 127. */ | 1596 | /* Note: this effectively limits LJ_MAX_UPVAL to 127. */ |
1346 | uv = (uv << 8) | (hashrot(uvp->dhash, uvp->dhash + HASH_BIAS) & 0xff); | 1597 | uv = (uv << 8) | (hashrot(uvp->dhash, uvp->dhash + HASH_BIAS) & 0xff); |
1347 | if (!uvp->closed) { | 1598 | if (!uvp->closed) { |
1348 | uref = tref_ref(emitir(IRTG(IR_UREFO, IRT_P32), fn, uv)); | 1599 | uref = tref_ref(emitir(IRTG(IR_UREFO, IRT_PGC), fn, uv)); |
1349 | /* In current stack? */ | 1600 | /* In current stack? */ |
1350 | if (uvval(uvp) >= tvref(J->L->stack) && | 1601 | if (uvval(uvp) >= tvref(J->L->stack) && |
1351 | uvval(uvp) < tvref(J->L->maxstack)) { | 1602 | uvval(uvp) < tvref(J->L->maxstack)) { |
1352 | int32_t slot = (int32_t)(uvval(uvp) - (J->L->base - J->baseslot)); | 1603 | int32_t slot = (int32_t)(uvval(uvp) - (J->L->base - J->baseslot)); |
1353 | if (slot >= 0) { /* Aliases an SSA slot? */ | 1604 | if (slot >= 0) { /* Aliases an SSA slot? */ |
1354 | emitir(IRTG(IR_EQ, IRT_P32), | 1605 | emitir(IRTG(IR_EQ, IRT_PGC), |
1355 | REF_BASE, | 1606 | REF_BASE, |
1356 | emitir(IRT(IR_ADD, IRT_P32), uref, | 1607 | emitir(IRT(IR_ADD, IRT_PGC), uref, |
1357 | lj_ir_kint(J, (slot - 1) * -8))); | 1608 | lj_ir_kint(J, (slot - 1 - LJ_FR2) * -8))); |
1358 | slot -= (int32_t)J->baseslot; /* Note: slot number may be negative! */ | 1609 | slot -= (int32_t)J->baseslot; /* Note: slot number may be negative! */ |
1359 | if (val == 0) { | 1610 | if (val == 0) { |
1360 | return getslot(J, slot); | 1611 | return getslot(J, slot); |
@@ -1365,12 +1616,12 @@ noconstify: | |||
1365 | } | 1616 | } |
1366 | } | 1617 | } |
1367 | } | 1618 | } |
1368 | emitir(IRTG(IR_UGT, IRT_P32), | 1619 | emitir(IRTG(IR_UGT, IRT_PGC), |
1369 | emitir(IRT(IR_SUB, IRT_P32), uref, REF_BASE), | 1620 | emitir(IRT(IR_SUB, IRT_PGC), uref, REF_BASE), |
1370 | lj_ir_kint(J, (J->baseslot + J->maxslot) * 8)); | 1621 | lj_ir_kint(J, (J->baseslot + J->maxslot) * 8)); |
1371 | } else { | 1622 | } else { |
1372 | needbarrier = 1; | 1623 | needbarrier = 1; |
1373 | uref = tref_ref(emitir(IRTG(IR_UREFC, IRT_P32), fn, uv)); | 1624 | uref = tref_ref(emitir(IRTG(IR_UREFC, IRT_PGC), fn, uv)); |
1374 | } | 1625 | } |
1375 | if (val == 0) { /* Upvalue load */ | 1626 | if (val == 0) { /* Upvalue load */ |
1376 | IRType t = itype2irt(uvval(uvp)); | 1627 | IRType t = itype2irt(uvval(uvp)); |
@@ -1409,9 +1660,9 @@ static void check_call_unroll(jit_State *J, TraceNo lnk) | |||
1409 | if (count + J->tailcalled > J->param[JIT_P_recunroll]) { | 1660 | if (count + J->tailcalled > J->param[JIT_P_recunroll]) { |
1410 | J->pc++; | 1661 | J->pc++; |
1411 | if (J->framedepth + J->retdepth == 0) | 1662 | if (J->framedepth + J->retdepth == 0) |
1412 | rec_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Tail-recursion. */ | 1663 | lj_record_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Tail-rec. */ |
1413 | else | 1664 | else |
1414 | rec_stop(J, LJ_TRLINK_UPREC, J->cur.traceno); /* Up-recursion. */ | 1665 | lj_record_stop(J, LJ_TRLINK_UPREC, J->cur.traceno); /* Up-recursion. */ |
1415 | } | 1666 | } |
1416 | } else { | 1667 | } else { |
1417 | if (count > J->param[JIT_P_callunroll]) { | 1668 | if (count > J->param[JIT_P_callunroll]) { |
@@ -1445,11 +1696,14 @@ static void rec_func_setup(jit_State *J) | |||
1445 | static void rec_func_vararg(jit_State *J) | 1696 | static void rec_func_vararg(jit_State *J) |
1446 | { | 1697 | { |
1447 | GCproto *pt = J->pt; | 1698 | GCproto *pt = J->pt; |
1448 | BCReg s, fixargs, vframe = J->maxslot+1; | 1699 | BCReg s, fixargs, vframe = J->maxslot+1+LJ_FR2; |
1449 | lua_assert((pt->flags & PROTO_VARARG)); | 1700 | lua_assert((pt->flags & PROTO_VARARG)); |
1450 | if (J->baseslot + vframe + pt->framesize >= LJ_MAX_JSLOTS) | 1701 | if (J->baseslot + vframe + pt->framesize >= LJ_MAX_JSLOTS) |
1451 | lj_trace_err(J, LJ_TRERR_STACKOV); | 1702 | lj_trace_err(J, LJ_TRERR_STACKOV); |
1452 | J->base[vframe-1] = J->base[-1]; /* Copy function up. */ | 1703 | J->base[vframe-1-LJ_FR2] = J->base[-1-LJ_FR2]; /* Copy function up. */ |
1704 | #if LJ_FR2 | ||
1705 | J->base[vframe-1] = TREF_FRAME; | ||
1706 | #endif | ||
1453 | /* Copy fixarg slots up and set their original slots to nil. */ | 1707 | /* Copy fixarg slots up and set their original slots to nil. */ |
1454 | fixargs = pt->numparams < J->maxslot ? pt->numparams : J->maxslot; | 1708 | fixargs = pt->numparams < J->maxslot ? pt->numparams : J->maxslot; |
1455 | for (s = 0; s < fixargs; s++) { | 1709 | for (s = 0; s < fixargs; s++) { |
@@ -1485,9 +1739,9 @@ static void rec_func_jit(jit_State *J, TraceNo lnk) | |||
1485 | } | 1739 | } |
1486 | J->instunroll = 0; /* Cannot continue across a compiled function. */ | 1740 | J->instunroll = 0; /* Cannot continue across a compiled function. */ |
1487 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) | 1741 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) |
1488 | rec_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Extra tail-recursion. */ | 1742 | lj_record_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Extra tail-rec. */ |
1489 | else | 1743 | else |
1490 | rec_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the function. */ | 1744 | lj_record_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the function. */ |
1491 | } | 1745 | } |
1492 | 1746 | ||
1493 | /* -- Vararg handling ----------------------------------------------------- */ | 1747 | /* -- Vararg handling ----------------------------------------------------- */ |
@@ -1511,8 +1765,10 @@ static int select_detect(jit_State *J) | |||
1511 | static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | 1765 | static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) |
1512 | { | 1766 | { |
1513 | int32_t numparams = J->pt->numparams; | 1767 | int32_t numparams = J->pt->numparams; |
1514 | ptrdiff_t nvararg = frame_delta(J->L->base-1) - numparams - 1; | 1768 | ptrdiff_t nvararg = frame_delta(J->L->base-1) - numparams - 1 - LJ_FR2; |
1515 | lua_assert(frame_isvarg(J->L->base-1)); | 1769 | lua_assert(frame_isvarg(J->L->base-1)); |
1770 | if (LJ_FR2 && dst > J->maxslot) | ||
1771 | J->base[dst-1] = 0; /* Prevent resurrection of unrelated slot. */ | ||
1516 | if (J->framedepth > 0) { /* Simple case: varargs defined on-trace. */ | 1772 | if (J->framedepth > 0) { /* Simple case: varargs defined on-trace. */ |
1517 | ptrdiff_t i; | 1773 | ptrdiff_t i; |
1518 | if (nvararg < 0) nvararg = 0; | 1774 | if (nvararg < 0) nvararg = 0; |
@@ -1523,10 +1779,10 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | |||
1523 | J->maxslot = dst + (BCReg)nresults; | 1779 | J->maxslot = dst + (BCReg)nresults; |
1524 | } | 1780 | } |
1525 | for (i = 0; i < nresults; i++) | 1781 | for (i = 0; i < nresults; i++) |
1526 | J->base[dst+i] = i < nvararg ? getslot(J, i - nvararg - 1) : TREF_NIL; | 1782 | J->base[dst+i] = i < nvararg ? getslot(J, i - nvararg - 1 - LJ_FR2) : TREF_NIL; |
1527 | } else { /* Unknown number of varargs passed to trace. */ | 1783 | } else { /* Unknown number of varargs passed to trace. */ |
1528 | TRef fr = emitir(IRTI(IR_SLOAD), 0, IRSLOAD_READONLY|IRSLOAD_FRAME); | 1784 | TRef fr = emitir(IRTI(IR_SLOAD), LJ_FR2, IRSLOAD_READONLY|IRSLOAD_FRAME); |
1529 | int32_t frofs = 8*(1+numparams)+FRAME_VARG; | 1785 | int32_t frofs = 8*(1+LJ_FR2+numparams)+FRAME_VARG; |
1530 | if (nresults >= 0) { /* Known fixed number of results. */ | 1786 | if (nresults >= 0) { /* Known fixed number of results. */ |
1531 | ptrdiff_t i; | 1787 | ptrdiff_t i; |
1532 | if (nvararg > 0) { | 1788 | if (nvararg > 0) { |
@@ -1535,12 +1791,13 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | |||
1535 | if (nvararg >= nresults) | 1791 | if (nvararg >= nresults) |
1536 | emitir(IRTGI(IR_GE), fr, lj_ir_kint(J, frofs+8*(int32_t)nresults)); | 1792 | emitir(IRTGI(IR_GE), fr, lj_ir_kint(J, frofs+8*(int32_t)nresults)); |
1537 | else | 1793 | else |
1538 | emitir(IRTGI(IR_EQ), fr, lj_ir_kint(J, frame_ftsz(J->L->base-1))); | 1794 | emitir(IRTGI(IR_EQ), fr, |
1539 | vbase = emitir(IRTI(IR_SUB), REF_BASE, fr); | 1795 | lj_ir_kint(J, (int32_t)frame_ftsz(J->L->base-1))); |
1540 | vbase = emitir(IRT(IR_ADD, IRT_P32), vbase, lj_ir_kint(J, frofs-8)); | 1796 | vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr); |
1797 | vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, lj_ir_kint(J, frofs-8)); | ||
1541 | for (i = 0; i < nload; i++) { | 1798 | for (i = 0; i < nload; i++) { |
1542 | IRType t = itype2irt(&J->L->base[i-1-nvararg]); | 1799 | IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]); |
1543 | TRef aref = emitir(IRT(IR_AREF, IRT_P32), | 1800 | TRef aref = emitir(IRT(IR_AREF, IRT_PGC), |
1544 | vbase, lj_ir_kint(J, (int32_t)i)); | 1801 | vbase, lj_ir_kint(J, (int32_t)i)); |
1545 | TRef tr = emitir(IRTG(IR_VLOAD, t), aref, 0); | 1802 | TRef tr = emitir(IRTG(IR_VLOAD, t), aref, 0); |
1546 | if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ | 1803 | if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ |
@@ -1586,15 +1843,16 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | |||
1586 | } | 1843 | } |
1587 | if (idx != 0 && idx <= nvararg) { | 1844 | if (idx != 0 && idx <= nvararg) { |
1588 | IRType t; | 1845 | IRType t; |
1589 | TRef aref, vbase = emitir(IRTI(IR_SUB), REF_BASE, fr); | 1846 | TRef aref, vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr); |
1590 | vbase = emitir(IRT(IR_ADD, IRT_P32), vbase, lj_ir_kint(J, frofs-8)); | 1847 | vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, |
1591 | t = itype2irt(&J->L->base[idx-2-nvararg]); | 1848 | lj_ir_kint(J, frofs-(8<<LJ_FR2))); |
1592 | aref = emitir(IRT(IR_AREF, IRT_P32), vbase, tridx); | 1849 | t = itype2irt(&J->L->base[idx-2-LJ_FR2-nvararg]); |
1850 | aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx); | ||
1593 | tr = emitir(IRTG(IR_VLOAD, t), aref, 0); | 1851 | tr = emitir(IRTG(IR_VLOAD, t), aref, 0); |
1594 | if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ | 1852 | if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ |
1595 | } | 1853 | } |
1596 | J->base[dst-2] = tr; | 1854 | J->base[dst-2-LJ_FR2] = tr; |
1597 | J->maxslot = dst-1; | 1855 | J->maxslot = dst-1-LJ_FR2; |
1598 | J->bcskip = 2; /* Skip CALLM + select. */ | 1856 | J->bcskip = 2; /* Skip CALLM + select. */ |
1599 | } else { | 1857 | } else { |
1600 | nyivarg: | 1858 | nyivarg: |
@@ -1612,8 +1870,63 @@ static TRef rec_tnew(jit_State *J, uint32_t ah) | |||
1612 | { | 1870 | { |
1613 | uint32_t asize = ah & 0x7ff; | 1871 | uint32_t asize = ah & 0x7ff; |
1614 | uint32_t hbits = ah >> 11; | 1872 | uint32_t hbits = ah >> 11; |
1873 | TRef tr; | ||
1615 | if (asize == 0x7ff) asize = 0x801; | 1874 | if (asize == 0x7ff) asize = 0x801; |
1616 | return emitir(IRTG(IR_TNEW, IRT_TAB), asize, hbits); | 1875 | tr = emitir(IRTG(IR_TNEW, IRT_TAB), asize, hbits); |
1876 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
1877 | J->rbchash[(tr & (RBCHASH_SLOTS-1))].ref = tref_ref(tr); | ||
1878 | setmref(J->rbchash[(tr & (RBCHASH_SLOTS-1))].pc, J->pc); | ||
1879 | setgcref(J->rbchash[(tr & (RBCHASH_SLOTS-1))].pt, obj2gco(J->pt)); | ||
1880 | #endif | ||
1881 | return tr; | ||
1882 | } | ||
1883 | |||
1884 | /* -- Concatenation ------------------------------------------------------- */ | ||
1885 | |||
1886 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) | ||
1887 | { | ||
1888 | TRef *top = &J->base[topslot]; | ||
1889 | TValue savetv[5]; | ||
1890 | BCReg s; | ||
1891 | RecordIndex ix; | ||
1892 | lua_assert(baseslot < topslot); | ||
1893 | for (s = baseslot; s <= topslot; s++) | ||
1894 | (void)getslot(J, s); /* Ensure all arguments have a reference. */ | ||
1895 | if (tref_isnumber_str(top[0]) && tref_isnumber_str(top[-1])) { | ||
1896 | TRef tr, hdr, *trp, *xbase, *base = &J->base[baseslot]; | ||
1897 | /* First convert numbers to strings. */ | ||
1898 | for (trp = top; trp >= base; trp--) { | ||
1899 | if (tref_isnumber(*trp)) | ||
1900 | *trp = emitir(IRT(IR_TOSTR, IRT_STR), *trp, | ||
1901 | tref_isnum(*trp) ? IRTOSTR_NUM : IRTOSTR_INT); | ||
1902 | else if (!tref_isstr(*trp)) | ||
1903 | break; | ||
1904 | } | ||
1905 | xbase = ++trp; | ||
1906 | tr = hdr = emitir(IRT(IR_BUFHDR, IRT_PGC), | ||
1907 | lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET); | ||
1908 | do { | ||
1909 | tr = emitir(IRT(IR_BUFPUT, IRT_PGC), tr, *trp++); | ||
1910 | } while (trp <= top); | ||
1911 | tr = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); | ||
1912 | J->maxslot = (BCReg)(xbase - J->base); | ||
1913 | if (xbase == base) return tr; /* Return simple concatenation result. */ | ||
1914 | /* Pass partial result. */ | ||
1915 | topslot = J->maxslot--; | ||
1916 | *xbase = tr; | ||
1917 | top = xbase; | ||
1918 | setstrV(J->L, &ix.keyv, &J2G(J)->strempty); /* Simulate string result. */ | ||
1919 | } else { | ||
1920 | J->maxslot = topslot-1; | ||
1921 | copyTV(J->L, &ix.keyv, &J->L->base[topslot]); | ||
1922 | } | ||
1923 | copyTV(J->L, &ix.tabv, &J->L->base[topslot-1]); | ||
1924 | ix.tab = top[-1]; | ||
1925 | ix.key = top[0]; | ||
1926 | memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */ | ||
1927 | rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */ | ||
1928 | memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ | ||
1929 | return 0; /* No result yet. */ | ||
1617 | } | 1930 | } |
1618 | 1931 | ||
1619 | /* -- Record bytecode ops ------------------------------------------------- */ | 1932 | /* -- Record bytecode ops ------------------------------------------------- */ |
@@ -1634,7 +1947,15 @@ static void rec_comp_fixup(jit_State *J, const BCIns *pc, int cond) | |||
1634 | const BCIns *npc = pc + 2 + (cond ? bc_j(jmpins) : 0); | 1947 | const BCIns *npc = pc + 2 + (cond ? bc_j(jmpins) : 0); |
1635 | SnapShot *snap = &J->cur.snap[J->cur.nsnap-1]; | 1948 | SnapShot *snap = &J->cur.snap[J->cur.nsnap-1]; |
1636 | /* Set PC to opposite target to avoid re-recording the comp. in side trace. */ | 1949 | /* Set PC to opposite target to avoid re-recording the comp. in side trace. */ |
1950 | #if LJ_FR2 | ||
1951 | SnapEntry *flink = &J->cur.snapmap[snap->mapofs + snap->nent]; | ||
1952 | uint64_t pcbase; | ||
1953 | memcpy(&pcbase, flink, sizeof(uint64_t)); | ||
1954 | pcbase = (pcbase & 0xff) | (u64ptr(npc) << 8); | ||
1955 | memcpy(flink, &pcbase, sizeof(uint64_t)); | ||
1956 | #else | ||
1637 | J->cur.snapmap[snap->mapofs + snap->nent] = SNAP_MKPC(npc); | 1957 | J->cur.snapmap[snap->mapofs + snap->nent] = SNAP_MKPC(npc); |
1958 | #endif | ||
1638 | J->needsnap = 1; | 1959 | J->needsnap = 1; |
1639 | if (bc_a(jmpins) < J->maxslot) J->maxslot = bc_a(jmpins); | 1960 | if (bc_a(jmpins) < J->maxslot) J->maxslot = bc_a(jmpins); |
1640 | lj_snap_shrink(J); /* Shrink last snapshot if possible. */ | 1961 | lj_snap_shrink(J); /* Shrink last snapshot if possible. */ |
@@ -1654,7 +1975,7 @@ void lj_record_ins(jit_State *J) | |||
1654 | if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) { | 1975 | if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) { |
1655 | switch (J->postproc) { | 1976 | switch (J->postproc) { |
1656 | case LJ_POST_FIXCOMP: /* Fixup comparison. */ | 1977 | case LJ_POST_FIXCOMP: /* Fixup comparison. */ |
1657 | pc = frame_pc(&J2G(J)->tmptv); | 1978 | pc = (const BCIns *)(uintptr_t)J2G(J)->tmptv.u64; |
1658 | rec_comp_fixup(J, pc, (!tvistruecond(&J2G(J)->tmptv2) ^ (bc_op(*pc)&1))); | 1979 | rec_comp_fixup(J, pc, (!tvistruecond(&J2G(J)->tmptv2) ^ (bc_op(*pc)&1))); |
1659 | /* fallthrough */ | 1980 | /* fallthrough */ |
1660 | case LJ_POST_FIXGUARD: /* Fixup and emit pending guard. */ | 1981 | case LJ_POST_FIXGUARD: /* Fixup and emit pending guard. */ |
@@ -1722,6 +2043,10 @@ void lj_record_ins(jit_State *J) | |||
1722 | rec_check_ir(J); | 2043 | rec_check_ir(J); |
1723 | #endif | 2044 | #endif |
1724 | 2045 | ||
2046 | #if LJ_HASPROFILE | ||
2047 | rec_profile_ins(J, pc); | ||
2048 | #endif | ||
2049 | |||
1725 | /* Keep a copy of the runtime values of var/num/str operands. */ | 2050 | /* Keep a copy of the runtime values of var/num/str operands. */ |
1726 | #define rav (&ix.valv) | 2051 | #define rav (&ix.valv) |
1727 | #define rbv (&ix.tabv) | 2052 | #define rbv (&ix.tabv) |
@@ -1748,7 +2073,7 @@ void lj_record_ins(jit_State *J) | |||
1748 | switch (bcmode_c(op)) { | 2073 | switch (bcmode_c(op)) { |
1749 | case BCMvar: | 2074 | case BCMvar: |
1750 | copyTV(J->L, rcv, &lbase[rc]); ix.key = rc = getslot(J, rc); break; | 2075 | copyTV(J->L, rcv, &lbase[rc]); ix.key = rc = getslot(J, rc); break; |
1751 | case BCMpri: setitype(rcv, ~rc); ix.key = rc = TREF_PRI(IRT_NIL+rc); break; | 2076 | case BCMpri: setpriV(rcv, ~rc); ix.key = rc = TREF_PRI(IRT_NIL+rc); break; |
1752 | case BCMnum: { cTValue *tv = proto_knumtv(J->pt, rc); | 2077 | case BCMnum: { cTValue *tv = proto_knumtv(J->pt, rc); |
1753 | copyTV(J->L, rcv, tv); ix.key = rc = tvisint(tv) ? lj_ir_kint(J, intV(tv)) : | 2078 | copyTV(J->L, rcv, tv); ix.key = rc = tvisint(tv) ? lj_ir_kint(J, intV(tv)) : |
1754 | lj_ir_knumint(J, numV(tv)); } break; | 2079 | lj_ir_knumint(J, numV(tv)); } break; |
@@ -1843,6 +2168,18 @@ void lj_record_ins(jit_State *J) | |||
1843 | J->maxslot = bc_a(pc[1]); /* Shrink used slots. */ | 2168 | J->maxslot = bc_a(pc[1]); /* Shrink used slots. */ |
1844 | break; | 2169 | break; |
1845 | 2170 | ||
2171 | case BC_ISTYPE: case BC_ISNUM: | ||
2172 | /* These coercions need to correspond with lj_meta_istype(). */ | ||
2173 | if (LJ_DUALNUM && rc == ~LJ_TNUMX+1) | ||
2174 | ra = lj_opt_narrow_toint(J, ra); | ||
2175 | else if (rc == ~LJ_TNUMX+2) | ||
2176 | ra = lj_ir_tonum(J, ra); | ||
2177 | else if (rc == ~LJ_TSTR+1) | ||
2178 | ra = lj_ir_tostr(J, ra); | ||
2179 | /* else: type specialization suffices. */ | ||
2180 | J->base[bc_a(ins)] = ra; | ||
2181 | break; | ||
2182 | |||
1846 | /* -- Unary ops --------------------------------------------------------- */ | 2183 | /* -- Unary ops --------------------------------------------------------- */ |
1847 | 2184 | ||
1848 | case BC_NOT: | 2185 | case BC_NOT: |
@@ -1906,11 +2243,23 @@ void lj_record_ins(jit_State *J) | |||
1906 | rc = rec_mm_arith(J, &ix, MM_pow); | 2243 | rc = rec_mm_arith(J, &ix, MM_pow); |
1907 | break; | 2244 | break; |
1908 | 2245 | ||
2246 | /* -- Miscellaneous ops ------------------------------------------------- */ | ||
2247 | |||
2248 | case BC_CAT: | ||
2249 | rc = rec_cat(J, rb, rc); | ||
2250 | break; | ||
2251 | |||
1909 | /* -- Constant and move ops --------------------------------------------- */ | 2252 | /* -- Constant and move ops --------------------------------------------- */ |
1910 | 2253 | ||
1911 | case BC_MOV: | 2254 | case BC_MOV: |
1912 | /* Clear gap of method call to avoid resurrecting previous refs. */ | 2255 | /* Clear gap of method call to avoid resurrecting previous refs. */ |
1913 | if (ra > J->maxslot) J->base[ra-1] = 0; | 2256 | if (ra > J->maxslot) { |
2257 | #if LJ_FR2 | ||
2258 | memset(J->base + J->maxslot, 0, (ra - J->maxslot) * sizeof(TRef)); | ||
2259 | #else | ||
2260 | J->base[ra-1] = 0; | ||
2261 | #endif | ||
2262 | } | ||
1914 | break; | 2263 | break; |
1915 | case BC_KSTR: case BC_KNUM: case BC_KPRI: | 2264 | case BC_KSTR: case BC_KNUM: case BC_KPRI: |
1916 | break; | 2265 | break; |
@@ -1918,6 +2267,8 @@ void lj_record_ins(jit_State *J) | |||
1918 | rc = lj_ir_kint(J, (int32_t)(int16_t)rc); | 2267 | rc = lj_ir_kint(J, (int32_t)(int16_t)rc); |
1919 | break; | 2268 | break; |
1920 | case BC_KNIL: | 2269 | case BC_KNIL: |
2270 | if (LJ_FR2 && ra > J->maxslot) | ||
2271 | J->base[ra-1] = 0; | ||
1921 | while (ra <= rc) | 2272 | while (ra <= rc) |
1922 | J->base[ra++] = TREF_NIL; | 2273 | J->base[ra++] = TREF_NIL; |
1923 | if (rc >= J->maxslot) J->maxslot = rc+1; | 2274 | if (rc >= J->maxslot) J->maxslot = rc+1; |
@@ -1954,6 +2305,14 @@ void lj_record_ins(jit_State *J) | |||
1954 | ix.idxchain = LJ_MAX_IDXCHAIN; | 2305 | ix.idxchain = LJ_MAX_IDXCHAIN; |
1955 | rc = lj_record_idx(J, &ix); | 2306 | rc = lj_record_idx(J, &ix); |
1956 | break; | 2307 | break; |
2308 | case BC_TGETR: case BC_TSETR: | ||
2309 | ix.idxchain = 0; | ||
2310 | rc = lj_record_idx(J, &ix); | ||
2311 | break; | ||
2312 | |||
2313 | case BC_TSETM: | ||
2314 | rec_tsetm(J, ra, (BCReg)(J->L->top - J->L->base), (int32_t)rcv->u32.lo); | ||
2315 | break; | ||
1957 | 2316 | ||
1958 | case BC_TNEW: | 2317 | case BC_TNEW: |
1959 | rc = rec_tnew(J, rc); | 2318 | rc = rec_tnew(J, rc); |
@@ -1961,33 +2320,38 @@ void lj_record_ins(jit_State *J) | |||
1961 | case BC_TDUP: | 2320 | case BC_TDUP: |
1962 | rc = emitir(IRTG(IR_TDUP, IRT_TAB), | 2321 | rc = emitir(IRTG(IR_TDUP, IRT_TAB), |
1963 | lj_ir_ktab(J, gco2tab(proto_kgc(J->pt, ~(ptrdiff_t)rc))), 0); | 2322 | lj_ir_ktab(J, gco2tab(proto_kgc(J->pt, ~(ptrdiff_t)rc))), 0); |
2323 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
2324 | J->rbchash[(rc & (RBCHASH_SLOTS-1))].ref = tref_ref(rc); | ||
2325 | setmref(J->rbchash[(rc & (RBCHASH_SLOTS-1))].pc, pc); | ||
2326 | setgcref(J->rbchash[(rc & (RBCHASH_SLOTS-1))].pt, obj2gco(J->pt)); | ||
2327 | #endif | ||
1964 | break; | 2328 | break; |
1965 | 2329 | ||
1966 | /* -- Calls and vararg handling ----------------------------------------- */ | 2330 | /* -- Calls and vararg handling ----------------------------------------- */ |
1967 | 2331 | ||
1968 | case BC_ITERC: | 2332 | case BC_ITERC: |
1969 | J->base[ra] = getslot(J, ra-3); | 2333 | J->base[ra] = getslot(J, ra-3); |
1970 | J->base[ra+1] = getslot(J, ra-2); | 2334 | J->base[ra+1+LJ_FR2] = getslot(J, ra-2); |
1971 | J->base[ra+2] = getslot(J, ra-1); | 2335 | J->base[ra+2+LJ_FR2] = getslot(J, ra-1); |
1972 | { /* Do the actual copy now because lj_record_call needs the values. */ | 2336 | { /* Do the actual copy now because lj_record_call needs the values. */ |
1973 | TValue *b = &J->L->base[ra]; | 2337 | TValue *b = &J->L->base[ra]; |
1974 | copyTV(J->L, b, b-3); | 2338 | copyTV(J->L, b, b-3); |
1975 | copyTV(J->L, b+1, b-2); | 2339 | copyTV(J->L, b+1+LJ_FR2, b-2); |
1976 | copyTV(J->L, b+2, b-1); | 2340 | copyTV(J->L, b+2+LJ_FR2, b-1); |
1977 | } | 2341 | } |
1978 | lj_record_call(J, ra, (ptrdiff_t)rc-1); | 2342 | lj_record_call(J, ra, (ptrdiff_t)rc-1); |
1979 | break; | 2343 | break; |
1980 | 2344 | ||
1981 | /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */ | 2345 | /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */ |
1982 | case BC_CALLM: | 2346 | case BC_CALLM: |
1983 | rc = (BCReg)(J->L->top - J->L->base) - ra; | 2347 | rc = (BCReg)(J->L->top - J->L->base) - ra - LJ_FR2; |
1984 | /* fallthrough */ | 2348 | /* fallthrough */ |
1985 | case BC_CALL: | 2349 | case BC_CALL: |
1986 | lj_record_call(J, ra, (ptrdiff_t)rc-1); | 2350 | lj_record_call(J, ra, (ptrdiff_t)rc-1); |
1987 | break; | 2351 | break; |
1988 | 2352 | ||
1989 | case BC_CALLMT: | 2353 | case BC_CALLMT: |
1990 | rc = (BCReg)(J->L->top - J->L->base) - ra; | 2354 | rc = (BCReg)(J->L->top - J->L->base) - ra - LJ_FR2; |
1991 | /* fallthrough */ | 2355 | /* fallthrough */ |
1992 | case BC_CALLT: | 2356 | case BC_CALLT: |
1993 | lj_record_tailcall(J, ra, (ptrdiff_t)rc-1); | 2357 | lj_record_tailcall(J, ra, (ptrdiff_t)rc-1); |
@@ -2004,6 +2368,9 @@ void lj_record_ins(jit_State *J) | |||
2004 | rc = (BCReg)(J->L->top - J->L->base) - ra + 1; | 2368 | rc = (BCReg)(J->L->top - J->L->base) - ra + 1; |
2005 | /* fallthrough */ | 2369 | /* fallthrough */ |
2006 | case BC_RET: case BC_RET0: case BC_RET1: | 2370 | case BC_RET: case BC_RET0: case BC_RET1: |
2371 | #if LJ_HASPROFILE | ||
2372 | rec_profile_ret(J); | ||
2373 | #endif | ||
2007 | lj_record_ret(J, ra, (ptrdiff_t)rc-1); | 2374 | lj_record_ret(J, ra, (ptrdiff_t)rc-1); |
2008 | break; | 2375 | break; |
2009 | 2376 | ||
@@ -2016,7 +2383,7 @@ void lj_record_ins(jit_State *J) | |||
2016 | case BC_JFORI: | 2383 | case BC_JFORI: |
2017 | lua_assert(bc_op(pc[(ptrdiff_t)rc-BCBIAS_J]) == BC_JFORL); | 2384 | lua_assert(bc_op(pc[(ptrdiff_t)rc-BCBIAS_J]) == BC_JFORL); |
2018 | if (rec_for(J, pc, 0) != LOOPEV_LEAVE) /* Link to existing loop. */ | 2385 | if (rec_for(J, pc, 0) != LOOPEV_LEAVE) /* Link to existing loop. */ |
2019 | rec_stop(J, LJ_TRLINK_ROOT, bc_d(pc[(ptrdiff_t)rc-BCBIAS_J])); | 2386 | lj_record_stop(J, LJ_TRLINK_ROOT, bc_d(pc[(ptrdiff_t)rc-BCBIAS_J])); |
2020 | /* Continue tracing if the loop is not entered. */ | 2387 | /* Continue tracing if the loop is not entered. */ |
2021 | break; | 2388 | break; |
2022 | 2389 | ||
@@ -2083,10 +2450,8 @@ void lj_record_ins(jit_State *J) | |||
2083 | /* fallthrough */ | 2450 | /* fallthrough */ |
2084 | case BC_ITERN: | 2451 | case BC_ITERN: |
2085 | case BC_ISNEXT: | 2452 | case BC_ISNEXT: |
2086 | case BC_CAT: | ||
2087 | case BC_UCLO: | 2453 | case BC_UCLO: |
2088 | case BC_FNEW: | 2454 | case BC_FNEW: |
2089 | case BC_TSETM: | ||
2090 | setintV(&J->errinfo, (int32_t)op); | 2455 | setintV(&J->errinfo, (int32_t)op); |
2091 | lj_trace_err_info(J, LJ_TRERR_NYIBC); | 2456 | lj_trace_err_info(J, LJ_TRERR_NYIBC); |
2092 | break; | 2457 | break; |
@@ -2095,15 +2460,21 @@ void lj_record_ins(jit_State *J) | |||
2095 | /* rc == 0 if we have no result yet, e.g. pending __index metamethod call. */ | 2460 | /* rc == 0 if we have no result yet, e.g. pending __index metamethod call. */ |
2096 | if (bcmode_a(op) == BCMdst && rc) { | 2461 | if (bcmode_a(op) == BCMdst && rc) { |
2097 | J->base[ra] = rc; | 2462 | J->base[ra] = rc; |
2098 | if (ra >= J->maxslot) J->maxslot = ra+1; | 2463 | if (ra >= J->maxslot) { |
2464 | #if LJ_FR2 | ||
2465 | if (ra > J->maxslot) J->base[ra-1] = 0; | ||
2466 | #endif | ||
2467 | J->maxslot = ra+1; | ||
2468 | } | ||
2099 | } | 2469 | } |
2100 | 2470 | ||
2101 | #undef rav | 2471 | #undef rav |
2102 | #undef rbv | 2472 | #undef rbv |
2103 | #undef rcv | 2473 | #undef rcv |
2104 | 2474 | ||
2105 | /* Limit the number of recorded IR instructions. */ | 2475 | /* Limit the number of recorded IR instructions and constants. */ |
2106 | if (J->cur.nins > REF_FIRST+(IRRef)J->param[JIT_P_maxrecord]) | 2476 | if (J->cur.nins > REF_FIRST+(IRRef)J->param[JIT_P_maxrecord] || |
2477 | J->cur.nk < REF_BIAS-(IRRef)J->param[JIT_P_maxirconst]) | ||
2107 | lj_trace_err(J, LJ_TRERR_TRACEOV); | 2478 | lj_trace_err(J, LJ_TRERR_TRACEOV); |
2108 | } | 2479 | } |
2109 | 2480 | ||
@@ -2152,6 +2523,12 @@ static const BCIns *rec_setup_root(jit_State *J) | |||
2152 | J->maxslot = J->pt->numparams; | 2523 | J->maxslot = J->pt->numparams; |
2153 | pc++; | 2524 | pc++; |
2154 | break; | 2525 | break; |
2526 | case BC_CALLM: | ||
2527 | case BC_CALL: | ||
2528 | case BC_ITERC: | ||
2529 | /* No bytecode range check for stitched traces. */ | ||
2530 | pc++; | ||
2531 | break; | ||
2155 | default: | 2532 | default: |
2156 | lua_assert(0); | 2533 | lua_assert(0); |
2157 | break; | 2534 | break; |
@@ -2167,11 +2544,14 @@ void lj_record_setup(jit_State *J) | |||
2167 | /* Initialize state related to current trace. */ | 2544 | /* Initialize state related to current trace. */ |
2168 | memset(J->slot, 0, sizeof(J->slot)); | 2545 | memset(J->slot, 0, sizeof(J->slot)); |
2169 | memset(J->chain, 0, sizeof(J->chain)); | 2546 | memset(J->chain, 0, sizeof(J->chain)); |
2547 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
2548 | memset(J->rbchash, 0, sizeof(J->rbchash)); | ||
2549 | #endif | ||
2170 | memset(J->bpropcache, 0, sizeof(J->bpropcache)); | 2550 | memset(J->bpropcache, 0, sizeof(J->bpropcache)); |
2171 | J->scev.idx = REF_NIL; | 2551 | J->scev.idx = REF_NIL; |
2172 | setmref(J->scev.pc, NULL); | 2552 | setmref(J->scev.pc, NULL); |
2173 | 2553 | ||
2174 | J->baseslot = 1; /* Invoking function is at base[-1]. */ | 2554 | J->baseslot = 1+LJ_FR2; /* Invoking function is at base[-1-LJ_FR2]. */ |
2175 | J->base = J->slot + J->baseslot; | 2555 | J->base = J->slot + J->baseslot; |
2176 | J->maxslot = 0; | 2556 | J->maxslot = 0; |
2177 | J->framedepth = 0; | 2557 | J->framedepth = 0; |
@@ -2186,7 +2566,7 @@ void lj_record_setup(jit_State *J) | |||
2186 | J->bc_extent = ~(MSize)0; | 2566 | J->bc_extent = ~(MSize)0; |
2187 | 2567 | ||
2188 | /* Emit instructions for fixed references. Also triggers initial IR alloc. */ | 2568 | /* Emit instructions for fixed references. Also triggers initial IR alloc. */ |
2189 | emitir_raw(IRT(IR_BASE, IRT_P32), J->parent, J->exitno); | 2569 | emitir_raw(IRT(IR_BASE, IRT_PGC), J->parent, J->exitno); |
2190 | for (i = 0; i <= 2; i++) { | 2570 | for (i = 0; i <= 2; i++) { |
2191 | IRIns *ir = IR(REF_NIL-i); | 2571 | IRIns *ir = IR(REF_NIL-i); |
2192 | ir->i = 0; | 2572 | ir->i = 0; |
@@ -2220,7 +2600,7 @@ void lj_record_setup(jit_State *J) | |||
2220 | if (traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] || | 2600 | if (traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] || |
2221 | T->snap[J->exitno].count >= J->param[JIT_P_hotexit] + | 2601 | T->snap[J->exitno].count >= J->param[JIT_P_hotexit] + |
2222 | J->param[JIT_P_tryside]) { | 2602 | J->param[JIT_P_tryside]) { |
2223 | rec_stop(J, LJ_TRLINK_INTERP, 0); | 2603 | lj_record_stop(J, LJ_TRLINK_INTERP, 0); |
2224 | } | 2604 | } |
2225 | } else { /* Root trace. */ | 2605 | } else { /* Root trace. */ |
2226 | J->cur.root = 0; | 2606 | J->cur.root = 0; |
@@ -2232,9 +2612,15 @@ void lj_record_setup(jit_State *J) | |||
2232 | lj_snap_add(J); | 2612 | lj_snap_add(J); |
2233 | if (bc_op(J->cur.startins) == BC_FORL) | 2613 | if (bc_op(J->cur.startins) == BC_FORL) |
2234 | rec_for_loop(J, J->pc-1, &J->scev, 1); | 2614 | rec_for_loop(J, J->pc-1, &J->scev, 1); |
2615 | else if (bc_op(J->cur.startins) == BC_ITERC) | ||
2616 | J->startpc = NULL; | ||
2235 | if (1 + J->pt->framesize >= LJ_MAX_JSLOTS) | 2617 | if (1 + J->pt->framesize >= LJ_MAX_JSLOTS) |
2236 | lj_trace_err(J, LJ_TRERR_STACKOV); | 2618 | lj_trace_err(J, LJ_TRERR_STACKOV); |
2237 | } | 2619 | } |
2620 | #if LJ_HASPROFILE | ||
2621 | J->prev_pt = NULL; | ||
2622 | J->prev_line = -1; | ||
2623 | #endif | ||
2238 | #ifdef LUAJIT_ENABLE_CHECKHOOK | 2624 | #ifdef LUAJIT_ENABLE_CHECKHOOK |
2239 | /* Regularly check for instruction/line hooks from compiled code and | 2625 | /* Regularly check for instruction/line hooks from compiled code and |
2240 | ** exit to the interpreter if the hooks are set. | 2626 | ** exit to the interpreter if the hooks are set. |