diff options
Diffstat (limited to 'src/lj_record.c')
-rw-r--r-- | src/lj_record.c | 978 |
1 files changed, 776 insertions, 202 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index 0e14382c..9d0021a6 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" |
@@ -30,6 +33,7 @@ | |||
30 | #include "lj_snap.h" | 33 | #include "lj_snap.h" |
31 | #include "lj_dispatch.h" | 34 | #include "lj_dispatch.h" |
32 | #include "lj_vm.h" | 35 | #include "lj_vm.h" |
36 | #include "lj_prng.h" | ||
33 | 37 | ||
34 | /* Some local macros to save typing. Undef'd at the end. */ | 38 | /* Some local macros to save typing. Undef'd at the end. */ |
35 | #define IR(ref) (&J->cur.ir[(ref)]) | 39 | #define IR(ref) (&J->cur.ir[(ref)]) |
@@ -47,31 +51,52 @@ | |||
47 | static void rec_check_ir(jit_State *J) | 51 | static void rec_check_ir(jit_State *J) |
48 | { | 52 | { |
49 | IRRef i, nins = J->cur.nins, nk = J->cur.nk; | 53 | IRRef i, nins = J->cur.nins, nk = J->cur.nk; |
50 | lua_assert(nk <= REF_BIAS && nins >= REF_BIAS && nins < 65536); | 54 | lj_assertJ(nk <= REF_BIAS && nins >= REF_BIAS && nins < 65536, |
51 | for (i = nins-1; i >= nk; i--) { | 55 | "inconsistent IR layout"); |
56 | for (i = nk; i < nins; i++) { | ||
52 | IRIns *ir = IR(i); | 57 | IRIns *ir = IR(i); |
53 | uint32_t mode = lj_ir_mode[ir->o]; | 58 | uint32_t mode = lj_ir_mode[ir->o]; |
54 | IRRef op1 = ir->op1; | 59 | IRRef op1 = ir->op1; |
55 | IRRef op2 = ir->op2; | 60 | IRRef op2 = ir->op2; |
61 | const char *err = NULL; | ||
56 | switch (irm_op1(mode)) { | 62 | switch (irm_op1(mode)) { |
57 | case IRMnone: lua_assert(op1 == 0); break; | 63 | case IRMnone: |
58 | case IRMref: lua_assert(op1 >= nk); | 64 | if (op1 != 0) err = "IRMnone op1 used"; |
59 | lua_assert(i >= REF_BIAS ? op1 < i : op1 > i); break; | 65 | break; |
66 | case IRMref: | ||
67 | if (op1 < nk || (i >= REF_BIAS ? op1 >= i : op1 <= i)) | ||
68 | err = "IRMref op1 out of range"; | ||
69 | break; | ||
60 | case IRMlit: break; | 70 | case IRMlit: break; |
61 | case IRMcst: lua_assert(i < REF_BIAS); continue; | 71 | case IRMcst: |
72 | if (i >= REF_BIAS) { err = "constant in IR range"; break; } | ||
73 | if (irt_is64(ir->t) && ir->o != IR_KNULL) | ||
74 | i++; | ||
75 | continue; | ||
62 | } | 76 | } |
63 | switch (irm_op2(mode)) { | 77 | switch (irm_op2(mode)) { |
64 | case IRMnone: lua_assert(op2 == 0); break; | 78 | case IRMnone: |
65 | case IRMref: lua_assert(op2 >= nk); | 79 | if (op2) err = "IRMnone op2 used"; |
66 | lua_assert(i >= REF_BIAS ? op2 < i : op2 > i); break; | 80 | break; |
81 | case IRMref: | ||
82 | if (op2 < nk || (i >= REF_BIAS ? op2 >= i : op2 <= i)) | ||
83 | err = "IRMref op2 out of range"; | ||
84 | break; | ||
67 | case IRMlit: break; | 85 | case IRMlit: break; |
68 | case IRMcst: lua_assert(0); break; | 86 | case IRMcst: err = "IRMcst op2"; break; |
69 | } | 87 | } |
70 | if (ir->prev) { | 88 | if (!err && ir->prev) { |
71 | lua_assert(ir->prev >= nk); | 89 | if (ir->prev < nk || (i >= REF_BIAS ? ir->prev >= i : ir->prev <= i)) |
72 | lua_assert(i >= REF_BIAS ? ir->prev < i : ir->prev > i); | 90 | err = "chain out of range"; |
73 | lua_assert(ir->o == IR_NOP || IR(ir->prev)->o == ir->o); | 91 | else if (ir->o != IR_NOP && IR(ir->prev)->o != ir->o) |
92 | err = "chain to different op"; | ||
74 | } | 93 | } |
94 | lj_assertJ(!err, "bad IR %04d op %d(%04d,%04d): %s", | ||
95 | i-REF_BIAS, | ||
96 | ir->o, | ||
97 | irm_op1(mode) == IRMref ? op1-REF_BIAS : op1, | ||
98 | irm_op2(mode) == IRMref ? op2-REF_BIAS : op2, | ||
99 | err); | ||
75 | } | 100 | } |
76 | } | 101 | } |
77 | 102 | ||
@@ -81,48 +106,80 @@ static void rec_check_slots(jit_State *J) | |||
81 | BCReg s, nslots = J->baseslot + J->maxslot; | 106 | BCReg s, nslots = J->baseslot + J->maxslot; |
82 | int32_t depth = 0; | 107 | int32_t depth = 0; |
83 | cTValue *base = J->L->base - J->baseslot; | 108 | cTValue *base = J->L->base - J->baseslot; |
84 | lua_assert(J->baseslot >= 1); | 109 | lj_assertJ(J->baseslot >= 1+LJ_FR2, "bad baseslot"); |
85 | lua_assert(J->baseslot == 1 || (J->slot[J->baseslot-1] & TREF_FRAME)); | 110 | lj_assertJ(J->baseslot == 1+LJ_FR2 || (J->slot[J->baseslot-1] & TREF_FRAME), |
86 | lua_assert(nslots <= LJ_MAX_JSLOTS); | 111 | "baseslot does not point to frame"); |
112 | lj_assertJ(nslots <= LJ_MAX_JSLOTS, "slot overflow"); | ||
87 | for (s = 0; s < nslots; s++) { | 113 | for (s = 0; s < nslots; s++) { |
88 | TRef tr = J->slot[s]; | 114 | TRef tr = J->slot[s]; |
89 | if (tr) { | 115 | if (tr) { |
90 | cTValue *tv = &base[s]; | 116 | cTValue *tv = &base[s]; |
91 | IRRef ref = tref_ref(tr); | 117 | IRRef ref = tref_ref(tr); |
92 | IRIns *ir; | 118 | IRIns *ir = NULL; /* Silence compiler. */ |
93 | lua_assert(ref >= J->cur.nk && ref < J->cur.nins); | 119 | lj_assertJ(tv < J->L->top, "slot %d above top of Lua stack", s); |
94 | ir = IR(ref); | 120 | if (!LJ_FR2 || ref || !(tr & (TREF_FRAME | TREF_CONT))) { |
95 | lua_assert(irt_t(ir->t) == tref_t(tr)); | 121 | lj_assertJ(ref >= J->cur.nk && ref < J->cur.nins, |
122 | "slot %d ref %04d out of range", s, ref - REF_BIAS); | ||
123 | ir = IR(ref); | ||
124 | lj_assertJ(irt_t(ir->t) == tref_t(tr), "slot %d IR type mismatch", s); | ||
125 | } | ||
96 | if (s == 0) { | 126 | if (s == 0) { |
97 | lua_assert(tref_isfunc(tr)); | 127 | lj_assertJ(tref_isfunc(tr), "frame slot 0 is not a function"); |
128 | #if LJ_FR2 | ||
129 | } else if (s == 1) { | ||
130 | lj_assertJ((tr & ~TREF_FRAME) == 0, "bad frame slot 1"); | ||
131 | #endif | ||
98 | } else if ((tr & TREF_FRAME)) { | 132 | } else if ((tr & TREF_FRAME)) { |
99 | GCfunc *fn = gco2func(frame_gc(tv)); | 133 | GCfunc *fn = gco2func(frame_gc(tv)); |
100 | BCReg delta = (BCReg)(tv - frame_prev(tv)); | 134 | BCReg delta = (BCReg)(tv - frame_prev(tv)); |
101 | lua_assert(tref_isfunc(tr)); | 135 | #if LJ_FR2 |
102 | if (tref_isk(tr)) lua_assert(fn == ir_kfunc(ir)); | 136 | lj_assertJ(!ref || ir_knum(ir)->u64 == tv->u64, |
103 | lua_assert(s > delta ? (J->slot[s-delta] & TREF_FRAME) : (s == delta)); | 137 | "frame slot %d PC mismatch", s); |
138 | tr = J->slot[s-1]; | ||
139 | ir = IR(tref_ref(tr)); | ||
140 | #endif | ||
141 | lj_assertJ(tref_isfunc(tr), | ||
142 | "frame slot %d is not a function", s-LJ_FR2); | ||
143 | lj_assertJ(!tref_isk(tr) || fn == ir_kfunc(ir), | ||
144 | "frame slot %d function mismatch", s-LJ_FR2); | ||
145 | lj_assertJ(s > delta + LJ_FR2 ? (J->slot[s-delta] & TREF_FRAME) | ||
146 | : (s == delta + LJ_FR2), | ||
147 | "frame slot %d broken chain", s-LJ_FR2); | ||
104 | depth++; | 148 | depth++; |
105 | } else if ((tr & TREF_CONT)) { | 149 | } else if ((tr & TREF_CONT)) { |
106 | lua_assert(ir_kptr(ir) == gcrefp(tv->gcr, void)); | 150 | #if LJ_FR2 |
107 | lua_assert((J->slot[s+1] & TREF_FRAME)); | 151 | lj_assertJ(!ref || ir_knum(ir)->u64 == tv->u64, |
152 | "cont slot %d continuation mismatch", s); | ||
153 | #else | ||
154 | lj_assertJ(ir_kptr(ir) == gcrefp(tv->gcr, void), | ||
155 | "cont slot %d continuation mismatch", s); | ||
156 | #endif | ||
157 | lj_assertJ((J->slot[s+1+LJ_FR2] & TREF_FRAME), | ||
158 | "cont slot %d not followed by frame", s); | ||
108 | depth++; | 159 | depth++; |
160 | } else if ((tr & TREF_KEYINDEX)) { | ||
161 | lj_assertJ(tref_isint(tr), "keyindex slot %d bad type %d", | ||
162 | s, tref_type(tr)); | ||
109 | } else { | 163 | } else { |
110 | if (tvisnumber(tv)) | 164 | /* Number repr. may differ, but other types must be the same. */ |
111 | lua_assert(tref_isnumber(tr)); /* Could be IRT_INT etc., too. */ | 165 | lj_assertJ(tvisnumber(tv) ? tref_isnumber(tr) : |
112 | else | 166 | itype2irt(tv) == tref_type(tr), |
113 | lua_assert(itype2irt(tv) == tref_type(tr)); | 167 | "slot %d type mismatch: stack type %d vs IR type %d", |
168 | s, itypemap(tv), tref_type(tr)); | ||
114 | if (tref_isk(tr)) { /* Compare constants. */ | 169 | if (tref_isk(tr)) { /* Compare constants. */ |
115 | TValue tvk; | 170 | TValue tvk; |
116 | lj_ir_kvalue(J->L, &tvk, ir); | 171 | lj_ir_kvalue(J->L, &tvk, ir); |
117 | if (!(tvisnum(&tvk) && tvisnan(&tvk))) | 172 | lj_assertJ((tvisnum(&tvk) && tvisnan(&tvk)) ? |
118 | lua_assert(lj_obj_equal(tv, &tvk)); | 173 | (tvisnum(tv) && tvisnan(tv)) : |
119 | else | 174 | lj_obj_equal(tv, &tvk), |
120 | lua_assert(tvisnum(tv) && tvisnan(tv)); | 175 | "slot %d const mismatch: stack %016llx vs IR %016llx", |
176 | s, tv->u64, tvk.u64); | ||
121 | } | 177 | } |
122 | } | 178 | } |
123 | } | 179 | } |
124 | } | 180 | } |
125 | lua_assert(J->framedepth == depth); | 181 | lj_assertJ(J->framedepth == depth, |
182 | "frame depth mismatch %d vs %d", J->framedepth, depth); | ||
126 | } | 183 | } |
127 | #endif | 184 | #endif |
128 | 185 | ||
@@ -156,10 +213,11 @@ static TRef sload(jit_State *J, int32_t slot) | |||
156 | /* Get TRef for current function. */ | 213 | /* Get TRef for current function. */ |
157 | static TRef getcurrf(jit_State *J) | 214 | static TRef getcurrf(jit_State *J) |
158 | { | 215 | { |
159 | if (J->base[-1]) | 216 | if (J->base[-1-LJ_FR2]) |
160 | return J->base[-1]; | 217 | return J->base[-1-LJ_FR2]; |
161 | lua_assert(J->baseslot == 1); | 218 | /* Non-base frame functions ought to be loaded already. */ |
162 | return sloadt(J, -1, IRT_FUNC, IRSLOAD_READONLY); | 219 | lj_assertJ(J->baseslot == 1+LJ_FR2, "bad baseslot"); |
220 | return sloadt(J, -1-LJ_FR2, IRT_FUNC, IRSLOAD_READONLY); | ||
163 | } | 221 | } |
164 | 222 | ||
165 | /* Compare for raw object equality. | 223 | /* Compare for raw object equality. |
@@ -205,6 +263,14 @@ TRef lj_record_constify(jit_State *J, cTValue *o) | |||
205 | return 0; /* Can't represent lightuserdata (pointless). */ | 263 | return 0; /* Can't represent lightuserdata (pointless). */ |
206 | } | 264 | } |
207 | 265 | ||
266 | /* Emit a VLOAD with the correct type. */ | ||
267 | TRef lj_record_vload(jit_State *J, TRef ref, MSize idx, IRType t) | ||
268 | { | ||
269 | TRef tr = emitir(IRTG(IR_VLOAD, t), ref, idx); | ||
270 | if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ | ||
271 | return tr; | ||
272 | } | ||
273 | |||
208 | /* -- Record loop ops ----------------------------------------------------- */ | 274 | /* -- Record loop ops ----------------------------------------------------- */ |
209 | 275 | ||
210 | /* Loop event. */ | 276 | /* Loop event. */ |
@@ -221,17 +287,21 @@ static void canonicalize_slots(jit_State *J) | |||
221 | if (LJ_DUALNUM) return; | 287 | if (LJ_DUALNUM) return; |
222 | for (s = J->baseslot+J->maxslot-1; s >= 1; s--) { | 288 | for (s = J->baseslot+J->maxslot-1; s >= 1; s--) { |
223 | TRef tr = J->slot[s]; | 289 | TRef tr = J->slot[s]; |
224 | if (tref_isinteger(tr)) { | 290 | if (tref_isinteger(tr) && !(tr & TREF_KEYINDEX)) { |
225 | IRIns *ir = IR(tref_ref(tr)); | 291 | IRIns *ir = IR(tref_ref(tr)); |
226 | if (!(ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_READONLY))) | 292 | if (!(ir->o == IR_SLOAD && (ir->op2 & (IRSLOAD_READONLY)))) |
227 | J->slot[s] = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT); | 293 | J->slot[s] = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT); |
228 | } | 294 | } |
229 | } | 295 | } |
230 | } | 296 | } |
231 | 297 | ||
232 | /* Stop recording. */ | 298 | /* Stop recording. */ |
233 | static void rec_stop(jit_State *J, TraceLink linktype, TraceNo lnk) | 299 | void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk) |
234 | { | 300 | { |
301 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
302 | if (J->retryrec) | ||
303 | lj_trace_err(J, LJ_TRERR_RETRY); | ||
304 | #endif | ||
235 | lj_trace_end(J); | 305 | lj_trace_end(J); |
236 | J->cur.linktype = (uint8_t)linktype; | 306 | J->cur.linktype = (uint8_t)linktype; |
237 | J->cur.link = (uint16_t)lnk; | 307 | J->cur.link = (uint16_t)lnk; |
@@ -399,7 +469,8 @@ static void rec_for_loop(jit_State *J, const BCIns *fori, ScEvEntry *scev, | |||
399 | TRef stop = fori_arg(J, fori, ra+FORL_STOP, t, mode); | 469 | TRef stop = fori_arg(J, fori, ra+FORL_STOP, t, mode); |
400 | TRef step = fori_arg(J, fori, ra+FORL_STEP, t, mode); | 470 | TRef step = fori_arg(J, fori, ra+FORL_STEP, t, mode); |
401 | int tc, dir = rec_for_direction(&tv[FORL_STEP]); | 471 | int tc, dir = rec_for_direction(&tv[FORL_STEP]); |
402 | lua_assert(bc_op(*fori) == BC_FORI || bc_op(*fori) == BC_JFORI); | 472 | lj_assertJ(bc_op(*fori) == BC_FORI || bc_op(*fori) == BC_JFORI, |
473 | "bad bytecode %d instead of FORI/JFORI", bc_op(*fori)); | ||
403 | scev->t.irt = t; | 474 | scev->t.irt = t; |
404 | scev->dir = dir; | 475 | scev->dir = dir; |
405 | scev->stop = tref_ref(stop); | 476 | scev->stop = tref_ref(stop); |
@@ -455,7 +526,7 @@ static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) | |||
455 | IRT_NUM; | 526 | IRT_NUM; |
456 | for (i = FORL_IDX; i <= FORL_STEP; i++) { | 527 | for (i = FORL_IDX; i <= FORL_STEP; i++) { |
457 | if (!tr[i]) sload(J, ra+i); | 528 | if (!tr[i]) sload(J, ra+i); |
458 | lua_assert(tref_isnumber_str(tr[i])); | 529 | lj_assertJ(tref_isnumber_str(tr[i]), "bad FORI argument type"); |
459 | if (tref_isstr(tr[i])) | 530 | if (tref_isstr(tr[i])) |
460 | tr[i] = emitir(IRTG(IR_STRTO, IRT_NUM), tr[i], 0); | 531 | tr[i] = emitir(IRTG(IR_STRTO, IRT_NUM), tr[i], 0); |
461 | if (t == IRT_INT) { | 532 | if (t == IRT_INT) { |
@@ -499,8 +570,7 @@ static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) | |||
499 | static LoopEvent rec_iterl(jit_State *J, const BCIns iterins) | 570 | static LoopEvent rec_iterl(jit_State *J, const BCIns iterins) |
500 | { | 571 | { |
501 | BCReg ra = bc_a(iterins); | 572 | BCReg ra = bc_a(iterins); |
502 | lua_assert(J->base[ra] != 0); | 573 | 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. */ | 574 | J->base[ra-1] = J->base[ra]; /* Copy result of ITERC to control var. */ |
505 | J->maxslot = ra-1+bc_b(J->pc[-1]); | 575 | J->maxslot = ra-1+bc_b(J->pc[-1]); |
506 | J->pc += bc_j(iterins)+1; | 576 | J->pc += bc_j(iterins)+1; |
@@ -538,12 +608,13 @@ static int innerloopleft(jit_State *J, const BCIns *pc) | |||
538 | /* Handle the case when an interpreted loop op is hit. */ | 608 | /* Handle the case when an interpreted loop op is hit. */ |
539 | static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) | 609 | static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) |
540 | { | 610 | { |
541 | if (J->parent == 0) { | 611 | if (J->parent == 0 && J->exitno == 0) { |
542 | if (pc == J->startpc && J->framedepth + J->retdepth == 0) { | 612 | if (pc == J->startpc && J->framedepth + J->retdepth == 0) { |
613 | if (bc_op(J->cur.startins) == BC_ITERN) return; /* See rec_itern(). */ | ||
543 | /* Same loop? */ | 614 | /* Same loop? */ |
544 | if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */ | 615 | if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */ |
545 | lj_trace_err(J, LJ_TRERR_LLEAVE); | 616 | lj_trace_err(J, LJ_TRERR_LLEAVE); |
546 | rec_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping root trace. */ | 617 | lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */ |
547 | } else if (ev != LOOPEV_LEAVE) { /* Entering inner loop? */ | 618 | } else if (ev != LOOPEV_LEAVE) { /* Entering inner loop? */ |
548 | /* It's usually better to abort here and wait until the inner loop | 619 | /* 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, | 620 | ** is traced. But if the inner loop repeatedly didn't loop back, |
@@ -568,18 +639,136 @@ 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. */ | 639 | /* Handle the case when an already compiled loop op is hit. */ |
569 | static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev) | 640 | static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev) |
570 | { | 641 | { |
571 | if (J->parent == 0) { /* Root trace hit an inner loop. */ | 642 | 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. */ | 643 | /* Better let the inner loop spawn a side trace back here. */ |
573 | lj_trace_err(J, LJ_TRERR_LINNER); | 644 | lj_trace_err(J, LJ_TRERR_LINNER); |
574 | } else if (ev != LOOPEV_LEAVE) { /* Side trace enters a compiled loop. */ | 645 | } else if (ev != LOOPEV_LEAVE) { /* Side trace enters a compiled loop. */ |
575 | J->instunroll = 0; /* Cannot continue across a compiled loop op. */ | 646 | J->instunroll = 0; /* Cannot continue across a compiled loop op. */ |
576 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) | 647 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) |
577 | rec_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Form an extra loop. */ | 648 | lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Form extra loop. */ |
578 | else | 649 | else |
579 | rec_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the loop. */ | 650 | 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. */ | 651 | } /* Side trace continues across a loop that's left or not entered. */ |
581 | } | 652 | } |
582 | 653 | ||
654 | /* Record ITERN. */ | ||
655 | static LoopEvent rec_itern(jit_State *J, BCReg ra, BCReg rb) | ||
656 | { | ||
657 | #if LJ_BE | ||
658 | /* YAGNI: Disabled on big-endian due to issues with lj_vm_next, | ||
659 | ** IR_HIOP, RID_RETLO/RID_RETHI and ra_destpair. | ||
660 | */ | ||
661 | UNUSED(ra); UNUSED(rb); | ||
662 | setintV(&J->errinfo, (int32_t)BC_ITERN); | ||
663 | lj_trace_err_info(J, LJ_TRERR_NYIBC); | ||
664 | #else | ||
665 | RecordIndex ix; | ||
666 | /* Since ITERN is recorded at the start, we need our own loop detection. */ | ||
667 | if (J->pc == J->startpc && | ||
668 | J->framedepth + J->retdepth == 0 && J->parent == 0 && J->exitno == 0) { | ||
669 | IRRef ref = REF_FIRST + LJ_HASPROFILE; | ||
670 | #ifdef LUAJIT_ENABLE_CHECKHOOK | ||
671 | ref += 3; | ||
672 | #endif | ||
673 | if (J->cur.nins > ref || | ||
674 | (LJ_HASPROFILE && J->cur.nins == ref && J->cur.ir[ref-1].o != IR_PROF)) { | ||
675 | J->instunroll = 0; /* Cannot continue unrolling across an ITERN. */ | ||
676 | lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */ | ||
677 | return LOOPEV_ENTER; | ||
678 | } | ||
679 | } | ||
680 | J->maxslot = ra; | ||
681 | lj_snap_add(J); /* Required to make JLOOP the first ins in a side-trace. */ | ||
682 | ix.tab = getslot(J, ra-2); | ||
683 | ix.key = J->base[ra-1] ? J->base[ra-1] : | ||
684 | sloadt(J, (int32_t)(ra-1), IRT_GUARD|IRT_INT, | ||
685 | IRSLOAD_TYPECHECK|IRSLOAD_KEYINDEX); | ||
686 | copyTV(J->L, &ix.tabv, &J->L->base[ra-2]); | ||
687 | copyTV(J->L, &ix.keyv, &J->L->base[ra-1]); | ||
688 | ix.idxchain = (rb < 3); /* Omit value type check, if unused. */ | ||
689 | ix.mobj = 1; /* We need the next index, too. */ | ||
690 | J->maxslot = ra + lj_record_next(J, &ix); | ||
691 | J->needsnap = 1; | ||
692 | if (!tref_isnil(ix.key)) { /* Looping back? */ | ||
693 | J->base[ra-1] = ix.mobj | TREF_KEYINDEX; /* Control var has next index. */ | ||
694 | J->base[ra] = ix.key; | ||
695 | J->base[ra+1] = ix.val; | ||
696 | J->pc += bc_j(J->pc[1])+2; | ||
697 | return LOOPEV_ENTER; | ||
698 | } else { | ||
699 | J->maxslot = ra-3; | ||
700 | J->pc += 2; | ||
701 | return LOOPEV_LEAVE; | ||
702 | } | ||
703 | #endif | ||
704 | } | ||
705 | |||
706 | /* Record ISNEXT. */ | ||
707 | static void rec_isnext(jit_State *J, BCReg ra) | ||
708 | { | ||
709 | cTValue *b = &J->L->base[ra-3]; | ||
710 | if (tvisfunc(b) && funcV(b)->c.ffid == FF_next && | ||
711 | tvistab(b+1) && tvisnil(b+2)) { | ||
712 | /* These checks are folded away for a compiled pairs(). */ | ||
713 | TRef func = getslot(J, ra-3); | ||
714 | TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), func, IRFL_FUNC_FFID); | ||
715 | emitir(IRTGI(IR_EQ), trid, lj_ir_kint(J, FF_next)); | ||
716 | (void)getslot(J, ra-2); /* Type check for table. */ | ||
717 | (void)getslot(J, ra-1); /* Type check for nil key. */ | ||
718 | J->base[ra-1] = lj_ir_kint(J, 0) | TREF_KEYINDEX; | ||
719 | J->maxslot = ra; | ||
720 | } else { /* Abort trace. Interpreter will despecialize bytecode. */ | ||
721 | lj_trace_err(J, LJ_TRERR_RECERR); | ||
722 | } | ||
723 | } | ||
724 | |||
725 | /* -- Record profiler hook checks ----------------------------------------- */ | ||
726 | |||
727 | #if LJ_HASPROFILE | ||
728 | |||
729 | /* Need to insert profiler hook check? */ | ||
730 | static int rec_profile_need(jit_State *J, GCproto *pt, const BCIns *pc) | ||
731 | { | ||
732 | GCproto *ppt; | ||
733 | lj_assertJ(J->prof_mode == 'f' || J->prof_mode == 'l', | ||
734 | "bad profiler mode %c", J->prof_mode); | ||
735 | if (!pt) | ||
736 | return 0; | ||
737 | ppt = J->prev_pt; | ||
738 | J->prev_pt = pt; | ||
739 | if (pt != ppt && ppt) { | ||
740 | J->prev_line = -1; | ||
741 | return 1; | ||
742 | } | ||
743 | if (J->prof_mode == 'l') { | ||
744 | BCLine line = lj_debug_line(pt, proto_bcpos(pt, pc)); | ||
745 | BCLine pline = J->prev_line; | ||
746 | J->prev_line = line; | ||
747 | if (pline != line) | ||
748 | return 1; | ||
749 | } | ||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | static void rec_profile_ins(jit_State *J, const BCIns *pc) | ||
754 | { | ||
755 | if (J->prof_mode && rec_profile_need(J, J->pt, pc)) { | ||
756 | emitir(IRTG(IR_PROF, IRT_NIL), 0, 0); | ||
757 | lj_snap_add(J); | ||
758 | } | ||
759 | } | ||
760 | |||
761 | static void rec_profile_ret(jit_State *J) | ||
762 | { | ||
763 | if (J->prof_mode == 'f') { | ||
764 | emitir(IRTG(IR_PROF, IRT_NIL), 0, 0); | ||
765 | J->prev_pt = NULL; | ||
766 | lj_snap_add(J); | ||
767 | } | ||
768 | } | ||
769 | |||
770 | #endif | ||
771 | |||
583 | /* -- Record calls and returns -------------------------------------------- */ | 772 | /* -- Record calls and returns -------------------------------------------- */ |
584 | 773 | ||
585 | /* Specialize to the runtime value of the called function or its prototype. */ | 774 | /* Specialize to the runtime value of the called function or its prototype. */ |
@@ -590,11 +779,26 @@ static TRef rec_call_specialize(jit_State *J, GCfunc *fn, TRef tr) | |||
590 | GCproto *pt = funcproto(fn); | 779 | GCproto *pt = funcproto(fn); |
591 | /* Too many closures created? Probably not a monomorphic function. */ | 780 | /* Too many closures created? Probably not a monomorphic function. */ |
592 | if (pt->flags >= PROTO_CLC_POLY) { /* Specialize to prototype instead. */ | 781 | if (pt->flags >= PROTO_CLC_POLY) { /* Specialize to prototype instead. */ |
593 | TRef trpt = emitir(IRT(IR_FLOAD, IRT_P32), tr, IRFL_FUNC_PC); | 782 | 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))); | 783 | 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. */ | 784 | (void)lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); /* Prevent GC of proto. */ |
596 | return tr; | 785 | return tr; |
597 | } | 786 | } |
787 | } else { | ||
788 | /* Don't specialize to non-monomorphic builtins. */ | ||
789 | switch (fn->c.ffid) { | ||
790 | case FF_coroutine_wrap_aux: | ||
791 | case FF_string_gmatch_aux: | ||
792 | /* NYI: io_file_iter doesn't have an ffid, yet. */ | ||
793 | { /* Specialize to the ffid. */ | ||
794 | TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), tr, IRFL_FUNC_FFID); | ||
795 | emitir(IRTGI(IR_EQ), trid, lj_ir_kint(J, fn->c.ffid)); | ||
796 | } | ||
797 | return tr; | ||
798 | default: | ||
799 | /* NYI: don't specialize to non-monomorphic C functions. */ | ||
800 | break; | ||
801 | } | ||
598 | } | 802 | } |
599 | /* Otherwise specialize to the function (closure) value itself. */ | 803 | /* Otherwise specialize to the function (closure) value itself. */ |
600 | kfunc = lj_ir_kfunc(J, fn); | 804 | kfunc = lj_ir_kfunc(J, fn); |
@@ -607,21 +811,31 @@ static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs) | |||
607 | { | 811 | { |
608 | RecordIndex ix; | 812 | RecordIndex ix; |
609 | TValue *functv = &J->L->base[func]; | 813 | TValue *functv = &J->L->base[func]; |
610 | TRef *fbase = &J->base[func]; | 814 | TRef kfunc, *fbase = &J->base[func]; |
611 | ptrdiff_t i; | 815 | ptrdiff_t i; |
612 | for (i = 0; i <= nargs; i++) | 816 | (void)getslot(J, func); /* Ensure func has a reference. */ |
613 | (void)getslot(J, func+i); /* Ensure func and all args have a reference. */ | 817 | for (i = 1; i <= nargs; i++) |
818 | (void)getslot(J, func+LJ_FR2+i); /* Ensure all args have a reference. */ | ||
614 | if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */ | 819 | if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */ |
615 | ix.tab = fbase[0]; | 820 | ix.tab = fbase[0]; |
616 | copyTV(J->L, &ix.tabv, functv); | 821 | copyTV(J->L, &ix.tabv, functv); |
617 | if (!lj_record_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj)) | 822 | if (!lj_record_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj)) |
618 | lj_trace_err(J, LJ_TRERR_NOMM); | 823 | lj_trace_err(J, LJ_TRERR_NOMM); |
619 | for (i = ++nargs; i > 0; i--) /* Shift arguments up. */ | 824 | for (i = ++nargs; i > LJ_FR2; i--) /* Shift arguments up. */ |
620 | fbase[i] = fbase[i-1]; | 825 | fbase[i+LJ_FR2] = fbase[i+LJ_FR2-1]; |
826 | #if LJ_FR2 | ||
827 | fbase[2] = fbase[0]; | ||
828 | #endif | ||
621 | fbase[0] = ix.mobj; /* Replace function. */ | 829 | fbase[0] = ix.mobj; /* Replace function. */ |
622 | functv = &ix.mobjv; | 830 | functv = &ix.mobjv; |
623 | } | 831 | } |
624 | fbase[0] = TREF_FRAME | rec_call_specialize(J, funcV(functv), fbase[0]); | 832 | kfunc = rec_call_specialize(J, funcV(functv), fbase[0]); |
833 | #if LJ_FR2 | ||
834 | fbase[0] = kfunc; | ||
835 | fbase[1] = TREF_FRAME; | ||
836 | #else | ||
837 | fbase[0] = kfunc | TREF_FRAME; | ||
838 | #endif | ||
625 | J->maxslot = (BCReg)nargs; | 839 | J->maxslot = (BCReg)nargs; |
626 | } | 840 | } |
627 | 841 | ||
@@ -631,8 +845,8 @@ void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs) | |||
631 | rec_call_setup(J, func, nargs); | 845 | rec_call_setup(J, func, nargs); |
632 | /* Bump frame. */ | 846 | /* Bump frame. */ |
633 | J->framedepth++; | 847 | J->framedepth++; |
634 | J->base += func+1; | 848 | J->base += func+1+LJ_FR2; |
635 | J->baseslot += func+1; | 849 | J->baseslot += func+1+LJ_FR2; |
636 | if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS) | 850 | if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS) |
637 | lj_trace_err(J, LJ_TRERR_STACKOV); | 851 | lj_trace_err(J, LJ_TRERR_STACKOV); |
638 | } | 852 | } |
@@ -650,7 +864,9 @@ void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs) | |||
650 | func += cbase; | 864 | func += cbase; |
651 | } | 865 | } |
652 | /* Move func + args down. */ | 866 | /* Move func + args down. */ |
653 | memmove(&J->base[-1], &J->base[func], sizeof(TRef)*(J->maxslot+1)); | 867 | if (LJ_FR2 && J->baseslot == 2) |
868 | J->base[func+1] = TREF_FRAME; | ||
869 | 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). */ | 870 | /* 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. */ | 871 | /* Tailcalls can form a loop, so count towards the loop unroll limit. */ |
656 | if (++J->tailcalled > J->loopunroll) | 872 | if (++J->tailcalled > J->loopunroll) |
@@ -680,6 +896,8 @@ static int check_downrec_unroll(jit_State *J, GCproto *pt) | |||
680 | return 0; | 896 | return 0; |
681 | } | 897 | } |
682 | 898 | ||
899 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot); | ||
900 | |||
683 | /* Record return. */ | 901 | /* Record return. */ |
684 | void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | 902 | void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) |
685 | { | 903 | { |
@@ -691,30 +909,32 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
691 | BCReg cbase = (BCReg)frame_delta(frame); | 909 | BCReg cbase = (BCReg)frame_delta(frame); |
692 | if (--J->framedepth <= 0) | 910 | if (--J->framedepth <= 0) |
693 | lj_trace_err(J, LJ_TRERR_NYIRETL); | 911 | lj_trace_err(J, LJ_TRERR_NYIRETL); |
694 | lua_assert(J->baseslot > 1); | 912 | lj_assertJ(J->baseslot > 1+LJ_FR2, "bad baseslot for return"); |
695 | gotresults++; | 913 | gotresults++; |
696 | rbase += cbase; | 914 | rbase += cbase; |
697 | J->baseslot -= (BCReg)cbase; | 915 | J->baseslot -= (BCReg)cbase; |
698 | J->base -= cbase; | 916 | J->base -= cbase; |
699 | J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */ | 917 | J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */ |
700 | frame = frame_prevd(frame); | 918 | frame = frame_prevd(frame); |
919 | J->needsnap = 1; /* Stop catching on-trace errors. */ | ||
701 | } | 920 | } |
702 | /* Return to lower frame via interpreter for unhandled cases. */ | 921 | /* Return to lower frame via interpreter for unhandled cases. */ |
703 | if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && | 922 | if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && |
704 | (!frame_islua(frame) || | 923 | (!frame_islua(frame) || |
705 | (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))))) { | 924 | (J->parent == 0 && J->exitno == 0 && |
925 | !bc_isret(bc_op(J->cur.startins))))) { | ||
706 | /* NYI: specialize to frame type and return directly, not via RET*. */ | 926 | /* NYI: specialize to frame type and return directly, not via RET*. */ |
707 | for (i = 0; i < (ptrdiff_t)rbase; i++) | 927 | for (i = 0; i < (ptrdiff_t)rbase; i++) |
708 | J->base[i] = 0; /* Purge dead slots. */ | 928 | J->base[i] = 0; /* Purge dead slots. */ |
709 | J->maxslot = rbase + (BCReg)gotresults; | 929 | J->maxslot = rbase + (BCReg)gotresults; |
710 | rec_stop(J, LJ_TRLINK_RETURN, 0); /* Return to interpreter. */ | 930 | lj_record_stop(J, LJ_TRLINK_RETURN, 0); /* Return to interpreter. */ |
711 | return; | 931 | return; |
712 | } | 932 | } |
713 | if (frame_isvarg(frame)) { | 933 | if (frame_isvarg(frame)) { |
714 | BCReg cbase = (BCReg)frame_delta(frame); | 934 | BCReg cbase = (BCReg)frame_delta(frame); |
715 | if (--J->framedepth < 0) /* NYI: return of vararg func to lower frame. */ | 935 | if (--J->framedepth < 0) /* NYI: return of vararg func to lower frame. */ |
716 | lj_trace_err(J, LJ_TRERR_NYIRETL); | 936 | lj_trace_err(J, LJ_TRERR_NYIRETL); |
717 | lua_assert(J->baseslot > 1); | 937 | lj_assertJ(J->baseslot > 1+LJ_FR2, "bad baseslot for return"); |
718 | rbase += cbase; | 938 | rbase += cbase; |
719 | J->baseslot -= (BCReg)cbase; | 939 | J->baseslot -= (BCReg)cbase; |
720 | J->base -= cbase; | 940 | J->base -= cbase; |
@@ -724,27 +944,28 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
724 | BCIns callins = *(frame_pc(frame)-1); | 944 | BCIns callins = *(frame_pc(frame)-1); |
725 | ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults; | 945 | ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults; |
726 | BCReg cbase = bc_a(callins); | 946 | BCReg cbase = bc_a(callins); |
727 | GCproto *pt = funcproto(frame_func(frame - (cbase+1))); | 947 | GCproto *pt = funcproto(frame_func(frame - (cbase+1+LJ_FR2))); |
728 | if ((pt->flags & PROTO_NOJIT)) | 948 | if ((pt->flags & PROTO_NOJIT)) |
729 | lj_trace_err(J, LJ_TRERR_CJITOFF); | 949 | lj_trace_err(J, LJ_TRERR_CJITOFF); |
730 | if (J->framedepth == 0 && J->pt && frame == J->L->base - 1) { | 950 | if (J->framedepth == 0 && J->pt && frame == J->L->base - 1) { |
731 | if (check_downrec_unroll(J, pt)) { | 951 | if (check_downrec_unroll(J, pt)) { |
732 | J->maxslot = (BCReg)(rbase + gotresults); | 952 | J->maxslot = (BCReg)(rbase + gotresults); |
733 | lj_snap_purge(J); | 953 | lj_snap_purge(J); |
734 | rec_stop(J, LJ_TRLINK_DOWNREC, J->cur.traceno); /* Down-recursion. */ | 954 | lj_record_stop(J, LJ_TRLINK_DOWNREC, J->cur.traceno); /* Down-rec. */ |
735 | return; | 955 | return; |
736 | } | 956 | } |
737 | lj_snap_add(J); | 957 | lj_snap_add(J); |
738 | } | 958 | } |
739 | for (i = 0; i < nresults; i++) /* Adjust results. */ | 959 | for (i = 0; i < nresults; i++) /* Adjust results. */ |
740 | J->base[i-1] = i < gotresults ? J->base[rbase+i] : TREF_NIL; | 960 | J->base[i-1-LJ_FR2] = i < gotresults ? J->base[rbase+i] : TREF_NIL; |
741 | J->maxslot = cbase+(BCReg)nresults; | 961 | J->maxslot = cbase+(BCReg)nresults; |
742 | if (J->framedepth > 0) { /* Return to a frame that is part of the trace. */ | 962 | if (J->framedepth > 0) { /* Return to a frame that is part of the trace. */ |
743 | J->framedepth--; | 963 | J->framedepth--; |
744 | lua_assert(J->baseslot > cbase+1); | 964 | lj_assertJ(J->baseslot > cbase+1+LJ_FR2, "bad baseslot for return"); |
745 | J->baseslot -= cbase+1; | 965 | J->baseslot -= cbase+1+LJ_FR2; |
746 | J->base -= cbase+1; | 966 | J->base -= cbase+1+LJ_FR2; |
747 | } else if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) { | 967 | } else if (J->parent == 0 && J->exitno == 0 && |
968 | !bc_isret(bc_op(J->cur.startins))) { | ||
748 | /* Return to lower frame would leave the loop in a root trace. */ | 969 | /* Return to lower frame would leave the loop in a root trace. */ |
749 | lj_trace_err(J, LJ_TRERR_LLEAVE); | 970 | lj_trace_err(J, LJ_TRERR_LLEAVE); |
750 | } else if (J->needsnap) { /* Tailcalled to ff with side-effects. */ | 971 | } else if (J->needsnap) { /* Tailcalled to ff with side-effects. */ |
@@ -752,13 +973,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. */ | 973 | } else { /* Return to lower frame. Guard for the target we return to. */ |
753 | TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); | 974 | TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); |
754 | TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame)); | 975 | TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame)); |
755 | emitir(IRTG(IR_RETF, IRT_P32), trpt, trpc); | 976 | emitir(IRTG(IR_RETF, IRT_PGC), trpt, trpc); |
756 | J->retdepth++; | 977 | J->retdepth++; |
757 | J->needsnap = 1; | 978 | J->needsnap = 1; |
758 | lua_assert(J->baseslot == 1); | 979 | lj_assertJ(J->baseslot == 1+LJ_FR2, "bad baseslot for return"); |
759 | /* Shift result slots up and clear the slots of the new frame below. */ | 980 | /* Shift result slots up and clear the slots of the new frame below. */ |
760 | memmove(J->base + cbase, J->base-1, sizeof(TRef)*nresults); | 981 | memmove(J->base + cbase, J->base-1-LJ_FR2, sizeof(TRef)*nresults); |
761 | memset(J->base-1, 0, sizeof(TRef)*(cbase+1)); | 982 | memset(J->base-1-LJ_FR2, 0, sizeof(TRef)*(cbase+1+LJ_FR2)); |
762 | } | 983 | } |
763 | } else if (frame_iscont(frame)) { /* Return to continuation frame. */ | 984 | } else if (frame_iscont(frame)) { /* Return to continuation frame. */ |
764 | ASMFunction cont = frame_contf(frame); | 985 | ASMFunction cont = frame_contf(frame); |
@@ -767,24 +988,52 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
767 | lj_trace_err(J, LJ_TRERR_NYIRETL); | 988 | lj_trace_err(J, LJ_TRERR_NYIRETL); |
768 | J->baseslot -= (BCReg)cbase; | 989 | J->baseslot -= (BCReg)cbase; |
769 | J->base -= cbase; | 990 | J->base -= cbase; |
770 | J->maxslot = cbase-2; | 991 | J->maxslot = cbase-(2<<LJ_FR2); |
771 | if (cont == lj_cont_ra) { | 992 | if (cont == lj_cont_ra) { |
772 | /* Copy result to destination slot. */ | 993 | /* Copy result to destination slot. */ |
773 | BCReg dst = bc_a(*(frame_contpc(frame)-1)); | 994 | BCReg dst = bc_a(*(frame_contpc(frame)-1)); |
774 | J->base[dst] = gotresults ? J->base[cbase+rbase] : TREF_NIL; | 995 | J->base[dst] = gotresults ? J->base[cbase+rbase] : TREF_NIL; |
775 | if (dst >= J->maxslot) J->maxslot = dst+1; | 996 | if (dst >= J->maxslot) { |
997 | J->maxslot = dst+1; | ||
998 | } | ||
776 | } else if (cont == lj_cont_nop) { | 999 | } else if (cont == lj_cont_nop) { |
777 | /* Nothing to do here. */ | 1000 | /* Nothing to do here. */ |
778 | } else if (cont == lj_cont_cat) { | 1001 | } else if (cont == lj_cont_cat) { |
779 | lua_assert(0); | 1002 | BCReg bslot = bc_b(*(frame_contpc(frame)-1)); |
1003 | TRef tr = gotresults ? J->base[cbase+rbase] : TREF_NIL; | ||
1004 | if (bslot != J->maxslot) { /* Concatenate the remainder. */ | ||
1005 | TValue *b = J->L->base, save; /* Simulate lower frame and result. */ | ||
1006 | /* Can't handle MM_concat + CALLT + fast func side-effects. */ | ||
1007 | if (J->postproc != LJ_POST_NONE) | ||
1008 | lj_trace_err(J, LJ_TRERR_NYIRETL); | ||
1009 | J->base[J->maxslot] = tr; | ||
1010 | copyTV(J->L, &save, b-(2<<LJ_FR2)); | ||
1011 | if (gotresults) | ||
1012 | copyTV(J->L, b-(2<<LJ_FR2), b+rbase); | ||
1013 | else | ||
1014 | setnilV(b-(2<<LJ_FR2)); | ||
1015 | J->L->base = b - cbase; | ||
1016 | tr = rec_cat(J, bslot, cbase-(2<<LJ_FR2)); | ||
1017 | b = J->L->base + cbase; /* Undo. */ | ||
1018 | J->L->base = b; | ||
1019 | copyTV(J->L, b-(2<<LJ_FR2), &save); | ||
1020 | } | ||
1021 | if (tr) { /* Store final result. */ | ||
1022 | BCReg dst = bc_a(*(frame_contpc(frame)-1)); | ||
1023 | J->base[dst] = tr; | ||
1024 | if (dst >= J->maxslot) { | ||
1025 | J->maxslot = dst+1; | ||
1026 | } | ||
1027 | } /* Otherwise continue with another __concat call. */ | ||
780 | } else { | 1028 | } else { |
781 | /* Result type already specialized. */ | 1029 | /* Result type already specialized. */ |
782 | lua_assert(cont == lj_cont_condf || cont == lj_cont_condt); | 1030 | lj_assertJ(cont == lj_cont_condf || cont == lj_cont_condt, |
1031 | "bad continuation type"); | ||
783 | } | 1032 | } |
784 | } else { | 1033 | } else { |
785 | lj_trace_err(J, LJ_TRERR_NYIRETL); /* NYI: handle return to C frame. */ | 1034 | lj_trace_err(J, LJ_TRERR_NYIRETL); /* NYI: handle return to C frame. */ |
786 | } | 1035 | } |
787 | lua_assert(J->baseslot >= 1); | 1036 | lj_assertJ(J->baseslot >= 1+LJ_FR2, "bad baseslot for return"); |
788 | } | 1037 | } |
789 | 1038 | ||
790 | /* -- Metamethod handling ------------------------------------------------- */ | 1039 | /* -- Metamethod handling ------------------------------------------------- */ |
@@ -792,19 +1041,17 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
792 | /* Prepare to record call to metamethod. */ | 1041 | /* Prepare to record call to metamethod. */ |
793 | static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) | 1042 | static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) |
794 | { | 1043 | { |
795 | BCReg s, top = curr_proto(J->L)->framesize; | 1044 | BCReg s, top = cont == lj_cont_cat ? J->maxslot : curr_proto(J->L)->framesize; |
796 | TRef trcont; | 1045 | #if LJ_FR2 |
797 | setcont(&J->L->base[top], cont); | 1046 | J->base[top] = lj_ir_k64(J, IR_KNUM, u64ptr(contptr(cont))); |
798 | #if LJ_64 | 1047 | J->base[top+1] = TREF_CONT; |
799 | trcont = lj_ir_kptr(J, (void *)((int64_t)cont - (int64_t)lj_vm_asm_begin)); | ||
800 | #else | 1048 | #else |
801 | trcont = lj_ir_kptr(J, (void *)cont); | 1049 | J->base[top] = lj_ir_kptr(J, contptr(cont)) | TREF_CONT; |
802 | #endif | 1050 | #endif |
803 | J->base[top] = trcont | TREF_CONT; | ||
804 | J->framedepth++; | 1051 | J->framedepth++; |
805 | for (s = J->maxslot; s < top; s++) | 1052 | for (s = J->maxslot; s < top; s++) |
806 | J->base[s] = 0; /* Clear frame gap to avoid resurrecting previous refs. */ | 1053 | J->base[s] = 0; /* Clear frame gap to avoid resurrecting previous refs. */ |
807 | return top+1; | 1054 | return top+1+LJ_FR2; |
808 | } | 1055 | } |
809 | 1056 | ||
810 | /* Record metamethod lookup. */ | 1057 | /* Record metamethod lookup. */ |
@@ -823,7 +1070,7 @@ int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm) | |||
823 | cTValue *mo; | 1070 | cTValue *mo; |
824 | if (LJ_HASFFI && udtype == UDTYPE_FFI_CLIB) { | 1071 | if (LJ_HASFFI && udtype == UDTYPE_FFI_CLIB) { |
825 | /* Specialize to the C library namespace object. */ | 1072 | /* Specialize to the C library namespace object. */ |
826 | emitir(IRTG(IR_EQ, IRT_P32), ix->tab, lj_ir_kptr(J, udataV(&ix->tabv))); | 1073 | emitir(IRTG(IR_EQ, IRT_PGC), ix->tab, lj_ir_kptr(J, udataV(&ix->tabv))); |
827 | } else { | 1074 | } else { |
828 | /* Specialize to the type of userdata. */ | 1075 | /* Specialize to the type of userdata. */ |
829 | TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), ix->tab, IRFL_UDATA_UDTYPE); | 1076 | TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), ix->tab, IRFL_UDATA_UDTYPE); |
@@ -852,7 +1099,8 @@ int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm) | |||
852 | } | 1099 | } |
853 | /* The cdata metatable is treated as immutable. */ | 1100 | /* The cdata metatable is treated as immutable. */ |
854 | if (LJ_HASFFI && tref_iscdata(ix->tab)) goto immutable_mt; | 1101 | if (LJ_HASFFI && tref_iscdata(ix->tab)) goto immutable_mt; |
855 | ix->mt = mix.tab = lj_ir_ktab(J, mt); | 1102 | ix->mt = mix.tab = lj_ir_ggfload(J, IRT_TAB, |
1103 | GG_OFS(g.gcroot[GCROOT_BASEMT+itypemap(&ix->tabv)])); | ||
856 | goto nocheck; | 1104 | goto nocheck; |
857 | } | 1105 | } |
858 | ix->mt = mt ? mix.tab : TREF_NIL; | 1106 | ix->mt = mt ? mix.tab : TREF_NIL; |
@@ -879,12 +1127,12 @@ nocheck: | |||
879 | static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) | 1127 | static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) |
880 | { | 1128 | { |
881 | /* Set up metamethod call first to save ix->tab and ix->tabv. */ | 1129 | /* Set up metamethod call first to save ix->tab and ix->tabv. */ |
882 | BCReg func = rec_mm_prep(J, lj_cont_ra); | 1130 | BCReg func = rec_mm_prep(J, mm == MM_concat ? lj_cont_cat : lj_cont_ra); |
883 | TRef *base = J->base + func; | 1131 | TRef *base = J->base + func; |
884 | TValue *basev = J->L->base + func; | 1132 | TValue *basev = J->L->base + func; |
885 | base[1] = ix->tab; base[2] = ix->key; | 1133 | base[1+LJ_FR2] = ix->tab; base[2+LJ_FR2] = ix->key; |
886 | copyTV(J->L, basev+1, &ix->tabv); | 1134 | copyTV(J->L, basev+1+LJ_FR2, &ix->tabv); |
887 | copyTV(J->L, basev+2, &ix->keyv); | 1135 | copyTV(J->L, basev+2+LJ_FR2, &ix->keyv); |
888 | if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */ | 1136 | if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */ |
889 | if (mm != MM_unm) { | 1137 | if (mm != MM_unm) { |
890 | ix->tab = ix->key; | 1138 | ix->tab = ix->key; |
@@ -896,6 +1144,9 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) | |||
896 | } | 1144 | } |
897 | ok: | 1145 | ok: |
898 | base[0] = ix->mobj; | 1146 | base[0] = ix->mobj; |
1147 | #if LJ_FR2 | ||
1148 | base[1] = 0; | ||
1149 | #endif | ||
899 | copyTV(J->L, basev+0, &ix->mobjv); | 1150 | copyTV(J->L, basev+0, &ix->mobjv); |
900 | lj_record_call(J, func, 2); | 1151 | lj_record_call(J, func, 2); |
901 | return 0; /* No result yet. */ | 1152 | return 0; /* No result yet. */ |
@@ -912,6 +1163,8 @@ static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv) | |||
912 | TRef *base = J->base + func; | 1163 | TRef *base = J->base + func; |
913 | TValue *basev = J->L->base + func; | 1164 | TValue *basev = J->L->base + func; |
914 | base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv); | 1165 | base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv); |
1166 | base += LJ_FR2; | ||
1167 | basev += LJ_FR2; | ||
915 | base[1] = tr; copyTV(J->L, basev+1, tv); | 1168 | base[1] = tr; copyTV(J->L, basev+1, tv); |
916 | #if LJ_52 | 1169 | #if LJ_52 |
917 | base[2] = tr; copyTV(J->L, basev+2, tv); | 1170 | base[2] = tr; copyTV(J->L, basev+2, tv); |
@@ -921,7 +1174,7 @@ static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv) | |||
921 | lj_record_call(J, func, 2); | 1174 | lj_record_call(J, func, 2); |
922 | } else { | 1175 | } else { |
923 | if (LJ_52 && tref_istab(tr)) | 1176 | if (LJ_52 && tref_istab(tr)) |
924 | return lj_ir_call(J, IRCALL_lj_tab_len, tr); | 1177 | return emitir(IRTI(IR_ALEN), tr, TREF_NIL); |
925 | lj_trace_err(J, LJ_TRERR_NOMM); | 1178 | lj_trace_err(J, LJ_TRERR_NOMM); |
926 | } | 1179 | } |
927 | return 0; /* No result yet. */ | 1180 | return 0; /* No result yet. */ |
@@ -931,10 +1184,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) | 1184 | static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op) |
932 | { | 1185 | { |
933 | BCReg func = rec_mm_prep(J, (op&1) ? lj_cont_condf : lj_cont_condt); | 1186 | BCReg func = rec_mm_prep(J, (op&1) ? lj_cont_condf : lj_cont_condt); |
934 | TRef *base = J->base + func; | 1187 | TRef *base = J->base + func + LJ_FR2; |
935 | TValue *tv = J->L->base + func; | 1188 | TValue *tv = J->L->base + func + LJ_FR2; |
936 | base[0] = ix->mobj; base[1] = ix->val; base[2] = ix->key; | 1189 | base[-LJ_FR2] = ix->mobj; base[1] = ix->val; base[2] = ix->key; |
937 | copyTV(J->L, tv+0, &ix->mobjv); | 1190 | copyTV(J->L, tv-LJ_FR2, &ix->mobjv); |
938 | copyTV(J->L, tv+1, &ix->valv); | 1191 | copyTV(J->L, tv+1, &ix->valv); |
939 | copyTV(J->L, tv+2, &ix->keyv); | 1192 | copyTV(J->L, tv+2, &ix->keyv); |
940 | lj_record_call(J, func, 2); | 1193 | lj_record_call(J, func, 2); |
@@ -1030,7 +1283,7 @@ static void rec_mm_comp_cdata(jit_State *J, RecordIndex *ix, int op, MMS mm) | |||
1030 | ix->tab = ix->val; | 1283 | ix->tab = ix->val; |
1031 | copyTV(J->L, &ix->tabv, &ix->valv); | 1284 | copyTV(J->L, &ix->tabv, &ix->valv); |
1032 | } else { | 1285 | } else { |
1033 | lua_assert(tref_iscdata(ix->key)); | 1286 | lj_assertJ(tref_iscdata(ix->key), "cdata expected"); |
1034 | ix->tab = ix->key; | 1287 | ix->tab = ix->key; |
1035 | copyTV(J->L, &ix->tabv, &ix->keyv); | 1288 | copyTV(J->L, &ix->tabv, &ix->keyv); |
1036 | } | 1289 | } |
@@ -1041,6 +1294,72 @@ static void rec_mm_comp_cdata(jit_State *J, RecordIndex *ix, int op, MMS mm) | |||
1041 | 1294 | ||
1042 | /* -- Indexed access ------------------------------------------------------ */ | 1295 | /* -- Indexed access ------------------------------------------------------ */ |
1043 | 1296 | ||
1297 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
1298 | /* Bump table allocations in bytecode when they grow during recording. */ | ||
1299 | static void rec_idx_bump(jit_State *J, RecordIndex *ix) | ||
1300 | { | ||
1301 | RBCHashEntry *rbc = &J->rbchash[(ix->tab & (RBCHASH_SLOTS-1))]; | ||
1302 | if (tref_ref(ix->tab) == rbc->ref) { | ||
1303 | const BCIns *pc = mref(rbc->pc, const BCIns); | ||
1304 | GCtab *tb = tabV(&ix->tabv); | ||
1305 | uint32_t nhbits; | ||
1306 | IRIns *ir; | ||
1307 | if (!tvisnil(&ix->keyv)) | ||
1308 | (void)lj_tab_set(J->L, tb, &ix->keyv); /* Grow table right now. */ | ||
1309 | nhbits = tb->hmask > 0 ? lj_fls(tb->hmask)+1 : 0; | ||
1310 | ir = IR(tref_ref(ix->tab)); | ||
1311 | if (ir->o == IR_TNEW) { | ||
1312 | uint32_t ah = bc_d(*pc); | ||
1313 | uint32_t asize = ah & 0x7ff, hbits = ah >> 11; | ||
1314 | if (nhbits > hbits) hbits = nhbits; | ||
1315 | if (tb->asize > asize) { | ||
1316 | asize = tb->asize <= 0x7ff ? tb->asize : 0x7ff; | ||
1317 | } | ||
1318 | if ((asize | (hbits<<11)) != ah) { /* Has the size changed? */ | ||
1319 | /* Patch bytecode, but continue recording (for more patching). */ | ||
1320 | setbc_d(pc, (asize | (hbits<<11))); | ||
1321 | /* Patching TNEW operands is only safe if the trace is aborted. */ | ||
1322 | ir->op1 = asize; ir->op2 = hbits; | ||
1323 | J->retryrec = 1; /* Abort the trace at the end of recording. */ | ||
1324 | } | ||
1325 | } else if (ir->o == IR_TDUP) { | ||
1326 | GCtab *tpl = gco2tab(proto_kgc(&gcref(rbc->pt)->pt, ~(ptrdiff_t)bc_d(*pc))); | ||
1327 | /* Grow template table, but preserve keys with nil values. */ | ||
1328 | if ((tb->asize > tpl->asize && (1u << nhbits)-1 == tpl->hmask) || | ||
1329 | (tb->asize == tpl->asize && (1u << nhbits)-1 > tpl->hmask)) { | ||
1330 | Node *node = noderef(tpl->node); | ||
1331 | uint32_t i, hmask = tpl->hmask, asize; | ||
1332 | TValue *array; | ||
1333 | for (i = 0; i <= hmask; i++) { | ||
1334 | if (!tvisnil(&node[i].key) && tvisnil(&node[i].val)) | ||
1335 | settabV(J->L, &node[i].val, tpl); | ||
1336 | } | ||
1337 | if (!tvisnil(&ix->keyv) && tref_isk(ix->key)) { | ||
1338 | TValue *o = lj_tab_set(J->L, tpl, &ix->keyv); | ||
1339 | if (tvisnil(o)) settabV(J->L, o, tpl); | ||
1340 | } | ||
1341 | lj_tab_resize(J->L, tpl, tb->asize, nhbits); | ||
1342 | node = noderef(tpl->node); | ||
1343 | hmask = tpl->hmask; | ||
1344 | for (i = 0; i <= hmask; i++) { | ||
1345 | /* This is safe, since template tables only hold immutable values. */ | ||
1346 | if (tvistab(&node[i].val)) | ||
1347 | setnilV(&node[i].val); | ||
1348 | } | ||
1349 | /* The shape of the table may have changed. Clean up array part, too. */ | ||
1350 | asize = tpl->asize; | ||
1351 | array = tvref(tpl->array); | ||
1352 | for (i = 0; i < asize; i++) { | ||
1353 | if (tvistab(&array[i])) | ||
1354 | setnilV(&array[i]); | ||
1355 | } | ||
1356 | J->retryrec = 1; /* Abort the trace at the end of recording. */ | ||
1357 | } | ||
1358 | } | ||
1359 | } | ||
1360 | } | ||
1361 | #endif | ||
1362 | |||
1044 | /* Record bounds-check. */ | 1363 | /* Record bounds-check. */ |
1045 | static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) | 1364 | static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) |
1046 | { | 1365 | { |
@@ -1061,7 +1380,8 @@ static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) | |||
1061 | /* Got scalar evolution analysis results for this reference? */ | 1380 | /* Got scalar evolution analysis results for this reference? */ |
1062 | if (ref == J->scev.idx) { | 1381 | if (ref == J->scev.idx) { |
1063 | int32_t stop; | 1382 | int32_t stop; |
1064 | lua_assert(irt_isint(J->scev.t) && ir->o == IR_SLOAD); | 1383 | lj_assertJ(irt_isint(J->scev.t) && ir->o == IR_SLOAD, |
1384 | "only int SCEV supported"); | ||
1065 | stop = numberVint(&(J->L->base - J->baseslot)[ir->op1 + FORL_STOP]); | 1385 | stop = numberVint(&(J->L->base - J->baseslot)[ir->op1 + FORL_STOP]); |
1066 | /* Runtime value for stop of loop is within bounds? */ | 1386 | /* Runtime value for stop of loop is within bounds? */ |
1067 | if ((uint64_t)stop + ofs < (uint64_t)asize) { | 1387 | if ((uint64_t)stop + ofs < (uint64_t)asize) { |
@@ -1080,11 +1400,14 @@ static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) | |||
1080 | } | 1400 | } |
1081 | 1401 | ||
1082 | /* Record indexed key lookup. */ | 1402 | /* Record indexed key lookup. */ |
1083 | static TRef rec_idx_key(jit_State *J, RecordIndex *ix) | 1403 | static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref, |
1404 | IRType1 *rbguard) | ||
1084 | { | 1405 | { |
1085 | TRef key; | 1406 | TRef key; |
1086 | GCtab *t = tabV(&ix->tabv); | 1407 | GCtab *t = tabV(&ix->tabv); |
1087 | ix->oldv = lj_tab_get(J->L, t, &ix->keyv); /* Lookup previous value. */ | 1408 | ix->oldv = lj_tab_get(J->L, t, &ix->keyv); /* Lookup previous value. */ |
1409 | *rbref = 0; | ||
1410 | rbguard->irt = 0; | ||
1088 | 1411 | ||
1089 | /* Integer keys are looked up in the array part first. */ | 1412 | /* Integer keys are looked up in the array part first. */ |
1090 | key = ix->key; | 1413 | key = ix->key; |
@@ -1098,8 +1421,8 @@ static TRef rec_idx_key(jit_State *J, RecordIndex *ix) | |||
1098 | if ((MSize)k < t->asize) { /* Currently an array key? */ | 1421 | if ((MSize)k < t->asize) { /* Currently an array key? */ |
1099 | TRef arrayref; | 1422 | TRef arrayref; |
1100 | rec_idx_abc(J, asizeref, ikey, t->asize); | 1423 | rec_idx_abc(J, asizeref, ikey, t->asize); |
1101 | arrayref = emitir(IRT(IR_FLOAD, IRT_P32), ix->tab, IRFL_TAB_ARRAY); | 1424 | arrayref = emitir(IRT(IR_FLOAD, IRT_PGC), ix->tab, IRFL_TAB_ARRAY); |
1102 | return emitir(IRT(IR_AREF, IRT_P32), arrayref, ikey); | 1425 | return emitir(IRT(IR_AREF, IRT_PGC), arrayref, ikey); |
1103 | } else { /* Currently not in array (may be an array extension)? */ | 1426 | } else { /* Currently not in array (may be an array extension)? */ |
1104 | emitir(IRTGI(IR_ULE), asizeref, ikey); /* Inv. bounds check. */ | 1427 | emitir(IRTGI(IR_ULE), asizeref, ikey); /* Inv. bounds check. */ |
1105 | if (k == 0 && tref_isk(key)) | 1428 | if (k == 0 && tref_isk(key)) |
@@ -1131,19 +1454,21 @@ static TRef rec_idx_key(jit_State *J, RecordIndex *ix) | |||
1131 | key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT); | 1454 | key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT); |
1132 | if (tref_isk(key)) { | 1455 | if (tref_isk(key)) { |
1133 | /* Optimize lookup of constant hash keys. */ | 1456 | /* Optimize lookup of constant hash keys. */ |
1134 | MSize hslot = (MSize)((char *)ix->oldv - (char *)&noderef(t->node)[0].val); | 1457 | GCSize hslot = (GCSize)((char *)ix->oldv-(char *)&noderef(t->node)[0].val); |
1135 | if (t->hmask > 0 && hslot <= t->hmask*(MSize)sizeof(Node) && | 1458 | if (hslot <= t->hmask*(GCSize)sizeof(Node) && |
1136 | hslot <= 65535*(MSize)sizeof(Node)) { | 1459 | hslot <= 65535*(GCSize)sizeof(Node)) { |
1137 | TRef node, kslot; | 1460 | TRef node, kslot, hm; |
1138 | TRef hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK); | 1461 | *rbref = J->cur.nins; /* Mark possible rollback point. */ |
1462 | *rbguard = J->guardemit; | ||
1463 | hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK); | ||
1139 | emitir(IRTGI(IR_EQ), hm, lj_ir_kint(J, (int32_t)t->hmask)); | 1464 | 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); | 1465 | node = emitir(IRT(IR_FLOAD, IRT_PGC), ix->tab, IRFL_TAB_NODE); |
1141 | kslot = lj_ir_kslot(J, key, hslot / sizeof(Node)); | 1466 | kslot = lj_ir_kslot(J, key, (IRRef)(hslot / sizeof(Node))); |
1142 | return emitir(IRTG(IR_HREFK, IRT_P32), node, kslot); | 1467 | return emitir(IRTG(IR_HREFK, IRT_PGC), node, kslot); |
1143 | } | 1468 | } |
1144 | } | 1469 | } |
1145 | /* Fall back to a regular hash lookup. */ | 1470 | /* Fall back to a regular hash lookup. */ |
1146 | return emitir(IRT(IR_HREF, IRT_P32), ix->tab, key); | 1471 | return emitir(IRT(IR_HREF, IRT_PGC), ix->tab, key); |
1147 | } | 1472 | } |
1148 | 1473 | ||
1149 | /* Determine whether a key is NOT one of the fast metamethod names. */ | 1474 | /* Determine whether a key is NOT one of the fast metamethod names. */ |
@@ -1168,20 +1493,22 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1168 | { | 1493 | { |
1169 | TRef xref; | 1494 | TRef xref; |
1170 | IROp xrefop, loadop; | 1495 | IROp xrefop, loadop; |
1496 | IRRef rbref; | ||
1497 | IRType1 rbguard; | ||
1171 | cTValue *oldv; | 1498 | cTValue *oldv; |
1172 | 1499 | ||
1173 | while (!tref_istab(ix->tab)) { /* Handle non-table lookup. */ | 1500 | while (!tref_istab(ix->tab)) { /* Handle non-table lookup. */ |
1174 | /* Never call raw lj_record_idx() on non-table. */ | 1501 | /* Never call raw lj_record_idx() on non-table. */ |
1175 | lua_assert(ix->idxchain != 0); | 1502 | lj_assertJ(ix->idxchain != 0, "bad usage"); |
1176 | if (!lj_record_mm_lookup(J, ix, ix->val ? MM_newindex : MM_index)) | 1503 | if (!lj_record_mm_lookup(J, ix, ix->val ? MM_newindex : MM_index)) |
1177 | lj_trace_err(J, LJ_TRERR_NOMM); | 1504 | lj_trace_err(J, LJ_TRERR_NOMM); |
1178 | handlemm: | 1505 | handlemm: |
1179 | if (tref_isfunc(ix->mobj)) { /* Handle metamethod call. */ | 1506 | if (tref_isfunc(ix->mobj)) { /* Handle metamethod call. */ |
1180 | BCReg func = rec_mm_prep(J, ix->val ? lj_cont_nop : lj_cont_ra); | 1507 | BCReg func = rec_mm_prep(J, ix->val ? lj_cont_nop : lj_cont_ra); |
1181 | TRef *base = J->base + func; | 1508 | TRef *base = J->base + func + LJ_FR2; |
1182 | TValue *tv = J->L->base + func; | 1509 | TValue *tv = J->L->base + func + LJ_FR2; |
1183 | base[0] = ix->mobj; base[1] = ix->tab; base[2] = ix->key; | 1510 | base[-LJ_FR2] = ix->mobj; base[1] = ix->tab; base[2] = ix->key; |
1184 | setfuncV(J->L, tv+0, funcV(&ix->mobjv)); | 1511 | setfuncV(J->L, tv-LJ_FR2, funcV(&ix->mobjv)); |
1185 | copyTV(J->L, tv+1, &ix->tabv); | 1512 | copyTV(J->L, tv+1, &ix->tabv); |
1186 | copyTV(J->L, tv+2, &ix->keyv); | 1513 | copyTV(J->L, tv+2, &ix->keyv); |
1187 | if (ix->val) { | 1514 | if (ix->val) { |
@@ -1194,6 +1521,16 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1194 | return 0; /* No result yet. */ | 1521 | return 0; /* No result yet. */ |
1195 | } | 1522 | } |
1196 | } | 1523 | } |
1524 | #if LJ_HASBUFFER | ||
1525 | /* The index table of buffer objects is treated as immutable. */ | ||
1526 | if (ix->mt == TREF_NIL && !ix->val && | ||
1527 | tref_isudata(ix->tab) && udataV(&ix->tabv)->udtype == UDTYPE_BUFFER && | ||
1528 | tref_istab(ix->mobj) && tref_isstr(ix->key) && tref_isk(ix->key)) { | ||
1529 | cTValue *val = lj_tab_getstr(tabV(&ix->mobjv), strV(&ix->keyv)); | ||
1530 | TRef tr = lj_record_constify(J, val); | ||
1531 | if (tr) return tr; /* Specialize to the value, i.e. a method. */ | ||
1532 | } | ||
1533 | #endif | ||
1197 | /* Otherwise retry lookup with metaobject. */ | 1534 | /* Otherwise retry lookup with metaobject. */ |
1198 | ix->tab = ix->mobj; | 1535 | ix->tab = ix->mobj; |
1199 | copyTV(J->L, &ix->tabv, &ix->mobjv); | 1536 | copyTV(J->L, &ix->tabv, &ix->mobjv); |
@@ -1213,7 +1550,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1213 | } | 1550 | } |
1214 | 1551 | ||
1215 | /* Record the key lookup. */ | 1552 | /* Record the key lookup. */ |
1216 | xref = rec_idx_key(J, ix); | 1553 | xref = rec_idx_key(J, ix, &rbref, &rbguard); |
1217 | xrefop = IR(tref_ref(xref))->o; | 1554 | xrefop = IR(tref_ref(xref))->o; |
1218 | loadop = xrefop == IR_AREF ? IR_ALOAD : IR_HLOAD; | 1555 | loadop = xrefop == IR_AREF ? IR_ALOAD : IR_HLOAD; |
1219 | /* The lj_meta_tset() inconsistency is gone, but better play safe. */ | 1556 | /* The lj_meta_tset() inconsistency is gone, but better play safe. */ |
@@ -1223,11 +1560,15 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1223 | IRType t = itype2irt(oldv); | 1560 | IRType t = itype2irt(oldv); |
1224 | TRef res; | 1561 | TRef res; |
1225 | if (oldv == niltvg(J2G(J))) { | 1562 | if (oldv == niltvg(J2G(J))) { |
1226 | emitir(IRTG(IR_EQ, IRT_P32), xref, lj_ir_kkptr(J, niltvg(J2G(J)))); | 1563 | emitir(IRTG(IR_EQ, IRT_PGC), xref, lj_ir_kkptr(J, niltvg(J2G(J)))); |
1227 | res = TREF_NIL; | 1564 | res = TREF_NIL; |
1228 | } else { | 1565 | } else { |
1229 | res = emitir(IRTG(loadop, t), xref, 0); | 1566 | res = emitir(IRTG(loadop, t), xref, 0); |
1230 | } | 1567 | } |
1568 | if (tref_ref(res) < rbref) { /* HREFK + load forwarded? */ | ||
1569 | lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */ | ||
1570 | J->guardemit = rbguard; | ||
1571 | } | ||
1231 | if (t == IRT_NIL && ix->idxchain && lj_record_mm_lookup(J, ix, MM_index)) | 1572 | if (t == IRT_NIL && ix->idxchain && lj_record_mm_lookup(J, ix, MM_index)) |
1232 | goto handlemm; | 1573 | goto handlemm; |
1233 | if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitives. */ | 1574 | if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitives. */ |
@@ -1235,6 +1576,10 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1235 | } else { /* Indexed store. */ | 1576 | } else { /* Indexed store. */ |
1236 | GCtab *mt = tabref(tabV(&ix->tabv)->metatable); | 1577 | GCtab *mt = tabref(tabV(&ix->tabv)->metatable); |
1237 | int keybarrier = tref_isgcv(ix->key) && !tref_isnil(ix->val); | 1578 | int keybarrier = tref_isgcv(ix->key) && !tref_isnil(ix->val); |
1579 | if (tref_ref(xref) < rbref) { /* HREFK forwarded? */ | ||
1580 | lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */ | ||
1581 | J->guardemit = rbguard; | ||
1582 | } | ||
1238 | if (tvisnil(oldv)) { /* Previous value was nil? */ | 1583 | if (tvisnil(oldv)) { /* Previous value was nil? */ |
1239 | /* Need to duplicate the hasmm check for the early guards. */ | 1584 | /* Need to duplicate the hasmm check for the early guards. */ |
1240 | int hasmm = 0; | 1585 | int hasmm = 0; |
@@ -1245,26 +1590,30 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1245 | if (hasmm) | 1590 | if (hasmm) |
1246 | emitir(IRTG(loadop, IRT_NIL), xref, 0); /* Guard for nil value. */ | 1591 | emitir(IRTG(loadop, IRT_NIL), xref, 0); /* Guard for nil value. */ |
1247 | else if (xrefop == IR_HREF) | 1592 | else if (xrefop == IR_HREF) |
1248 | emitir(IRTG(oldv == niltvg(J2G(J)) ? IR_EQ : IR_NE, IRT_P32), | 1593 | emitir(IRTG(oldv == niltvg(J2G(J)) ? IR_EQ : IR_NE, IRT_PGC), |
1249 | xref, lj_ir_kkptr(J, niltvg(J2G(J)))); | 1594 | xref, lj_ir_kkptr(J, niltvg(J2G(J)))); |
1250 | if (ix->idxchain && lj_record_mm_lookup(J, ix, MM_newindex)) { | 1595 | if (ix->idxchain && lj_record_mm_lookup(J, ix, MM_newindex)) { |
1251 | lua_assert(hasmm); | 1596 | lj_assertJ(hasmm, "inconsistent metamethod handling"); |
1252 | goto handlemm; | 1597 | goto handlemm; |
1253 | } | 1598 | } |
1254 | lua_assert(!hasmm); | 1599 | lj_assertJ(!hasmm, "inconsistent metamethod handling"); |
1255 | if (oldv == niltvg(J2G(J))) { /* Need to insert a new key. */ | 1600 | if (oldv == niltvg(J2G(J))) { /* Need to insert a new key. */ |
1256 | TRef key = ix->key; | 1601 | TRef key = ix->key; |
1257 | if (tref_isinteger(key)) /* NEWREF needs a TValue as a key. */ | 1602 | if (tref_isinteger(key)) /* NEWREF needs a TValue as a key. */ |
1258 | key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT); | 1603 | key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT); |
1259 | else if (tref_isnumber(key) && tref_isk(key) && tvismzero(&ix->keyv)) | 1604 | else if (tref_isnumber(key) && tref_isk(key) && tvismzero(&ix->keyv)) |
1260 | key = lj_ir_knum_zero(J); /* Canonicalize -0.0 to +0.0. */ | 1605 | key = lj_ir_knum_zero(J); /* Canonicalize -0.0 to +0.0. */ |
1261 | xref = emitir(IRT(IR_NEWREF, IRT_P32), ix->tab, key); | 1606 | xref = emitir(IRT(IR_NEWREF, IRT_PGC), ix->tab, key); |
1262 | keybarrier = 0; /* NEWREF already takes care of the key barrier. */ | 1607 | keybarrier = 0; /* NEWREF already takes care of the key barrier. */ |
1608 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
1609 | if ((J->flags & JIT_F_OPT_SINK)) /* Avoid a separate flag. */ | ||
1610 | rec_idx_bump(J, ix); | ||
1611 | #endif | ||
1263 | } | 1612 | } |
1264 | } else if (!lj_opt_fwd_wasnonnil(J, loadop, tref_ref(xref))) { | 1613 | } else if (!lj_opt_fwd_wasnonnil(J, loadop, tref_ref(xref))) { |
1265 | /* Cannot derive that the previous value was non-nil, must do checks. */ | 1614 | /* Cannot derive that the previous value was non-nil, must do checks. */ |
1266 | if (xrefop == IR_HREF) /* Guard against store to niltv. */ | 1615 | if (xrefop == IR_HREF) /* Guard against store to niltv. */ |
1267 | emitir(IRTG(IR_NE, IRT_P32), xref, lj_ir_kkptr(J, niltvg(J2G(J)))); | 1616 | emitir(IRTG(IR_NE, IRT_PGC), xref, lj_ir_kkptr(J, niltvg(J2G(J)))); |
1268 | if (ix->idxchain) { /* Metamethod lookup required? */ | 1617 | if (ix->idxchain) { /* Metamethod lookup required? */ |
1269 | /* A check for NULL metatable is cheaper (hoistable) than a load. */ | 1618 | /* A check for NULL metatable is cheaper (hoistable) than a load. */ |
1270 | if (!mt) { | 1619 | if (!mt) { |
@@ -1286,7 +1635,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1286 | emitir(IRT(IR_TBAR, IRT_NIL), ix->tab, 0); | 1635 | emitir(IRT(IR_TBAR, IRT_NIL), ix->tab, 0); |
1287 | /* Invalidate neg. metamethod cache for stores with certain string keys. */ | 1636 | /* Invalidate neg. metamethod cache for stores with certain string keys. */ |
1288 | if (!nommstr(J, ix->key)) { | 1637 | if (!nommstr(J, ix->key)) { |
1289 | TRef fref = emitir(IRT(IR_FREF, IRT_P32), ix->tab, IRFL_TAB_NOMM); | 1638 | TRef fref = emitir(IRT(IR_FREF, IRT_PGC), ix->tab, IRFL_TAB_NOMM); |
1290 | emitir(IRT(IR_FSTORE, IRT_U8), fref, lj_ir_kint(J, 0)); | 1639 | emitir(IRT(IR_FSTORE, IRT_U8), fref, lj_ir_kint(J, 0)); |
1291 | } | 1640 | } |
1292 | J->needsnap = 1; | 1641 | J->needsnap = 1; |
@@ -1294,6 +1643,72 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1294 | } | 1643 | } |
1295 | } | 1644 | } |
1296 | 1645 | ||
1646 | /* Determine result type of table traversal. */ | ||
1647 | static IRType rec_next_types(GCtab *t, uint32_t idx) | ||
1648 | { | ||
1649 | for (; idx < t->asize; idx++) { | ||
1650 | cTValue *a = arrayslot(t, idx); | ||
1651 | if (LJ_LIKELY(!tvisnil(a))) | ||
1652 | return (LJ_DUALNUM ? IRT_INT : IRT_NUM) + (itype2irt(a) << 8); | ||
1653 | } | ||
1654 | idx -= t->asize; | ||
1655 | for (; idx <= t->hmask; idx++) { | ||
1656 | Node *n = &noderef(t->node)[idx]; | ||
1657 | if (!tvisnil(&n->val)) | ||
1658 | return itype2irt(&n->key) + (itype2irt(&n->val) << 8); | ||
1659 | } | ||
1660 | return IRT_NIL + (IRT_NIL << 8); | ||
1661 | } | ||
1662 | |||
1663 | /* Record a table traversal step aka next(). */ | ||
1664 | int lj_record_next(jit_State *J, RecordIndex *ix) | ||
1665 | { | ||
1666 | IRType t, tkey, tval; | ||
1667 | TRef trvk; | ||
1668 | t = rec_next_types(tabV(&ix->tabv), ix->keyv.u32.lo); | ||
1669 | tkey = (t & 0xff); tval = (t >> 8); | ||
1670 | trvk = lj_ir_call(J, IRCALL_lj_vm_next, ix->tab, ix->key); | ||
1671 | if (ix->mobj || tkey == IRT_NIL) { | ||
1672 | TRef idx = emitir(IRTI(IR_HIOP), trvk, trvk); | ||
1673 | /* Always check for invalid key from next() for nil result. */ | ||
1674 | if (!ix->mobj) emitir(IRTGI(IR_NE), idx, lj_ir_kint(J, -1)); | ||
1675 | ix->mobj = idx; | ||
1676 | } | ||
1677 | ix->key = lj_record_vload(J, trvk, 1, tkey); | ||
1678 | if (tkey == IRT_NIL || ix->idxchain) { /* Omit value type check. */ | ||
1679 | ix->val = TREF_NIL; | ||
1680 | return 1; | ||
1681 | } else { /* Need value. */ | ||
1682 | ix->val = lj_record_vload(J, trvk, 0, tval); | ||
1683 | return 2; | ||
1684 | } | ||
1685 | } | ||
1686 | |||
1687 | static void rec_tsetm(jit_State *J, BCReg ra, BCReg rn, int32_t i) | ||
1688 | { | ||
1689 | RecordIndex ix; | ||
1690 | cTValue *basev = J->L->base; | ||
1691 | GCtab *t = tabV(&basev[ra-1]); | ||
1692 | settabV(J->L, &ix.tabv, t); | ||
1693 | ix.tab = getslot(J, ra-1); | ||
1694 | ix.idxchain = 0; | ||
1695 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
1696 | if ((J->flags & JIT_F_OPT_SINK)) { | ||
1697 | if (t->asize < i+rn-ra) | ||
1698 | lj_tab_reasize(J->L, t, i+rn-ra); | ||
1699 | setnilV(&ix.keyv); | ||
1700 | rec_idx_bump(J, &ix); | ||
1701 | } | ||
1702 | #endif | ||
1703 | for (; ra < rn; i++, ra++) { | ||
1704 | setintV(&ix.keyv, i); | ||
1705 | ix.key = lj_ir_kint(J, i); | ||
1706 | copyTV(J->L, &ix.valv, &basev[ra]); | ||
1707 | ix.val = getslot(J, ra); | ||
1708 | lj_record_idx(J, &ix); | ||
1709 | } | ||
1710 | } | ||
1711 | |||
1297 | /* -- Upvalue access ------------------------------------------------------ */ | 1712 | /* -- Upvalue access ------------------------------------------------------ */ |
1298 | 1713 | ||
1299 | /* Check whether upvalue is immutable and ok to constify. */ | 1714 | /* Check whether upvalue is immutable and ok to constify. */ |
@@ -1330,13 +1745,17 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val) | |||
1330 | int needbarrier = 0; | 1745 | int needbarrier = 0; |
1331 | if (rec_upvalue_constify(J, uvp)) { /* Try to constify immutable upvalue. */ | 1746 | if (rec_upvalue_constify(J, uvp)) { /* Try to constify immutable upvalue. */ |
1332 | TRef tr, kfunc; | 1747 | TRef tr, kfunc; |
1333 | lua_assert(val == 0); | 1748 | lj_assertJ(val == 0, "bad usage"); |
1334 | if (!tref_isk(fn)) { /* Late specialization of current function. */ | 1749 | if (!tref_isk(fn)) { /* Late specialization of current function. */ |
1335 | if (J->pt->flags >= PROTO_CLC_POLY) | 1750 | if (J->pt->flags >= PROTO_CLC_POLY) |
1336 | goto noconstify; | 1751 | goto noconstify; |
1337 | kfunc = lj_ir_kfunc(J, J->fn); | 1752 | kfunc = lj_ir_kfunc(J, J->fn); |
1338 | emitir(IRTG(IR_EQ, IRT_FUNC), fn, kfunc); | 1753 | emitir(IRTG(IR_EQ, IRT_FUNC), fn, kfunc); |
1339 | J->base[-1] = TREF_FRAME | kfunc; | 1754 | #if LJ_FR2 |
1755 | J->base[-2] = kfunc; | ||
1756 | #else | ||
1757 | J->base[-1] = kfunc | TREF_FRAME; | ||
1758 | #endif | ||
1340 | fn = kfunc; | 1759 | fn = kfunc; |
1341 | } | 1760 | } |
1342 | tr = lj_record_constify(J, uvval(uvp)); | 1761 | tr = lj_record_constify(J, uvval(uvp)); |
@@ -1347,16 +1766,16 @@ noconstify: | |||
1347 | /* Note: this effectively limits LJ_MAX_UPVAL to 127. */ | 1766 | /* Note: this effectively limits LJ_MAX_UPVAL to 127. */ |
1348 | uv = (uv << 8) | (hashrot(uvp->dhash, uvp->dhash + HASH_BIAS) & 0xff); | 1767 | uv = (uv << 8) | (hashrot(uvp->dhash, uvp->dhash + HASH_BIAS) & 0xff); |
1349 | if (!uvp->closed) { | 1768 | if (!uvp->closed) { |
1350 | uref = tref_ref(emitir(IRTG(IR_UREFO, IRT_P32), fn, uv)); | 1769 | uref = tref_ref(emitir(IRTG(IR_UREFO, IRT_PGC), fn, uv)); |
1351 | /* In current stack? */ | 1770 | /* In current stack? */ |
1352 | if (uvval(uvp) >= tvref(J->L->stack) && | 1771 | if (uvval(uvp) >= tvref(J->L->stack) && |
1353 | uvval(uvp) < tvref(J->L->maxstack)) { | 1772 | uvval(uvp) < tvref(J->L->maxstack)) { |
1354 | int32_t slot = (int32_t)(uvval(uvp) - (J->L->base - J->baseslot)); | 1773 | int32_t slot = (int32_t)(uvval(uvp) - (J->L->base - J->baseslot)); |
1355 | if (slot >= 0) { /* Aliases an SSA slot? */ | 1774 | if (slot >= 0) { /* Aliases an SSA slot? */ |
1356 | emitir(IRTG(IR_EQ, IRT_P32), | 1775 | emitir(IRTG(IR_EQ, IRT_PGC), |
1357 | REF_BASE, | 1776 | REF_BASE, |
1358 | emitir(IRT(IR_ADD, IRT_P32), uref, | 1777 | emitir(IRT(IR_ADD, IRT_PGC), uref, |
1359 | lj_ir_kint(J, (slot - 1) * -8))); | 1778 | lj_ir_kint(J, (slot - 1 - LJ_FR2) * -8))); |
1360 | slot -= (int32_t)J->baseslot; /* Note: slot number may be negative! */ | 1779 | slot -= (int32_t)J->baseslot; /* Note: slot number may be negative! */ |
1361 | if (val == 0) { | 1780 | if (val == 0) { |
1362 | return getslot(J, slot); | 1781 | return getslot(J, slot); |
@@ -1367,12 +1786,12 @@ noconstify: | |||
1367 | } | 1786 | } |
1368 | } | 1787 | } |
1369 | } | 1788 | } |
1370 | emitir(IRTG(IR_UGT, IRT_P32), | 1789 | emitir(IRTG(IR_UGT, IRT_PGC), |
1371 | emitir(IRT(IR_SUB, IRT_P32), uref, REF_BASE), | 1790 | emitir(IRT(IR_SUB, IRT_PGC), uref, REF_BASE), |
1372 | lj_ir_kint(J, (J->baseslot + J->maxslot) * 8)); | 1791 | lj_ir_kint(J, (J->baseslot + J->maxslot) * 8)); |
1373 | } else { | 1792 | } else { |
1374 | needbarrier = 1; | 1793 | needbarrier = 1; |
1375 | uref = tref_ref(emitir(IRTG(IR_UREFC, IRT_P32), fn, uv)); | 1794 | uref = tref_ref(emitir(IRTG(IR_UREFC, IRT_PGC), fn, uv)); |
1376 | } | 1795 | } |
1377 | if (val == 0) { /* Upvalue load */ | 1796 | if (val == 0) { /* Upvalue load */ |
1378 | IRType t = itype2irt(uvval(uvp)); | 1797 | IRType t = itype2irt(uvval(uvp)); |
@@ -1411,16 +1830,16 @@ static void check_call_unroll(jit_State *J, TraceNo lnk) | |||
1411 | if (count + J->tailcalled > J->param[JIT_P_recunroll]) { | 1830 | if (count + J->tailcalled > J->param[JIT_P_recunroll]) { |
1412 | J->pc++; | 1831 | J->pc++; |
1413 | if (J->framedepth + J->retdepth == 0) | 1832 | if (J->framedepth + J->retdepth == 0) |
1414 | rec_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Tail-recursion. */ | 1833 | lj_record_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Tail-rec. */ |
1415 | else | 1834 | else |
1416 | rec_stop(J, LJ_TRLINK_UPREC, J->cur.traceno); /* Up-recursion. */ | 1835 | lj_record_stop(J, LJ_TRLINK_UPREC, J->cur.traceno); /* Up-recursion. */ |
1417 | } | 1836 | } |
1418 | } else { | 1837 | } else { |
1419 | if (count > J->param[JIT_P_callunroll]) { | 1838 | if (count > J->param[JIT_P_callunroll]) { |
1420 | if (lnk) { /* Possible tail- or up-recursion. */ | 1839 | if (lnk) { /* Possible tail- or up-recursion. */ |
1421 | lj_trace_flush(J, lnk); /* Flush trace that only returns. */ | 1840 | lj_trace_flush(J, lnk); /* Flush trace that only returns. */ |
1422 | /* Set a small, pseudo-random hotcount for a quick retry of JFUNC*. */ | 1841 | /* Set a small, pseudo-random hotcount for a quick retry of JFUNC*. */ |
1423 | hotcount_set(J2GG(J), J->pc+1, LJ_PRNG_BITS(J, 4)); | 1842 | hotcount_set(J2GG(J), J->pc+1, lj_prng_u64(&J2G(J)->prng) & 15u); |
1424 | } | 1843 | } |
1425 | lj_trace_err(J, LJ_TRERR_CUNROLL); | 1844 | lj_trace_err(J, LJ_TRERR_CUNROLL); |
1426 | } | 1845 | } |
@@ -1447,11 +1866,14 @@ static void rec_func_setup(jit_State *J) | |||
1447 | static void rec_func_vararg(jit_State *J) | 1866 | static void rec_func_vararg(jit_State *J) |
1448 | { | 1867 | { |
1449 | GCproto *pt = J->pt; | 1868 | GCproto *pt = J->pt; |
1450 | BCReg s, fixargs, vframe = J->maxslot+1; | 1869 | BCReg s, fixargs, vframe = J->maxslot+1+LJ_FR2; |
1451 | lua_assert((pt->flags & PROTO_VARARG)); | 1870 | lj_assertJ((pt->flags & PROTO_VARARG), "FUNCV in non-vararg function"); |
1452 | if (J->baseslot + vframe + pt->framesize >= LJ_MAX_JSLOTS) | 1871 | if (J->baseslot + vframe + pt->framesize >= LJ_MAX_JSLOTS) |
1453 | lj_trace_err(J, LJ_TRERR_STACKOV); | 1872 | lj_trace_err(J, LJ_TRERR_STACKOV); |
1454 | J->base[vframe-1] = J->base[-1]; /* Copy function up. */ | 1873 | J->base[vframe-1-LJ_FR2] = J->base[-1-LJ_FR2]; /* Copy function up. */ |
1874 | #if LJ_FR2 | ||
1875 | J->base[vframe-1] = TREF_FRAME; | ||
1876 | #endif | ||
1455 | /* Copy fixarg slots up and set their original slots to nil. */ | 1877 | /* Copy fixarg slots up and set their original slots to nil. */ |
1456 | fixargs = pt->numparams < J->maxslot ? pt->numparams : J->maxslot; | 1878 | fixargs = pt->numparams < J->maxslot ? pt->numparams : J->maxslot; |
1457 | for (s = 0; s < fixargs; s++) { | 1879 | for (s = 0; s < fixargs; s++) { |
@@ -1487,9 +1909,9 @@ static void rec_func_jit(jit_State *J, TraceNo lnk) | |||
1487 | } | 1909 | } |
1488 | J->instunroll = 0; /* Cannot continue across a compiled function. */ | 1910 | J->instunroll = 0; /* Cannot continue across a compiled function. */ |
1489 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) | 1911 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) |
1490 | rec_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Extra tail-recursion. */ | 1912 | lj_record_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Extra tail-rec. */ |
1491 | else | 1913 | else |
1492 | rec_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the function. */ | 1914 | lj_record_stop(J, LJ_TRLINK_ROOT, lnk); /* Link to the function. */ |
1493 | } | 1915 | } |
1494 | 1916 | ||
1495 | /* -- Vararg handling ----------------------------------------------------- */ | 1917 | /* -- Vararg handling ----------------------------------------------------- */ |
@@ -1513,8 +1935,10 @@ static int select_detect(jit_State *J) | |||
1513 | static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | 1935 | static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) |
1514 | { | 1936 | { |
1515 | int32_t numparams = J->pt->numparams; | 1937 | int32_t numparams = J->pt->numparams; |
1516 | ptrdiff_t nvararg = frame_delta(J->L->base-1) - numparams - 1; | 1938 | ptrdiff_t nvararg = frame_delta(J->L->base-1) - numparams - 1 - LJ_FR2; |
1517 | lua_assert(frame_isvarg(J->L->base-1)); | 1939 | lj_assertJ(frame_isvarg(J->L->base-1), "VARG in non-vararg frame"); |
1940 | if (LJ_FR2 && dst > J->maxslot) | ||
1941 | J->base[dst-1] = 0; /* Prevent resurrection of unrelated slot. */ | ||
1518 | if (J->framedepth > 0) { /* Simple case: varargs defined on-trace. */ | 1942 | if (J->framedepth > 0) { /* Simple case: varargs defined on-trace. */ |
1519 | ptrdiff_t i; | 1943 | ptrdiff_t i; |
1520 | if (nvararg < 0) nvararg = 0; | 1944 | if (nvararg < 0) nvararg = 0; |
@@ -1527,10 +1951,10 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | |||
1527 | if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS) | 1951 | if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS) |
1528 | lj_trace_err(J, LJ_TRERR_STACKOV); | 1952 | lj_trace_err(J, LJ_TRERR_STACKOV); |
1529 | for (i = 0; i < nresults; i++) | 1953 | for (i = 0; i < nresults; i++) |
1530 | J->base[dst+i] = i < nvararg ? getslot(J, i - nvararg - 1) : TREF_NIL; | 1954 | J->base[dst+i] = i < nvararg ? getslot(J, i - nvararg - 1 - LJ_FR2) : TREF_NIL; |
1531 | } else { /* Unknown number of varargs passed to trace. */ | 1955 | } else { /* Unknown number of varargs passed to trace. */ |
1532 | TRef fr = emitir(IRTI(IR_SLOAD), 0, IRSLOAD_READONLY|IRSLOAD_FRAME); | 1956 | TRef fr = emitir(IRTI(IR_SLOAD), LJ_FR2, IRSLOAD_READONLY|IRSLOAD_FRAME); |
1533 | int32_t frofs = 8*(1+numparams)+FRAME_VARG; | 1957 | int32_t frofs = 8*(1+LJ_FR2+numparams)+FRAME_VARG; |
1534 | if (nresults >= 0) { /* Known fixed number of results. */ | 1958 | if (nresults >= 0) { /* Known fixed number of results. */ |
1535 | ptrdiff_t i; | 1959 | ptrdiff_t i; |
1536 | if (nvararg > 0) { | 1960 | if (nvararg > 0) { |
@@ -1539,16 +1963,13 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | |||
1539 | if (nvararg >= nresults) | 1963 | if (nvararg >= nresults) |
1540 | emitir(IRTGI(IR_GE), fr, lj_ir_kint(J, frofs+8*(int32_t)nresults)); | 1964 | emitir(IRTGI(IR_GE), fr, lj_ir_kint(J, frofs+8*(int32_t)nresults)); |
1541 | else | 1965 | else |
1542 | emitir(IRTGI(IR_EQ), fr, lj_ir_kint(J, frame_ftsz(J->L->base-1))); | 1966 | emitir(IRTGI(IR_EQ), fr, |
1543 | vbase = emitir(IRTI(IR_SUB), REF_BASE, fr); | 1967 | lj_ir_kint(J, (int32_t)frame_ftsz(J->L->base-1))); |
1544 | vbase = emitir(IRT(IR_ADD, IRT_P32), vbase, lj_ir_kint(J, frofs-8)); | 1968 | vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr); |
1969 | vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, lj_ir_kint(J, frofs-8*(1+LJ_FR2))); | ||
1545 | for (i = 0; i < nload; i++) { | 1970 | for (i = 0; i < nload; i++) { |
1546 | IRType t = itype2irt(&J->L->base[i-1-nvararg]); | 1971 | IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]); |
1547 | TRef aref = emitir(IRT(IR_AREF, IRT_P32), | 1972 | J->base[dst+i] = lj_record_vload(J, vbase, (MSize)i, t); |
1548 | vbase, lj_ir_kint(J, (int32_t)i)); | ||
1549 | TRef tr = emitir(IRTG(IR_VLOAD, t), aref, 0); | ||
1550 | if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ | ||
1551 | J->base[dst+i] = tr; | ||
1552 | } | 1973 | } |
1553 | } else { | 1974 | } else { |
1554 | emitir(IRTGI(IR_LE), fr, lj_ir_kint(J, frofs)); | 1975 | emitir(IRTGI(IR_LE), fr, lj_ir_kint(J, frofs)); |
@@ -1591,15 +2012,15 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | |||
1591 | } | 2012 | } |
1592 | if (idx != 0 && idx <= nvararg) { | 2013 | if (idx != 0 && idx <= nvararg) { |
1593 | IRType t; | 2014 | IRType t; |
1594 | TRef aref, vbase = emitir(IRTI(IR_SUB), REF_BASE, fr); | 2015 | TRef aref, vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr); |
1595 | vbase = emitir(IRT(IR_ADD, IRT_P32), vbase, lj_ir_kint(J, frofs-8)); | 2016 | vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, |
1596 | t = itype2irt(&J->L->base[idx-2-nvararg]); | 2017 | lj_ir_kint(J, frofs-(8<<LJ_FR2))); |
1597 | aref = emitir(IRT(IR_AREF, IRT_P32), vbase, tridx); | 2018 | t = itype2irt(&J->L->base[idx-2-LJ_FR2-nvararg]); |
1598 | tr = emitir(IRTG(IR_VLOAD, t), aref, 0); | 2019 | aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx); |
1599 | if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ | 2020 | tr = lj_record_vload(J, aref, 0, t); |
1600 | } | 2021 | } |
1601 | J->base[dst-2] = tr; | 2022 | J->base[dst-2-LJ_FR2] = tr; |
1602 | J->maxslot = dst-1; | 2023 | J->maxslot = dst-1-LJ_FR2; |
1603 | J->bcskip = 2; /* Skip CALLM + select. */ | 2024 | J->bcskip = 2; /* Skip CALLM + select. */ |
1604 | } else { | 2025 | } else { |
1605 | nyivarg: | 2026 | nyivarg: |
@@ -1615,8 +2036,63 @@ static TRef rec_tnew(jit_State *J, uint32_t ah) | |||
1615 | { | 2036 | { |
1616 | uint32_t asize = ah & 0x7ff; | 2037 | uint32_t asize = ah & 0x7ff; |
1617 | uint32_t hbits = ah >> 11; | 2038 | uint32_t hbits = ah >> 11; |
2039 | TRef tr; | ||
1618 | if (asize == 0x7ff) asize = 0x801; | 2040 | if (asize == 0x7ff) asize = 0x801; |
1619 | return emitir(IRTG(IR_TNEW, IRT_TAB), asize, hbits); | 2041 | tr = emitir(IRTG(IR_TNEW, IRT_TAB), asize, hbits); |
2042 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
2043 | J->rbchash[(tr & (RBCHASH_SLOTS-1))].ref = tref_ref(tr); | ||
2044 | setmref(J->rbchash[(tr & (RBCHASH_SLOTS-1))].pc, J->pc); | ||
2045 | setgcref(J->rbchash[(tr & (RBCHASH_SLOTS-1))].pt, obj2gco(J->pt)); | ||
2046 | #endif | ||
2047 | return tr; | ||
2048 | } | ||
2049 | |||
2050 | /* -- Concatenation ------------------------------------------------------- */ | ||
2051 | |||
2052 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) | ||
2053 | { | ||
2054 | TRef *top = &J->base[topslot]; | ||
2055 | TValue savetv[5+LJ_FR2]; | ||
2056 | BCReg s; | ||
2057 | RecordIndex ix; | ||
2058 | lj_assertJ(baseslot < topslot, "bad CAT arg"); | ||
2059 | for (s = baseslot; s <= topslot; s++) | ||
2060 | (void)getslot(J, s); /* Ensure all arguments have a reference. */ | ||
2061 | if (tref_isnumber_str(top[0]) && tref_isnumber_str(top[-1])) { | ||
2062 | TRef tr, hdr, *trp, *xbase, *base = &J->base[baseslot]; | ||
2063 | /* First convert numbers to strings. */ | ||
2064 | for (trp = top; trp >= base; trp--) { | ||
2065 | if (tref_isnumber(*trp)) | ||
2066 | *trp = emitir(IRT(IR_TOSTR, IRT_STR), *trp, | ||
2067 | tref_isnum(*trp) ? IRTOSTR_NUM : IRTOSTR_INT); | ||
2068 | else if (!tref_isstr(*trp)) | ||
2069 | break; | ||
2070 | } | ||
2071 | xbase = ++trp; | ||
2072 | tr = hdr = emitir(IRT(IR_BUFHDR, IRT_PGC), | ||
2073 | lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET); | ||
2074 | do { | ||
2075 | tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, *trp++); | ||
2076 | } while (trp <= top); | ||
2077 | tr = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); | ||
2078 | J->maxslot = (BCReg)(xbase - J->base); | ||
2079 | if (xbase == base) return tr; /* Return simple concatenation result. */ | ||
2080 | /* Pass partial result. */ | ||
2081 | topslot = J->maxslot--; | ||
2082 | *xbase = tr; | ||
2083 | top = xbase; | ||
2084 | setstrV(J->L, &ix.keyv, &J2G(J)->strempty); /* Simulate string result. */ | ||
2085 | } else { | ||
2086 | J->maxslot = topslot-1; | ||
2087 | copyTV(J->L, &ix.keyv, &J->L->base[topslot]); | ||
2088 | } | ||
2089 | copyTV(J->L, &ix.tabv, &J->L->base[topslot-1]); | ||
2090 | ix.tab = top[-1]; | ||
2091 | ix.key = top[0]; | ||
2092 | memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */ | ||
2093 | rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */ | ||
2094 | memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ | ||
2095 | return 0; /* No result yet. */ | ||
1620 | } | 2096 | } |
1621 | 2097 | ||
1622 | /* -- Record bytecode ops ------------------------------------------------- */ | 2098 | /* -- Record bytecode ops ------------------------------------------------- */ |
@@ -1637,7 +2113,15 @@ static void rec_comp_fixup(jit_State *J, const BCIns *pc, int cond) | |||
1637 | const BCIns *npc = pc + 2 + (cond ? bc_j(jmpins) : 0); | 2113 | const BCIns *npc = pc + 2 + (cond ? bc_j(jmpins) : 0); |
1638 | SnapShot *snap = &J->cur.snap[J->cur.nsnap-1]; | 2114 | SnapShot *snap = &J->cur.snap[J->cur.nsnap-1]; |
1639 | /* Set PC to opposite target to avoid re-recording the comp. in side trace. */ | 2115 | /* Set PC to opposite target to avoid re-recording the comp. in side trace. */ |
2116 | #if LJ_FR2 | ||
2117 | SnapEntry *flink = &J->cur.snapmap[snap->mapofs + snap->nent]; | ||
2118 | uint64_t pcbase; | ||
2119 | memcpy(&pcbase, flink, sizeof(uint64_t)); | ||
2120 | pcbase = (pcbase & 0xff) | (u64ptr(npc) << 8); | ||
2121 | memcpy(flink, &pcbase, sizeof(uint64_t)); | ||
2122 | #else | ||
1640 | J->cur.snapmap[snap->mapofs + snap->nent] = SNAP_MKPC(npc); | 2123 | J->cur.snapmap[snap->mapofs + snap->nent] = SNAP_MKPC(npc); |
2124 | #endif | ||
1641 | J->needsnap = 1; | 2125 | J->needsnap = 1; |
1642 | if (bc_a(jmpins) < J->maxslot) J->maxslot = bc_a(jmpins); | 2126 | if (bc_a(jmpins) < J->maxslot) J->maxslot = bc_a(jmpins); |
1643 | lj_snap_shrink(J); /* Shrink last snapshot if possible. */ | 2127 | lj_snap_shrink(J); /* Shrink last snapshot if possible. */ |
@@ -1657,7 +2141,7 @@ void lj_record_ins(jit_State *J) | |||
1657 | if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) { | 2141 | if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) { |
1658 | switch (J->postproc) { | 2142 | switch (J->postproc) { |
1659 | case LJ_POST_FIXCOMP: /* Fixup comparison. */ | 2143 | case LJ_POST_FIXCOMP: /* Fixup comparison. */ |
1660 | pc = frame_pc(&J2G(J)->tmptv); | 2144 | pc = (const BCIns *)(uintptr_t)J2G(J)->tmptv.u64; |
1661 | rec_comp_fixup(J, pc, (!tvistruecond(&J2G(J)->tmptv2) ^ (bc_op(*pc)&1))); | 2145 | rec_comp_fixup(J, pc, (!tvistruecond(&J2G(J)->tmptv2) ^ (bc_op(*pc)&1))); |
1662 | /* fallthrough */ | 2146 | /* fallthrough */ |
1663 | case LJ_POST_FIXGUARD: /* Fixup and emit pending guard. */ | 2147 | case LJ_POST_FIXGUARD: /* Fixup and emit pending guard. */ |
@@ -1695,7 +2179,7 @@ void lj_record_ins(jit_State *J) | |||
1695 | if (bc_op(*J->pc) >= BC__MAX) | 2179 | if (bc_op(*J->pc) >= BC__MAX) |
1696 | return; | 2180 | return; |
1697 | break; | 2181 | break; |
1698 | default: lua_assert(0); break; | 2182 | default: lj_assertJ(0, "bad post-processing mode"); break; |
1699 | } | 2183 | } |
1700 | J->postproc = LJ_POST_NONE; | 2184 | J->postproc = LJ_POST_NONE; |
1701 | } | 2185 | } |
@@ -1703,7 +2187,7 @@ void lj_record_ins(jit_State *J) | |||
1703 | /* Need snapshot before recording next bytecode (e.g. after a store). */ | 2187 | /* Need snapshot before recording next bytecode (e.g. after a store). */ |
1704 | if (J->needsnap) { | 2188 | if (J->needsnap) { |
1705 | J->needsnap = 0; | 2189 | J->needsnap = 0; |
1706 | lj_snap_purge(J); | 2190 | if (J->pt) lj_snap_purge(J); |
1707 | lj_snap_add(J); | 2191 | lj_snap_add(J); |
1708 | J->mergesnap = 1; | 2192 | J->mergesnap = 1; |
1709 | } | 2193 | } |
@@ -1725,6 +2209,10 @@ void lj_record_ins(jit_State *J) | |||
1725 | rec_check_ir(J); | 2209 | rec_check_ir(J); |
1726 | #endif | 2210 | #endif |
1727 | 2211 | ||
2212 | #if LJ_HASPROFILE | ||
2213 | rec_profile_ins(J, pc); | ||
2214 | #endif | ||
2215 | |||
1728 | /* Keep a copy of the runtime values of var/num/str operands. */ | 2216 | /* Keep a copy of the runtime values of var/num/str operands. */ |
1729 | #define rav (&ix.valv) | 2217 | #define rav (&ix.valv) |
1730 | #define rbv (&ix.tabv) | 2218 | #define rbv (&ix.tabv) |
@@ -1751,9 +2239,10 @@ void lj_record_ins(jit_State *J) | |||
1751 | switch (bcmode_c(op)) { | 2239 | switch (bcmode_c(op)) { |
1752 | case BCMvar: | 2240 | case BCMvar: |
1753 | copyTV(J->L, rcv, &lbase[rc]); ix.key = rc = getslot(J, rc); break; | 2241 | copyTV(J->L, rcv, &lbase[rc]); ix.key = rc = getslot(J, rc); break; |
1754 | case BCMpri: setitype(rcv, ~rc); ix.key = rc = TREF_PRI(IRT_NIL+rc); break; | 2242 | case BCMpri: setpriV(rcv, ~rc); ix.key = rc = TREF_PRI(IRT_NIL+rc); break; |
1755 | case BCMnum: { cTValue *tv = proto_knumtv(J->pt, rc); | 2243 | case BCMnum: { cTValue *tv = proto_knumtv(J->pt, rc); |
1756 | copyTV(J->L, rcv, tv); ix.key = rc = tvisint(tv) ? lj_ir_kint(J, intV(tv)) : | 2244 | copyTV(J->L, rcv, tv); ix.key = rc = tvisint(tv) ? lj_ir_kint(J, intV(tv)) : |
2245 | tv->u32.hi == LJ_KEYINDEX ? (lj_ir_kint(J, 0) | TREF_KEYINDEX) : | ||
1757 | lj_ir_knumint(J, numV(tv)); } break; | 2246 | lj_ir_knumint(J, numV(tv)); } break; |
1758 | case BCMstr: { GCstr *s = gco2str(proto_kgc(J->pt, ~(ptrdiff_t)rc)); | 2247 | case BCMstr: { GCstr *s = gco2str(proto_kgc(J->pt, ~(ptrdiff_t)rc)); |
1759 | setstrV(J->L, rcv, s); ix.key = rc = lj_ir_kstr(J, s); } break; | 2248 | setstrV(J->L, rcv, s); ix.key = rc = lj_ir_kstr(J, s); } break; |
@@ -1846,6 +2335,18 @@ void lj_record_ins(jit_State *J) | |||
1846 | J->maxslot = bc_a(pc[1]); /* Shrink used slots. */ | 2335 | J->maxslot = bc_a(pc[1]); /* Shrink used slots. */ |
1847 | break; | 2336 | break; |
1848 | 2337 | ||
2338 | case BC_ISTYPE: case BC_ISNUM: | ||
2339 | /* These coercions need to correspond with lj_meta_istype(). */ | ||
2340 | if (LJ_DUALNUM && rc == ~LJ_TNUMX+1) | ||
2341 | ra = lj_opt_narrow_toint(J, ra); | ||
2342 | else if (rc == ~LJ_TNUMX+2) | ||
2343 | ra = lj_ir_tonum(J, ra); | ||
2344 | else if (rc == ~LJ_TSTR+1) | ||
2345 | ra = lj_ir_tostr(J, ra); | ||
2346 | /* else: type specialization suffices. */ | ||
2347 | J->base[bc_a(ins)] = ra; | ||
2348 | break; | ||
2349 | |||
1849 | /* -- Unary ops --------------------------------------------------------- */ | 2350 | /* -- Unary ops --------------------------------------------------------- */ |
1850 | 2351 | ||
1851 | case BC_NOT: | 2352 | case BC_NOT: |
@@ -1857,7 +2358,7 @@ void lj_record_ins(jit_State *J) | |||
1857 | if (tref_isstr(rc)) | 2358 | if (tref_isstr(rc)) |
1858 | rc = emitir(IRTI(IR_FLOAD), rc, IRFL_STR_LEN); | 2359 | rc = emitir(IRTI(IR_FLOAD), rc, IRFL_STR_LEN); |
1859 | else if (!LJ_52 && tref_istab(rc)) | 2360 | else if (!LJ_52 && tref_istab(rc)) |
1860 | rc = lj_ir_call(J, IRCALL_lj_tab_len, rc); | 2361 | rc = emitir(IRTI(IR_ALEN), rc, TREF_NIL); |
1861 | else | 2362 | else |
1862 | rc = rec_mm_len(J, rc, rcv); | 2363 | rc = rec_mm_len(J, rc, rcv); |
1863 | break; | 2364 | break; |
@@ -1904,16 +2405,28 @@ void lj_record_ins(jit_State *J) | |||
1904 | 2405 | ||
1905 | case BC_POW: | 2406 | case BC_POW: |
1906 | if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) | 2407 | if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) |
1907 | rc = lj_opt_narrow_pow(J, rb, rc, rbv, rcv); | 2408 | rc = lj_opt_narrow_arith(J, rb, rc, rbv, rcv, IR_POW); |
1908 | else | 2409 | else |
1909 | rc = rec_mm_arith(J, &ix, MM_pow); | 2410 | rc = rec_mm_arith(J, &ix, MM_pow); |
1910 | break; | 2411 | break; |
1911 | 2412 | ||
2413 | /* -- Miscellaneous ops ------------------------------------------------- */ | ||
2414 | |||
2415 | case BC_CAT: | ||
2416 | rc = rec_cat(J, rb, rc); | ||
2417 | break; | ||
2418 | |||
1912 | /* -- Constant and move ops --------------------------------------------- */ | 2419 | /* -- Constant and move ops --------------------------------------------- */ |
1913 | 2420 | ||
1914 | case BC_MOV: | 2421 | case BC_MOV: |
1915 | /* Clear gap of method call to avoid resurrecting previous refs. */ | 2422 | /* Clear gap of method call to avoid resurrecting previous refs. */ |
1916 | if (ra > J->maxslot) J->base[ra-1] = 0; | 2423 | if (ra > J->maxslot) { |
2424 | #if LJ_FR2 | ||
2425 | memset(J->base + J->maxslot, 0, (ra - J->maxslot) * sizeof(TRef)); | ||
2426 | #else | ||
2427 | J->base[ra-1] = 0; | ||
2428 | #endif | ||
2429 | } | ||
1917 | break; | 2430 | break; |
1918 | case BC_KSTR: case BC_KNUM: case BC_KPRI: | 2431 | case BC_KSTR: case BC_KNUM: case BC_KPRI: |
1919 | break; | 2432 | break; |
@@ -1921,6 +2434,8 @@ void lj_record_ins(jit_State *J) | |||
1921 | rc = lj_ir_kint(J, (int32_t)(int16_t)rc); | 2434 | rc = lj_ir_kint(J, (int32_t)(int16_t)rc); |
1922 | break; | 2435 | break; |
1923 | case BC_KNIL: | 2436 | case BC_KNIL: |
2437 | if (LJ_FR2 && ra > J->maxslot) | ||
2438 | J->base[ra-1] = 0; | ||
1924 | while (ra <= rc) | 2439 | while (ra <= rc) |
1925 | J->base[ra++] = TREF_NIL; | 2440 | J->base[ra++] = TREF_NIL; |
1926 | if (rc >= J->maxslot) J->maxslot = rc+1; | 2441 | if (rc >= J->maxslot) J->maxslot = rc+1; |
@@ -1957,6 +2472,15 @@ void lj_record_ins(jit_State *J) | |||
1957 | ix.idxchain = LJ_MAX_IDXCHAIN; | 2472 | ix.idxchain = LJ_MAX_IDXCHAIN; |
1958 | rc = lj_record_idx(J, &ix); | 2473 | rc = lj_record_idx(J, &ix); |
1959 | break; | 2474 | break; |
2475 | case BC_TGETR: case BC_TSETR: | ||
2476 | ix.idxchain = 0; | ||
2477 | rc = lj_record_idx(J, &ix); | ||
2478 | break; | ||
2479 | |||
2480 | case BC_TSETM: | ||
2481 | rec_tsetm(J, ra, (BCReg)(J->L->top - J->L->base), (int32_t)rcv->u32.lo); | ||
2482 | J->maxslot = ra; /* The table slot at ra-1 is the highest used slot. */ | ||
2483 | break; | ||
1960 | 2484 | ||
1961 | case BC_TNEW: | 2485 | case BC_TNEW: |
1962 | rc = rec_tnew(J, rc); | 2486 | rc = rec_tnew(J, rc); |
@@ -1964,33 +2488,38 @@ void lj_record_ins(jit_State *J) | |||
1964 | case BC_TDUP: | 2488 | case BC_TDUP: |
1965 | rc = emitir(IRTG(IR_TDUP, IRT_TAB), | 2489 | rc = emitir(IRTG(IR_TDUP, IRT_TAB), |
1966 | lj_ir_ktab(J, gco2tab(proto_kgc(J->pt, ~(ptrdiff_t)rc))), 0); | 2490 | lj_ir_ktab(J, gco2tab(proto_kgc(J->pt, ~(ptrdiff_t)rc))), 0); |
2491 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
2492 | J->rbchash[(rc & (RBCHASH_SLOTS-1))].ref = tref_ref(rc); | ||
2493 | setmref(J->rbchash[(rc & (RBCHASH_SLOTS-1))].pc, pc); | ||
2494 | setgcref(J->rbchash[(rc & (RBCHASH_SLOTS-1))].pt, obj2gco(J->pt)); | ||
2495 | #endif | ||
1967 | break; | 2496 | break; |
1968 | 2497 | ||
1969 | /* -- Calls and vararg handling ----------------------------------------- */ | 2498 | /* -- Calls and vararg handling ----------------------------------------- */ |
1970 | 2499 | ||
1971 | case BC_ITERC: | 2500 | case BC_ITERC: |
1972 | J->base[ra] = getslot(J, ra-3); | 2501 | J->base[ra] = getslot(J, ra-3); |
1973 | J->base[ra+1] = getslot(J, ra-2); | 2502 | J->base[ra+1+LJ_FR2] = getslot(J, ra-2); |
1974 | J->base[ra+2] = getslot(J, ra-1); | 2503 | J->base[ra+2+LJ_FR2] = getslot(J, ra-1); |
1975 | { /* Do the actual copy now because lj_record_call needs the values. */ | 2504 | { /* Do the actual copy now because lj_record_call needs the values. */ |
1976 | TValue *b = &J->L->base[ra]; | 2505 | TValue *b = &J->L->base[ra]; |
1977 | copyTV(J->L, b, b-3); | 2506 | copyTV(J->L, b, b-3); |
1978 | copyTV(J->L, b+1, b-2); | 2507 | copyTV(J->L, b+1+LJ_FR2, b-2); |
1979 | copyTV(J->L, b+2, b-1); | 2508 | copyTV(J->L, b+2+LJ_FR2, b-1); |
1980 | } | 2509 | } |
1981 | lj_record_call(J, ra, (ptrdiff_t)rc-1); | 2510 | lj_record_call(J, ra, (ptrdiff_t)rc-1); |
1982 | break; | 2511 | break; |
1983 | 2512 | ||
1984 | /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */ | 2513 | /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */ |
1985 | case BC_CALLM: | 2514 | case BC_CALLM: |
1986 | rc = (BCReg)(J->L->top - J->L->base) - ra; | 2515 | rc = (BCReg)(J->L->top - J->L->base) - ra - LJ_FR2; |
1987 | /* fallthrough */ | 2516 | /* fallthrough */ |
1988 | case BC_CALL: | 2517 | case BC_CALL: |
1989 | lj_record_call(J, ra, (ptrdiff_t)rc-1); | 2518 | lj_record_call(J, ra, (ptrdiff_t)rc-1); |
1990 | break; | 2519 | break; |
1991 | 2520 | ||
1992 | case BC_CALLMT: | 2521 | case BC_CALLMT: |
1993 | rc = (BCReg)(J->L->top - J->L->base) - ra; | 2522 | rc = (BCReg)(J->L->top - J->L->base) - ra - LJ_FR2; |
1994 | /* fallthrough */ | 2523 | /* fallthrough */ |
1995 | case BC_CALLT: | 2524 | case BC_CALLT: |
1996 | lj_record_tailcall(J, ra, (ptrdiff_t)rc-1); | 2525 | lj_record_tailcall(J, ra, (ptrdiff_t)rc-1); |
@@ -2007,6 +2536,9 @@ void lj_record_ins(jit_State *J) | |||
2007 | rc = (BCReg)(J->L->top - J->L->base) - ra + 1; | 2536 | rc = (BCReg)(J->L->top - J->L->base) - ra + 1; |
2008 | /* fallthrough */ | 2537 | /* fallthrough */ |
2009 | case BC_RET: case BC_RET0: case BC_RET1: | 2538 | case BC_RET: case BC_RET0: case BC_RET1: |
2539 | #if LJ_HASPROFILE | ||
2540 | rec_profile_ret(J); | ||
2541 | #endif | ||
2010 | lj_record_ret(J, ra, (ptrdiff_t)rc-1); | 2542 | lj_record_ret(J, ra, (ptrdiff_t)rc-1); |
2011 | break; | 2543 | break; |
2012 | 2544 | ||
@@ -2017,9 +2549,10 @@ void lj_record_ins(jit_State *J) | |||
2017 | J->loopref = J->cur.nins; | 2549 | J->loopref = J->cur.nins; |
2018 | break; | 2550 | break; |
2019 | case BC_JFORI: | 2551 | case BC_JFORI: |
2020 | lua_assert(bc_op(pc[(ptrdiff_t)rc-BCBIAS_J]) == BC_JFORL); | 2552 | lj_assertJ(bc_op(pc[(ptrdiff_t)rc-BCBIAS_J]) == BC_JFORL, |
2553 | "JFORI does not point to JFORL"); | ||
2021 | if (rec_for(J, pc, 0) != LOOPEV_LEAVE) /* Link to existing loop. */ | 2554 | if (rec_for(J, pc, 0) != LOOPEV_LEAVE) /* Link to existing loop. */ |
2022 | rec_stop(J, LJ_TRLINK_ROOT, bc_d(pc[(ptrdiff_t)rc-BCBIAS_J])); | 2555 | lj_record_stop(J, LJ_TRLINK_ROOT, bc_d(pc[(ptrdiff_t)rc-BCBIAS_J])); |
2023 | /* Continue tracing if the loop is not entered. */ | 2556 | /* Continue tracing if the loop is not entered. */ |
2024 | break; | 2557 | break; |
2025 | 2558 | ||
@@ -2029,6 +2562,9 @@ void lj_record_ins(jit_State *J) | |||
2029 | case BC_ITERL: | 2562 | case BC_ITERL: |
2030 | rec_loop_interp(J, pc, rec_iterl(J, *pc)); | 2563 | rec_loop_interp(J, pc, rec_iterl(J, *pc)); |
2031 | break; | 2564 | break; |
2565 | case BC_ITERN: | ||
2566 | rec_loop_interp(J, pc, rec_itern(J, ra, rb)); | ||
2567 | break; | ||
2032 | case BC_LOOP: | 2568 | case BC_LOOP: |
2033 | rec_loop_interp(J, pc, rec_loop(J, ra, 1)); | 2569 | rec_loop_interp(J, pc, rec_loop(J, ra, 1)); |
2034 | break; | 2570 | break; |
@@ -2041,7 +2577,8 @@ void lj_record_ins(jit_State *J) | |||
2041 | break; | 2577 | break; |
2042 | case BC_JLOOP: | 2578 | case BC_JLOOP: |
2043 | rec_loop_jit(J, rc, rec_loop(J, ra, | 2579 | rec_loop_jit(J, rc, rec_loop(J, ra, |
2044 | !bc_isret(bc_op(traceref(J, rc)->startins)))); | 2580 | !bc_isret(bc_op(traceref(J, rc)->startins)) && |
2581 | bc_op(traceref(J, rc)->startins) != BC_ITERN)); | ||
2045 | break; | 2582 | break; |
2046 | 2583 | ||
2047 | case BC_IFORL: | 2584 | case BC_IFORL: |
@@ -2057,6 +2594,10 @@ void lj_record_ins(jit_State *J) | |||
2057 | J->maxslot = ra; /* Shrink used slots. */ | 2594 | J->maxslot = ra; /* Shrink used slots. */ |
2058 | break; | 2595 | break; |
2059 | 2596 | ||
2597 | case BC_ISNEXT: | ||
2598 | rec_isnext(J, ra); | ||
2599 | break; | ||
2600 | |||
2060 | /* -- Function headers -------------------------------------------------- */ | 2601 | /* -- Function headers -------------------------------------------------- */ |
2061 | 2602 | ||
2062 | case BC_FUNCF: | 2603 | case BC_FUNCF: |
@@ -2071,7 +2612,8 @@ void lj_record_ins(jit_State *J) | |||
2071 | rec_func_lua(J); | 2612 | rec_func_lua(J); |
2072 | break; | 2613 | break; |
2073 | case BC_JFUNCV: | 2614 | case BC_JFUNCV: |
2074 | lua_assert(0); /* Cannot happen. No hotcall counting for varag funcs. */ | 2615 | /* Cannot happen. No hotcall counting for varag funcs. */ |
2616 | lj_assertJ(0, "unsupported vararg hotcall"); | ||
2075 | break; | 2617 | break; |
2076 | 2618 | ||
2077 | case BC_FUNCC: | 2619 | case BC_FUNCC: |
@@ -2085,12 +2627,8 @@ void lj_record_ins(jit_State *J) | |||
2085 | break; | 2627 | break; |
2086 | } | 2628 | } |
2087 | /* fallthrough */ | 2629 | /* fallthrough */ |
2088 | case BC_ITERN: | ||
2089 | case BC_ISNEXT: | ||
2090 | case BC_CAT: | ||
2091 | case BC_UCLO: | 2630 | case BC_UCLO: |
2092 | case BC_FNEW: | 2631 | case BC_FNEW: |
2093 | case BC_TSETM: | ||
2094 | setintV(&J->errinfo, (int32_t)op); | 2632 | setintV(&J->errinfo, (int32_t)op); |
2095 | lj_trace_err_info(J, LJ_TRERR_NYIBC); | 2633 | lj_trace_err_info(J, LJ_TRERR_NYIBC); |
2096 | break; | 2634 | break; |
@@ -2099,15 +2637,21 @@ void lj_record_ins(jit_State *J) | |||
2099 | /* rc == 0 if we have no result yet, e.g. pending __index metamethod call. */ | 2637 | /* rc == 0 if we have no result yet, e.g. pending __index metamethod call. */ |
2100 | if (bcmode_a(op) == BCMdst && rc) { | 2638 | if (bcmode_a(op) == BCMdst && rc) { |
2101 | J->base[ra] = rc; | 2639 | J->base[ra] = rc; |
2102 | if (ra >= J->maxslot) J->maxslot = ra+1; | 2640 | if (ra >= J->maxslot) { |
2641 | #if LJ_FR2 | ||
2642 | if (ra > J->maxslot) J->base[ra-1] = 0; | ||
2643 | #endif | ||
2644 | J->maxslot = ra+1; | ||
2645 | } | ||
2103 | } | 2646 | } |
2104 | 2647 | ||
2105 | #undef rav | 2648 | #undef rav |
2106 | #undef rbv | 2649 | #undef rbv |
2107 | #undef rcv | 2650 | #undef rcv |
2108 | 2651 | ||
2109 | /* Limit the number of recorded IR instructions. */ | 2652 | /* Limit the number of recorded IR instructions and constants. */ |
2110 | if (J->cur.nins > REF_FIRST+(IRRef)J->param[JIT_P_maxrecord]) | 2653 | if (J->cur.nins > REF_FIRST+(IRRef)J->param[JIT_P_maxrecord] || |
2654 | J->cur.nk < REF_BIAS-(IRRef)J->param[JIT_P_maxirconst]) | ||
2111 | lj_trace_err(J, LJ_TRERR_TRACEOV); | 2655 | lj_trace_err(J, LJ_TRERR_TRACEOV); |
2112 | } | 2656 | } |
2113 | 2657 | ||
@@ -2127,13 +2671,22 @@ static const BCIns *rec_setup_root(jit_State *J) | |||
2127 | J->bc_min = pc; | 2671 | J->bc_min = pc; |
2128 | break; | 2672 | break; |
2129 | case BC_ITERL: | 2673 | case BC_ITERL: |
2130 | lua_assert(bc_op(pc[-1]) == BC_ITERC); | 2674 | if (bc_op(pc[-1]) == BC_JLOOP) |
2675 | lj_trace_err(J, LJ_TRERR_LINNER); | ||
2676 | lj_assertJ(bc_op(pc[-1]) == BC_ITERC, "no ITERC before ITERL"); | ||
2131 | J->maxslot = ra + bc_b(pc[-1]) - 1; | 2677 | J->maxslot = ra + bc_b(pc[-1]) - 1; |
2132 | J->bc_extent = (MSize)(-bc_j(ins))*sizeof(BCIns); | 2678 | J->bc_extent = (MSize)(-bc_j(ins))*sizeof(BCIns); |
2133 | pc += 1+bc_j(ins); | 2679 | pc += 1+bc_j(ins); |
2134 | lua_assert(bc_op(pc[-1]) == BC_JMP); | 2680 | lj_assertJ(bc_op(pc[-1]) == BC_JMP, "ITERL does not point to JMP+1"); |
2135 | J->bc_min = pc; | 2681 | J->bc_min = pc; |
2136 | break; | 2682 | break; |
2683 | case BC_ITERN: | ||
2684 | lj_assertJ(bc_op(pc[1]) == BC_ITERL, "no ITERL after ITERN"); | ||
2685 | J->maxslot = ra; | ||
2686 | J->bc_extent = (MSize)(-bc_j(pc[1]))*sizeof(BCIns); | ||
2687 | J->bc_min = pc+2 + bc_j(pc[1]); | ||
2688 | J->state = LJ_TRACE_RECORD_1ST; /* Record the first ITERN, too. */ | ||
2689 | break; | ||
2137 | case BC_LOOP: | 2690 | case BC_LOOP: |
2138 | /* Only check BC range for real loops, but not for "repeat until true". */ | 2691 | /* Only check BC range for real loops, but not for "repeat until true". */ |
2139 | pcj = pc + bc_j(ins); | 2692 | pcj = pc + bc_j(ins); |
@@ -2156,8 +2709,14 @@ static const BCIns *rec_setup_root(jit_State *J) | |||
2156 | J->maxslot = J->pt->numparams; | 2709 | J->maxslot = J->pt->numparams; |
2157 | pc++; | 2710 | pc++; |
2158 | break; | 2711 | break; |
2712 | case BC_CALLM: | ||
2713 | case BC_CALL: | ||
2714 | case BC_ITERC: | ||
2715 | /* No bytecode range check for stitched traces. */ | ||
2716 | pc++; | ||
2717 | break; | ||
2159 | default: | 2718 | default: |
2160 | lua_assert(0); | 2719 | lj_assertJ(0, "bad root trace start bytecode %d", bc_op(ins)); |
2161 | break; | 2720 | break; |
2162 | } | 2721 | } |
2163 | return pc; | 2722 | return pc; |
@@ -2171,11 +2730,14 @@ void lj_record_setup(jit_State *J) | |||
2171 | /* Initialize state related to current trace. */ | 2730 | /* Initialize state related to current trace. */ |
2172 | memset(J->slot, 0, sizeof(J->slot)); | 2731 | memset(J->slot, 0, sizeof(J->slot)); |
2173 | memset(J->chain, 0, sizeof(J->chain)); | 2732 | memset(J->chain, 0, sizeof(J->chain)); |
2733 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | ||
2734 | memset(J->rbchash, 0, sizeof(J->rbchash)); | ||
2735 | #endif | ||
2174 | memset(J->bpropcache, 0, sizeof(J->bpropcache)); | 2736 | memset(J->bpropcache, 0, sizeof(J->bpropcache)); |
2175 | J->scev.idx = REF_NIL; | 2737 | J->scev.idx = REF_NIL; |
2176 | setmref(J->scev.pc, NULL); | 2738 | setmref(J->scev.pc, NULL); |
2177 | 2739 | ||
2178 | J->baseslot = 1; /* Invoking function is at base[-1]. */ | 2740 | J->baseslot = 1+LJ_FR2; /* Invoking function is at base[-1-LJ_FR2]. */ |
2179 | J->base = J->slot + J->baseslot; | 2741 | J->base = J->slot + J->baseslot; |
2180 | J->maxslot = 0; | 2742 | J->maxslot = 0; |
2181 | J->framedepth = 0; | 2743 | J->framedepth = 0; |
@@ -2190,7 +2752,7 @@ void lj_record_setup(jit_State *J) | |||
2190 | J->bc_extent = ~(MSize)0; | 2752 | J->bc_extent = ~(MSize)0; |
2191 | 2753 | ||
2192 | /* Emit instructions for fixed references. Also triggers initial IR alloc. */ | 2754 | /* Emit instructions for fixed references. Also triggers initial IR alloc. */ |
2193 | emitir_raw(IRT(IR_BASE, IRT_P32), J->parent, J->exitno); | 2755 | emitir_raw(IRT(IR_BASE, IRT_PGC), J->parent, J->exitno); |
2194 | for (i = 0; i <= 2; i++) { | 2756 | for (i = 0; i <= 2; i++) { |
2195 | IRIns *ir = IR(REF_NIL-i); | 2757 | IRIns *ir = IR(REF_NIL-i); |
2196 | ir->i = 0; | 2758 | ir->i = 0; |
@@ -2221,10 +2783,15 @@ void lj_record_setup(jit_State *J) | |||
2221 | } | 2783 | } |
2222 | lj_snap_replay(J, T); | 2784 | lj_snap_replay(J, T); |
2223 | sidecheck: | 2785 | sidecheck: |
2224 | if (traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] || | 2786 | if ((traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] || |
2225 | T->snap[J->exitno].count >= J->param[JIT_P_hotexit] + | 2787 | T->snap[J->exitno].count >= J->param[JIT_P_hotexit] + |
2226 | J->param[JIT_P_tryside]) { | 2788 | J->param[JIT_P_tryside])) { |
2227 | rec_stop(J, LJ_TRLINK_INTERP, 0); | 2789 | if (bc_op(*J->pc) == BC_JLOOP) { |
2790 | BCIns startins = traceref(J, bc_d(*J->pc))->startins; | ||
2791 | if (bc_op(startins) == BC_ITERN) | ||
2792 | rec_itern(J, bc_a(startins), bc_b(startins)); | ||
2793 | } | ||
2794 | lj_record_stop(J, LJ_TRLINK_INTERP, 0); | ||
2228 | } | 2795 | } |
2229 | } else { /* Root trace. */ | 2796 | } else { /* Root trace. */ |
2230 | J->cur.root = 0; | 2797 | J->cur.root = 0; |
@@ -2232,13 +2799,20 @@ void lj_record_setup(jit_State *J) | |||
2232 | J->pc = rec_setup_root(J); | 2799 | J->pc = rec_setup_root(J); |
2233 | /* Note: the loop instruction itself is recorded at the end and not | 2800 | /* Note: the loop instruction itself is recorded at the end and not |
2234 | ** at the start! So snapshot #0 needs to point to the *next* instruction. | 2801 | ** at the start! So snapshot #0 needs to point to the *next* instruction. |
2802 | ** The one exception is BC_ITERN, which sets LJ_TRACE_RECORD_1ST. | ||
2235 | */ | 2803 | */ |
2236 | lj_snap_add(J); | 2804 | lj_snap_add(J); |
2237 | if (bc_op(J->cur.startins) == BC_FORL) | 2805 | if (bc_op(J->cur.startins) == BC_FORL) |
2238 | rec_for_loop(J, J->pc-1, &J->scev, 1); | 2806 | rec_for_loop(J, J->pc-1, &J->scev, 1); |
2807 | else if (bc_op(J->cur.startins) == BC_ITERC) | ||
2808 | J->startpc = NULL; | ||
2239 | if (1 + J->pt->framesize >= LJ_MAX_JSLOTS) | 2809 | if (1 + J->pt->framesize >= LJ_MAX_JSLOTS) |
2240 | lj_trace_err(J, LJ_TRERR_STACKOV); | 2810 | lj_trace_err(J, LJ_TRERR_STACKOV); |
2241 | } | 2811 | } |
2812 | #if LJ_HASPROFILE | ||
2813 | J->prev_pt = NULL; | ||
2814 | J->prev_line = -1; | ||
2815 | #endif | ||
2242 | #ifdef LUAJIT_ENABLE_CHECKHOOK | 2816 | #ifdef LUAJIT_ENABLE_CHECKHOOK |
2243 | /* Regularly check for instruction/line hooks from compiled code and | 2817 | /* Regularly check for instruction/line hooks from compiled code and |
2244 | ** exit to the interpreter if the hooks are set. | 2818 | ** exit to the interpreter if the hooks are set. |