aboutsummaryrefslogtreecommitdiff
path: root/src/lj_snap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_snap.c')
-rw-r--r--src/lj_snap.c271
1 files changed, 182 insertions, 89 deletions
diff --git a/src/lj_snap.c b/src/lj_snap.c
index 7a02c9a9..bcc9da38 100644
--- a/src/lj_snap.c
+++ b/src/lj_snap.c
@@ -68,20 +68,37 @@ static MSize snapshot_slots(jit_State *J, SnapEntry *map, BCReg nslots)
68 for (s = 0; s < nslots; s++) { 68 for (s = 0; s < nslots; s++) {
69 TRef tr = J->slot[s]; 69 TRef tr = J->slot[s];
70 IRRef ref = tref_ref(tr); 70 IRRef ref = tref_ref(tr);
71#if LJ_FR2
72 if (s == 1) { /* Ignore slot 1 in LJ_FR2 mode, except if tailcalled. */
73 if ((tr & TREF_FRAME))
74 map[n++] = SNAP(1, SNAP_FRAME | SNAP_NORESTORE, REF_NIL);
75 continue;
76 }
77 if ((tr & (TREF_FRAME | TREF_CONT)) && !ref) {
78 cTValue *base = J->L->base - J->baseslot;
79 tr = J->slot[s] = (tr & 0xff0000) | lj_ir_k64(J, IR_KNUM, base[s].u64);
80 ref = tref_ref(tr);
81 }
82#endif
71 if (ref) { 83 if (ref) {
72 SnapEntry sn = SNAP_TR(s, tr); 84 SnapEntry sn = SNAP_TR(s, tr);
73 IRIns *ir = &J->cur.ir[ref]; 85 IRIns *ir = &J->cur.ir[ref];
74 if (!(sn & (SNAP_CONT|SNAP_FRAME)) && 86 if ((LJ_FR2 || !(sn & (SNAP_CONT|SNAP_FRAME))) &&
75 ir->o == IR_SLOAD && ir->op1 == s && ref > retf) { 87 ir->o == IR_SLOAD && ir->op1 == s && ref > retf) {
76 /* No need to snapshot unmodified non-inherited slots. */ 88 /*
77 if (!(ir->op2 & IRSLOAD_INHERIT)) 89 ** No need to snapshot unmodified non-inherited slots.
90 ** But always snapshot the function below a frame in LJ_FR2 mode.
91 */
92 if (!(ir->op2 & IRSLOAD_INHERIT) &&
93 (!LJ_FR2 || s == 0 || s+1 == nslots ||
94 !(J->slot[s+1] & (TREF_CONT|TREF_FRAME))))
78 continue; 95 continue;
79 /* No need to restore readonly slots and unmodified non-parent slots. */ 96 /* No need to restore readonly slots and unmodified non-parent slots. */
80 if (!(LJ_DUALNUM && (ir->op2 & IRSLOAD_CONVERT)) && 97 if (!(LJ_DUALNUM && (ir->op2 & IRSLOAD_CONVERT)) &&
81 (ir->op2 & (IRSLOAD_READONLY|IRSLOAD_PARENT)) != IRSLOAD_PARENT) 98 (ir->op2 & (IRSLOAD_READONLY|IRSLOAD_PARENT)) != IRSLOAD_PARENT)
82 sn |= SNAP_NORESTORE; 99 sn |= SNAP_NORESTORE;
83 } 100 }
84 if (LJ_SOFTFP && irt_isnum(ir->t)) 101 if (LJ_SOFTFP32 && irt_isnum(ir->t))
85 sn |= SNAP_SOFTFPNUM; 102 sn |= SNAP_SOFTFPNUM;
86 map[n++] = sn; 103 map[n++] = sn;
87 } 104 }
@@ -90,35 +107,54 @@ static MSize snapshot_slots(jit_State *J, SnapEntry *map, BCReg nslots)
90} 107}
91 108
92/* Add frame links at the end of the snapshot. */ 109/* Add frame links at the end of the snapshot. */
93static BCReg snapshot_framelinks(jit_State *J, SnapEntry *map) 110static MSize snapshot_framelinks(jit_State *J, SnapEntry *map, uint8_t *topslot)
94{ 111{
95 cTValue *frame = J->L->base - 1; 112 cTValue *frame = J->L->base - 1;
96 cTValue *lim = J->L->base - J->baseslot; 113 cTValue *lim = J->L->base - J->baseslot + LJ_FR2;
97 cTValue *ftop = frame + funcproto(frame_func(frame))->framesize; 114 GCfunc *fn = frame_func(frame);
115 cTValue *ftop = isluafunc(fn) ? (frame+funcproto(fn)->framesize) : J->L->top;
116#if LJ_FR2
117 uint64_t pcbase = (u64ptr(J->pc) << 8) | (J->baseslot - 2);
118 lj_assertJ(2 <= J->baseslot && J->baseslot <= 257, "bad baseslot");
119 memcpy(map, &pcbase, sizeof(uint64_t));
120#else
98 MSize f = 0; 121 MSize f = 0;
99 map[f++] = SNAP_MKPC(J->pc); /* The current PC is always the first entry. */ 122 map[f++] = SNAP_MKPC(J->pc); /* The current PC is always the first entry. */
100 lua_assert(!J->pt || 123#endif
124 lj_assertJ(!J->pt ||
101 (J->pc >= proto_bc(J->pt) && 125 (J->pc >= proto_bc(J->pt) &&
102 J->pc < proto_bc(J->pt) + J->pt->sizebc)); 126 J->pc < proto_bc(J->pt) + J->pt->sizebc), "bad snapshot PC");
103 while (frame > lim) { /* Backwards traversal of all frames above base. */ 127 while (frame > lim) { /* Backwards traversal of all frames above base. */
104 if (frame_islua(frame)) { 128 if (frame_islua(frame)) {
129#if !LJ_FR2
105 map[f++] = SNAP_MKPC(frame_pc(frame)); 130 map[f++] = SNAP_MKPC(frame_pc(frame));
131#endif
106 frame = frame_prevl(frame); 132 frame = frame_prevl(frame);
107 } else if (frame_iscont(frame)) { 133 } else if (frame_iscont(frame)) {
134#if !LJ_FR2
108 map[f++] = SNAP_MKFTSZ(frame_ftsz(frame)); 135 map[f++] = SNAP_MKFTSZ(frame_ftsz(frame));
109 map[f++] = SNAP_MKPC(frame_contpc(frame)); 136 map[f++] = SNAP_MKPC(frame_contpc(frame));
137#endif
110 frame = frame_prevd(frame); 138 frame = frame_prevd(frame);
111 } else { 139 } else {
112 lua_assert(!frame_isc(frame)); 140 lj_assertJ(!frame_isc(frame), "broken frame chain");
141#if !LJ_FR2
113 map[f++] = SNAP_MKFTSZ(frame_ftsz(frame)); 142 map[f++] = SNAP_MKFTSZ(frame_ftsz(frame));
143#endif
114 frame = frame_prevd(frame); 144 frame = frame_prevd(frame);
115 continue; 145 continue;
116 } 146 }
117 if (frame + funcproto(frame_func(frame))->framesize > ftop) 147 if (frame + funcproto(frame_func(frame))->framesize > ftop)
118 ftop = frame + funcproto(frame_func(frame))->framesize; 148 ftop = frame + funcproto(frame_func(frame))->framesize;
119 } 149 }
120 lua_assert(f == (MSize)(1 + J->framedepth)); 150 *topslot = (uint8_t)(ftop - lim);
121 return (BCReg)(ftop - lim); 151#if LJ_FR2
152 lj_assertJ(sizeof(SnapEntry) * 2 == sizeof(uint64_t), "bad SnapEntry def");
153 return 2;
154#else
155 lj_assertJ(f == (MSize)(1 + J->framedepth), "miscalculated snapshot size");
156 return f;
157#endif
122} 158}
123 159
124/* Take a snapshot of the current stack. */ 160/* Take a snapshot of the current stack. */
@@ -128,16 +164,17 @@ static void snapshot_stack(jit_State *J, SnapShot *snap, MSize nsnapmap)
128 MSize nent; 164 MSize nent;
129 SnapEntry *p; 165 SnapEntry *p;
130 /* Conservative estimate. */ 166 /* Conservative estimate. */
131 lj_snap_grow_map(J, nsnapmap + nslots + (MSize)J->framedepth+1); 167 lj_snap_grow_map(J, nsnapmap + nslots + (MSize)(LJ_FR2?2:J->framedepth+1));
132 p = &J->cur.snapmap[nsnapmap]; 168 p = &J->cur.snapmap[nsnapmap];
133 nent = snapshot_slots(J, p, nslots); 169 nent = snapshot_slots(J, p, nslots);
134 snap->topslot = (uint8_t)snapshot_framelinks(J, p + nent); 170 snap->nent = (uint8_t)nent;
171 nent += snapshot_framelinks(J, p + nent, &snap->topslot);
135 snap->mapofs = (uint32_t)nsnapmap; 172 snap->mapofs = (uint32_t)nsnapmap;
136 snap->ref = (IRRef1)J->cur.nins; 173 snap->ref = (IRRef1)J->cur.nins;
137 snap->nent = (uint8_t)nent; 174 snap->mcofs = 0;
138 snap->nslots = (uint8_t)nslots; 175 snap->nslots = (uint8_t)nslots;
139 snap->count = 0; 176 snap->count = 0;
140 J->cur.nsnapmap = (uint32_t)(nsnapmap + nent + 1 + J->framedepth); 177 J->cur.nsnapmap = (uint32_t)(nsnapmap + nent);
141} 178}
142 179
143/* Add or merge a snapshot. */ 180/* Add or merge a snapshot. */
@@ -146,8 +183,8 @@ void lj_snap_add(jit_State *J)
146 MSize nsnap = J->cur.nsnap; 183 MSize nsnap = J->cur.nsnap;
147 MSize nsnapmap = J->cur.nsnapmap; 184 MSize nsnapmap = J->cur.nsnapmap;
148 /* Merge if no ins. inbetween or if requested and no guard inbetween. */ 185 /* Merge if no ins. inbetween or if requested and no guard inbetween. */
149 if (J->mergesnap ? !irt_isguard(J->guardemit) : 186 if ((nsnap > 0 && J->cur.snap[nsnap-1].ref == J->cur.nins) ||
150 (nsnap > 0 && J->cur.snap[nsnap-1].ref == J->cur.nins)) { 187 (J->mergesnap && !irt_isguard(J->guardemit))) {
151 if (nsnap == 1) { /* But preserve snap #0 PC. */ 188 if (nsnap == 1) { /* But preserve snap #0 PC. */
152 emitir_raw(IRT(IR_NOP, IRT_NIL), 0, 0); 189 emitir_raw(IRT(IR_NOP, IRT_NIL), 0, 0);
153 goto nomerge; 190 goto nomerge;
@@ -194,7 +231,8 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf,
194#define DEF_SLOT(s) udf[(s)] *= 3 231#define DEF_SLOT(s) udf[(s)] *= 3
195 232
196 /* Scan through following bytecode and check for uses/defs. */ 233 /* Scan through following bytecode and check for uses/defs. */
197 lua_assert(pc >= proto_bc(J->pt) && pc < proto_bc(J->pt) + J->pt->sizebc); 234 lj_assertJ(pc >= proto_bc(J->pt) && pc < proto_bc(J->pt) + J->pt->sizebc,
235 "snapshot PC out of range");
198 for (;;) { 236 for (;;) {
199 BCIns ins = *pc++; 237 BCIns ins = *pc++;
200 BCOp op = bc_op(ins); 238 BCOp op = bc_op(ins);
@@ -205,7 +243,7 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf,
205 switch (bcmode_c(op)) { 243 switch (bcmode_c(op)) {
206 case BCMvar: USE_SLOT(bc_c(ins)); break; 244 case BCMvar: USE_SLOT(bc_c(ins)); break;
207 case BCMrbase: 245 case BCMrbase:
208 lua_assert(op == BC_CAT); 246 lj_assertJ(op == BC_CAT, "unhandled op %d with RC rbase", op);
209 for (s = bc_b(ins); s <= bc_c(ins); s++) USE_SLOT(s); 247 for (s = bc_b(ins); s <= bc_c(ins); s++) USE_SLOT(s);
210 for (; s < maxslot; s++) DEF_SLOT(s); 248 for (; s < maxslot; s++) DEF_SLOT(s);
211 break; 249 break;
@@ -245,7 +283,8 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf,
245 case BCMbase: 283 case BCMbase:
246 if (op >= BC_CALLM && op <= BC_ITERN) { 284 if (op >= BC_CALLM && op <= BC_ITERN) {
247 BCReg top = (op == BC_CALLM || op == BC_CALLMT || bc_c(ins) == 0) ? 285 BCReg top = (op == BC_CALLM || op == BC_CALLMT || bc_c(ins) == 0) ?
248 maxslot : (bc_a(ins) + bc_c(ins)); 286 maxslot : (bc_a(ins) + bc_c(ins)+LJ_FR2);
287 if (LJ_FR2) DEF_SLOT(bc_a(ins)+1);
249 s = bc_a(ins) - ((op == BC_ITERC || op == BC_ITERN) ? 3 : 0); 288 s = bc_a(ins) - ((op == BC_ITERC || op == BC_ITERN) ? 3 : 0);
250 for (; s < top; s++) USE_SLOT(s); 289 for (; s < top; s++) USE_SLOT(s);
251 for (; s < maxslot; s++) DEF_SLOT(s); 290 for (; s < maxslot; s++) DEF_SLOT(s);
@@ -263,7 +302,8 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf,
263 break; 302 break;
264 default: break; 303 default: break;
265 } 304 }
266 lua_assert(pc >= proto_bc(J->pt) && pc < proto_bc(J->pt) + J->pt->sizebc); 305 lj_assertJ(pc >= proto_bc(J->pt) && pc < proto_bc(J->pt) + J->pt->sizebc,
306 "use/def analysis PC out of range");
267 } 307 }
268 308
269#undef USE_SLOT 309#undef USE_SLOT
@@ -321,8 +361,8 @@ void lj_snap_shrink(jit_State *J)
321 MSize n, m, nlim, nent = snap->nent; 361 MSize n, m, nlim, nent = snap->nent;
322 uint8_t udf[SNAP_USEDEF_SLOTS]; 362 uint8_t udf[SNAP_USEDEF_SLOTS];
323 BCReg maxslot = J->maxslot; 363 BCReg maxslot = J->maxslot;
324 BCReg minslot = snap_usedef(J, udf, snap_pc(map[nent]), maxslot);
325 BCReg baseslot = J->baseslot; 364 BCReg baseslot = J->baseslot;
365 BCReg minslot = snap_usedef(J, udf, snap_pc(&map[nent]), maxslot);
326 if (minslot < maxslot) snap_useuv(J->pt, udf); 366 if (minslot < maxslot) snap_useuv(J->pt, udf);
327 maxslot += baseslot; 367 maxslot += baseslot;
328 minslot += baseslot; 368 minslot += baseslot;
@@ -365,25 +405,26 @@ static RegSP snap_renameref(GCtrace *T, SnapNo lim, IRRef ref, RegSP rs)
365} 405}
366 406
367/* Copy RegSP from parent snapshot to the parent links of the IR. */ 407/* Copy RegSP from parent snapshot to the parent links of the IR. */
368IRIns *lj_snap_regspmap(GCtrace *T, SnapNo snapno, IRIns *ir) 408IRIns *lj_snap_regspmap(jit_State *J, GCtrace *T, SnapNo snapno, IRIns *ir)
369{ 409{
370 SnapShot *snap = &T->snap[snapno]; 410 SnapShot *snap = &T->snap[snapno];
371 SnapEntry *map = &T->snapmap[snap->mapofs]; 411 SnapEntry *map = &T->snapmap[snap->mapofs];
372 BloomFilter rfilt = snap_renamefilter(T, snapno); 412 BloomFilter rfilt = snap_renamefilter(T, snapno);
373 MSize n = 0; 413 MSize n = 0;
374 IRRef ref = 0; 414 IRRef ref = 0;
415 UNUSED(J);
375 for ( ; ; ir++) { 416 for ( ; ; ir++) {
376 uint32_t rs; 417 uint32_t rs;
377 if (ir->o == IR_SLOAD) { 418 if (ir->o == IR_SLOAD) {
378 if (!(ir->op2 & IRSLOAD_PARENT)) break; 419 if (!(ir->op2 & IRSLOAD_PARENT)) break;
379 for ( ; ; n++) { 420 for ( ; ; n++) {
380 lua_assert(n < snap->nent); 421 lj_assertJ(n < snap->nent, "slot %d not found in snapshot", ir->op1);
381 if (snap_slot(map[n]) == ir->op1) { 422 if (snap_slot(map[n]) == ir->op1) {
382 ref = snap_ref(map[n++]); 423 ref = snap_ref(map[n++]);
383 break; 424 break;
384 } 425 }
385 } 426 }
386 } else if (LJ_SOFTFP && ir->o == IR_HIOP) { 427 } else if (LJ_SOFTFP32 && ir->o == IR_HIOP) {
387 ref++; 428 ref++;
388 } else if (ir->o == IR_PVAL) { 429 } else if (ir->o == IR_PVAL) {
389 ref = ir->op1 + REF_BIAS; 430 ref = ir->op1 + REF_BIAS;
@@ -394,7 +435,7 @@ IRIns *lj_snap_regspmap(GCtrace *T, SnapNo snapno, IRIns *ir)
394 if (bloomtest(rfilt, ref)) 435 if (bloomtest(rfilt, ref))
395 rs = snap_renameref(T, snapno, ref, rs); 436 rs = snap_renameref(T, snapno, ref, rs);
396 ir->prev = (uint16_t)rs; 437 ir->prev = (uint16_t)rs;
397 lua_assert(regsp_used(rs)); 438 lj_assertJ(regsp_used(rs), "unused IR %04d in snapshot", ref - REF_BIAS);
398 } 439 }
399 return ir; 440 return ir;
400} 441}
@@ -409,10 +450,10 @@ static TRef snap_replay_const(jit_State *J, IRIns *ir)
409 case IR_KPRI: return TREF_PRI(irt_type(ir->t)); 450 case IR_KPRI: return TREF_PRI(irt_type(ir->t));
410 case IR_KINT: return lj_ir_kint(J, ir->i); 451 case IR_KINT: return lj_ir_kint(J, ir->i);
411 case IR_KGC: return lj_ir_kgc(J, ir_kgc(ir), irt_t(ir->t)); 452 case IR_KGC: return lj_ir_kgc(J, ir_kgc(ir), irt_t(ir->t));
412 case IR_KNUM: return lj_ir_k64(J, IR_KNUM, ir_knum(ir)); 453 case IR_KNUM: case IR_KINT64:
413 case IR_KINT64: return lj_ir_k64(J, IR_KINT64, ir_kint64(ir)); 454 return lj_ir_k64(J, (IROp)ir->o, ir_k64(ir)->u64);
414 case IR_KPTR: return lj_ir_kptr(J, ir_kptr(ir)); /* Continuation. */ 455 case IR_KPTR: return lj_ir_kptr(J, ir_kptr(ir)); /* Continuation. */
415 default: lua_assert(0); return TREF_NIL; break; 456 default: lj_assertJ(0, "bad IR constant op %d", ir->o); return TREF_NIL;
416 } 457 }
417} 458}
418 459
@@ -422,7 +463,7 @@ static TRef snap_dedup(jit_State *J, SnapEntry *map, MSize nmax, IRRef ref)
422 MSize j; 463 MSize j;
423 for (j = 0; j < nmax; j++) 464 for (j = 0; j < nmax; j++)
424 if (snap_ref(map[j]) == ref) 465 if (snap_ref(map[j]) == ref)
425 return J->slot[snap_slot(map[j])] & ~(SNAP_CONT|SNAP_FRAME); 466 return J->slot[snap_slot(map[j])] & ~(SNAP_KEYINDEX|SNAP_CONT|SNAP_FRAME);
426 return 0; 467 return 0;
427} 468}
428 469
@@ -483,21 +524,27 @@ void lj_snap_replay(jit_State *J, GCtrace *T)
483 goto setslot; 524 goto setslot;
484 bloomset(seen, ref); 525 bloomset(seen, ref);
485 if (irref_isk(ref)) { 526 if (irref_isk(ref)) {
486 tr = snap_replay_const(J, ir); 527 /* See special treatment of LJ_FR2 slot 1 in snapshot_slots() above. */
528 if (LJ_FR2 && (sn == SNAP(1, SNAP_FRAME | SNAP_NORESTORE, REF_NIL)))
529 tr = 0;
530 else
531 tr = snap_replay_const(J, ir);
487 } else if (!regsp_used(ir->prev)) { 532 } else if (!regsp_used(ir->prev)) {
488 pass23 = 1; 533 pass23 = 1;
489 lua_assert(s != 0); 534 lj_assertJ(s != 0, "unused slot 0 in snapshot");
490 tr = s; 535 tr = s;
491 } else { 536 } else {
492 IRType t = irt_type(ir->t); 537 IRType t = irt_type(ir->t);
493 uint32_t mode = IRSLOAD_INHERIT|IRSLOAD_PARENT; 538 uint32_t mode = IRSLOAD_INHERIT|IRSLOAD_PARENT;
494 if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) t = IRT_NUM; 539 if (LJ_SOFTFP32 && (sn & SNAP_SOFTFPNUM)) t = IRT_NUM;
495 if (ir->o == IR_SLOAD) mode |= (ir->op2 & IRSLOAD_READONLY); 540 if (ir->o == IR_SLOAD) mode |= (ir->op2 & IRSLOAD_READONLY);
541 if ((sn & SNAP_KEYINDEX)) mode |= IRSLOAD_KEYINDEX;
496 tr = emitir_raw(IRT(IR_SLOAD, t), s, mode); 542 tr = emitir_raw(IRT(IR_SLOAD, t), s, mode);
497 } 543 }
498 setslot: 544 setslot:
499 J->slot[s] = tr | (sn&(SNAP_CONT|SNAP_FRAME)); /* Same as TREF_* flags. */ 545 /* Same as TREF_* flags. */
500 J->framedepth += ((sn & (SNAP_CONT|SNAP_FRAME)) && s); 546 J->slot[s] = tr | (sn&(SNAP_KEYINDEX|SNAP_CONT|SNAP_FRAME));
547 J->framedepth += ((sn & (SNAP_CONT|SNAP_FRAME)) && (s != LJ_FR2));
501 if ((sn & SNAP_FRAME)) 548 if ((sn & SNAP_FRAME))
502 J->baseslot = s+1; 549 J->baseslot = s+1;
503 } 550 }
@@ -512,8 +559,9 @@ void lj_snap_replay(jit_State *J, GCtrace *T)
512 if (regsp_reg(ir->r) == RID_SUNK) { 559 if (regsp_reg(ir->r) == RID_SUNK) {
513 if (J->slot[snap_slot(sn)] != snap_slot(sn)) continue; 560 if (J->slot[snap_slot(sn)] != snap_slot(sn)) continue;
514 pass23 = 1; 561 pass23 = 1;
515 lua_assert(ir->o == IR_TNEW || ir->o == IR_TDUP || 562 lj_assertJ(ir->o == IR_TNEW || ir->o == IR_TDUP ||
516 ir->o == IR_CNEW || ir->o == IR_CNEWI); 563 ir->o == IR_CNEW || ir->o == IR_CNEWI,
564 "sunk parent IR %04d has bad op %d", refp - REF_BIAS, ir->o);
517 if (ir->op1 >= T->nk) snap_pref(J, T, map, nent, seen, ir->op1); 565 if (ir->op1 >= T->nk) snap_pref(J, T, map, nent, seen, ir->op1);
518 if (ir->op2 >= T->nk) snap_pref(J, T, map, nent, seen, ir->op2); 566 if (ir->op2 >= T->nk) snap_pref(J, T, map, nent, seen, ir->op2);
519 if (LJ_HASFFI && ir->o == IR_CNEWI) { 567 if (LJ_HASFFI && ir->o == IR_CNEWI) {
@@ -525,13 +573,14 @@ void lj_snap_replay(jit_State *J, GCtrace *T)
525 if (irs->r == RID_SINK && snap_sunk_store(T, ir, irs)) { 573 if (irs->r == RID_SINK && snap_sunk_store(T, ir, irs)) {
526 if (snap_pref(J, T, map, nent, seen, irs->op2) == 0) 574 if (snap_pref(J, T, map, nent, seen, irs->op2) == 0)
527 snap_pref(J, T, map, nent, seen, T->ir[irs->op2].op1); 575 snap_pref(J, T, map, nent, seen, T->ir[irs->op2].op1);
528 else if ((LJ_SOFTFP || (LJ_32 && LJ_HASFFI)) && 576 else if ((LJ_SOFTFP32 || (LJ_32 && LJ_HASFFI)) &&
529 irs+1 < irlast && (irs+1)->o == IR_HIOP) 577 irs+1 < irlast && (irs+1)->o == IR_HIOP)
530 snap_pref(J, T, map, nent, seen, (irs+1)->op2); 578 snap_pref(J, T, map, nent, seen, (irs+1)->op2);
531 } 579 }
532 } 580 }
533 } else if (!irref_isk(refp) && !regsp_used(ir->prev)) { 581 } else if (!irref_isk(refp) && !regsp_used(ir->prev)) {
534 lua_assert(ir->o == IR_CONV && ir->op2 == IRCONV_NUM_INT); 582 lj_assertJ(ir->o == IR_CONV && ir->op2 == IRCONV_NUM_INT,
583 "sunk parent IR %04d has bad op %d", refp - REF_BIAS, ir->o);
535 J->slot[snap_slot(sn)] = snap_pref(J, T, map, nent, seen, ir->op1); 584 J->slot[snap_slot(sn)] = snap_pref(J, T, map, nent, seen, ir->op1);
536 } 585 }
537 } 586 }
@@ -581,20 +630,21 @@ void lj_snap_replay(jit_State *J, GCtrace *T)
581 val = snap_pref(J, T, map, nent, seen, irs->op2); 630 val = snap_pref(J, T, map, nent, seen, irs->op2);
582 if (val == 0) { 631 if (val == 0) {
583 IRIns *irc = &T->ir[irs->op2]; 632 IRIns *irc = &T->ir[irs->op2];
584 lua_assert(irc->o == IR_CONV && irc->op2 == IRCONV_NUM_INT); 633 lj_assertJ(irc->o == IR_CONV && irc->op2 == IRCONV_NUM_INT,
634 "sunk store for parent IR %04d with bad op %d",
635 refp - REF_BIAS, irc->o);
585 val = snap_pref(J, T, map, nent, seen, irc->op1); 636 val = snap_pref(J, T, map, nent, seen, irc->op1);
586 val = emitir(IRTN(IR_CONV), val, IRCONV_NUM_INT); 637 val = emitir(IRTN(IR_CONV), val, IRCONV_NUM_INT);
587 } else if ((LJ_SOFTFP || (LJ_32 && LJ_HASFFI)) && 638 } else if ((LJ_SOFTFP32 || (LJ_32 && LJ_HASFFI)) &&
588 irs+1 < irlast && (irs+1)->o == IR_HIOP) { 639 irs+1 < irlast && (irs+1)->o == IR_HIOP) {
589 IRType t = IRT_I64; 640 IRType t = IRT_I64;
590 if (LJ_SOFTFP && irt_type((irs+1)->t) == IRT_SOFTFP) 641 if (LJ_SOFTFP32 && irt_type((irs+1)->t) == IRT_SOFTFP)
591 t = IRT_NUM; 642 t = IRT_NUM;
592 lj_needsplit(J); 643 lj_needsplit(J);
593 if (irref_isk(irs->op2) && irref_isk((irs+1)->op2)) { 644 if (irref_isk(irs->op2) && irref_isk((irs+1)->op2)) {
594 uint64_t k = (uint32_t)T->ir[irs->op2].i + 645 uint64_t k = (uint32_t)T->ir[irs->op2].i +
595 ((uint64_t)T->ir[(irs+1)->op2].i << 32); 646 ((uint64_t)T->ir[(irs+1)->op2].i << 32);
596 val = lj_ir_k64(J, t == IRT_I64 ? IR_KINT64 : IR_KNUM, 647 val = lj_ir_k64(J, t == IRT_I64 ? IR_KINT64 : IR_KNUM, k);
597 lj_ir_k64_find(J, k));
598 } else { 648 } else {
599 val = emitir_raw(IRT(IR_HIOP, t), val, 649 val = emitir_raw(IRT(IR_HIOP, t), val,
600 snap_pref(J, T, map, nent, seen, (irs+1)->op2)); 650 snap_pref(J, T, map, nent, seen, (irs+1)->op2));
@@ -632,7 +682,14 @@ static void snap_restoreval(jit_State *J, GCtrace *T, ExitState *ex,
632 IRType1 t = ir->t; 682 IRType1 t = ir->t;
633 RegSP rs = ir->prev; 683 RegSP rs = ir->prev;
634 if (irref_isk(ref)) { /* Restore constant slot. */ 684 if (irref_isk(ref)) { /* Restore constant slot. */
635 lj_ir_kvalue(J->L, o, ir); 685 if (ir->o == IR_KPTR) {
686 o->u64 = (uint64_t)(uintptr_t)ir_kptr(ir);
687 } else {
688 lj_assertJ(!(ir->o == IR_KKPTR || ir->o == IR_KNULL),
689 "restore of const from IR %04d with bad op %d",
690 ref - REF_BIAS, ir->o);
691 lj_ir_kvalue(J->L, o, ir);
692 }
636 return; 693 return;
637 } 694 }
638 if (LJ_UNLIKELY(bloomtest(rfilt, ref))) 695 if (LJ_UNLIKELY(bloomtest(rfilt, ref)))
@@ -641,22 +698,24 @@ static void snap_restoreval(jit_State *J, GCtrace *T, ExitState *ex,
641 int32_t *sps = &ex->spill[regsp_spill(rs)]; 698 int32_t *sps = &ex->spill[regsp_spill(rs)];
642 if (irt_isinteger(t)) { 699 if (irt_isinteger(t)) {
643 setintV(o, *sps); 700 setintV(o, *sps);
644#if !LJ_SOFTFP 701#if !LJ_SOFTFP32
645 } else if (irt_isnum(t)) { 702 } else if (irt_isnum(t)) {
646 o->u64 = *(uint64_t *)sps; 703 o->u64 = *(uint64_t *)sps;
647#endif 704#endif
648 } else if (LJ_64 && irt_islightud(t)) { 705#if LJ_64 && !LJ_GC64
706 } else if (irt_islightud(t)) {
649 /* 64 bit lightuserdata which may escape already has the tag bits. */ 707 /* 64 bit lightuserdata which may escape already has the tag bits. */
650 o->u64 = *(uint64_t *)sps; 708 o->u64 = *(uint64_t *)sps;
709#endif
651 } else { 710 } else {
652 lua_assert(!irt_ispri(t)); /* PRI refs never have a spill slot. */ 711 lj_assertJ(!irt_ispri(t), "PRI ref with spill slot");
653 setgcrefi(o->gcr, *sps); 712 setgcV(J->L, o, (GCobj *)(uintptr_t)*(GCSize *)sps, irt_toitype(t));
654 setitype(o, irt_toitype(t));
655 } 713 }
656 } else { /* Restore from register. */ 714 } else { /* Restore from register. */
657 Reg r = regsp_reg(rs); 715 Reg r = regsp_reg(rs);
658 if (ra_noreg(r)) { 716 if (ra_noreg(r)) {
659 lua_assert(ir->o == IR_CONV && ir->op2 == IRCONV_NUM_INT); 717 lj_assertJ(ir->o == IR_CONV && ir->op2 == IRCONV_NUM_INT,
718 "restore from IR %04d has no reg", ref - REF_BIAS);
660 snap_restoreval(J, T, ex, snapno, rfilt, ir->op1, o); 719 snap_restoreval(J, T, ex, snapno, rfilt, ir->op1, o);
661 if (LJ_DUALNUM) setnumV(o, (lua_Number)intV(o)); 720 if (LJ_DUALNUM) setnumV(o, (lua_Number)intV(o));
662 return; 721 return;
@@ -665,21 +724,26 @@ static void snap_restoreval(jit_State *J, GCtrace *T, ExitState *ex,
665#if !LJ_SOFTFP 724#if !LJ_SOFTFP
666 } else if (irt_isnum(t)) { 725 } else if (irt_isnum(t)) {
667 setnumV(o, ex->fpr[r-RID_MIN_FPR]); 726 setnumV(o, ex->fpr[r-RID_MIN_FPR]);
727#elif LJ_64 /* && LJ_SOFTFP */
728 } else if (irt_isnum(t)) {
729 o->u64 = ex->gpr[r-RID_MIN_GPR];
668#endif 730#endif
669 } else if (LJ_64 && irt_islightud(t)) { 731#if LJ_64 && !LJ_GC64
670 /* 64 bit lightuserdata which may escape already has the tag bits. */ 732 } else if (irt_is64(t)) {
733 /* 64 bit values that already have the tag bits. */
671 o->u64 = ex->gpr[r-RID_MIN_GPR]; 734 o->u64 = ex->gpr[r-RID_MIN_GPR];
735#endif
736 } else if (irt_ispri(t)) {
737 setpriV(o, irt_toitype(t));
672 } else { 738 } else {
673 if (!irt_ispri(t)) 739 setgcV(J->L, o, (GCobj *)ex->gpr[r-RID_MIN_GPR], irt_toitype(t));
674 setgcrefi(o->gcr, ex->gpr[r-RID_MIN_GPR]);
675 setitype(o, irt_toitype(t));
676 } 740 }
677 } 741 }
678} 742}
679 743
680#if LJ_HASFFI 744#if LJ_HASFFI
681/* Restore raw data from the trace exit state. */ 745/* Restore raw data from the trace exit state. */
682static void snap_restoredata(GCtrace *T, ExitState *ex, 746static void snap_restoredata(jit_State *J, GCtrace *T, ExitState *ex,
683 SnapNo snapno, BloomFilter rfilt, 747 SnapNo snapno, BloomFilter rfilt,
684 IRRef ref, void *dst, CTSize sz) 748 IRRef ref, void *dst, CTSize sz)
685{ 749{
@@ -687,9 +751,10 @@ static void snap_restoredata(GCtrace *T, ExitState *ex,
687 RegSP rs = ir->prev; 751 RegSP rs = ir->prev;
688 int32_t *src; 752 int32_t *src;
689 uint64_t tmp; 753 uint64_t tmp;
754 UNUSED(J);
690 if (irref_isk(ref)) { 755 if (irref_isk(ref)) {
691 if (ir->o == IR_KNUM || ir->o == IR_KINT64) { 756 if (ir_isk64(ir)) {
692 src = mref(ir->ptr, int32_t); 757 src = (int32_t *)&ir[1];
693 } else if (sz == 8) { 758 } else if (sz == 8) {
694 tmp = (uint64_t)(uint32_t)ir->i; 759 tmp = (uint64_t)(uint32_t)ir->i;
695 src = (int32_t *)&tmp; 760 src = (int32_t *)&tmp;
@@ -709,8 +774,9 @@ static void snap_restoredata(GCtrace *T, ExitState *ex,
709 Reg r = regsp_reg(rs); 774 Reg r = regsp_reg(rs);
710 if (ra_noreg(r)) { 775 if (ra_noreg(r)) {
711 /* Note: this assumes CNEWI is never used for SOFTFP split numbers. */ 776 /* Note: this assumes CNEWI is never used for SOFTFP split numbers. */
712 lua_assert(sz == 8 && ir->o == IR_CONV && ir->op2 == IRCONV_NUM_INT); 777 lj_assertJ(sz == 8 && ir->o == IR_CONV && ir->op2 == IRCONV_NUM_INT,
713 snap_restoredata(T, ex, snapno, rfilt, ir->op1, dst, 4); 778 "restore from IR %04d has no reg", ref - REF_BIAS);
779 snap_restoredata(J, T, ex, snapno, rfilt, ir->op1, dst, 4);
714 *(lua_Number *)dst = (lua_Number)*(int32_t *)dst; 780 *(lua_Number *)dst = (lua_Number)*(int32_t *)dst;
715 return; 781 return;
716 } 782 }
@@ -726,11 +792,13 @@ static void snap_restoredata(GCtrace *T, ExitState *ex,
726#else 792#else
727 if (LJ_BE && sz == 4) src++; 793 if (LJ_BE && sz == 4) src++;
728#endif 794#endif
729 } 795 } else
730#endif 796#endif
797 if (LJ_64 && LJ_BE && sz == 4) src++;
731 } 798 }
732 } 799 }
733 lua_assert(sz == 1 || sz == 2 || sz == 4 || sz == 8); 800 lj_assertJ(sz == 1 || sz == 2 || sz == 4 || sz == 8,
801 "restore from IR %04d with bad size %d", ref - REF_BIAS, sz);
734 if (sz == 4) *(int32_t *)dst = *src; 802 if (sz == 4) *(int32_t *)dst = *src;
735 else if (sz == 8) *(int64_t *)dst = *(int64_t *)src; 803 else if (sz == 8) *(int64_t *)dst = *(int64_t *)src;
736 else if (sz == 1) *(int8_t *)dst = (int8_t)*src; 804 else if (sz == 1) *(int8_t *)dst = (int8_t)*src;
@@ -743,24 +811,27 @@ static void snap_unsink(jit_State *J, GCtrace *T, ExitState *ex,
743 SnapNo snapno, BloomFilter rfilt, 811 SnapNo snapno, BloomFilter rfilt,
744 IRIns *ir, TValue *o) 812 IRIns *ir, TValue *o)
745{ 813{
746 lua_assert(ir->o == IR_TNEW || ir->o == IR_TDUP || 814 lj_assertJ(ir->o == IR_TNEW || ir->o == IR_TDUP ||
747 ir->o == IR_CNEW || ir->o == IR_CNEWI); 815 ir->o == IR_CNEW || ir->o == IR_CNEWI,
816 "sunk allocation with bad op %d", ir->o);
748#if LJ_HASFFI 817#if LJ_HASFFI
749 if (ir->o == IR_CNEW || ir->o == IR_CNEWI) { 818 if (ir->o == IR_CNEW || ir->o == IR_CNEWI) {
750 CTState *cts = ctype_cts(J->L); 819 CTState *cts = ctype_cts(J->L);
751 CTypeID id = (CTypeID)T->ir[ir->op1].i; 820 CTypeID id = (CTypeID)T->ir[ir->op1].i;
752 CTSize sz = lj_ctype_size(cts, id); 821 CTSize sz;
753 GCcdata *cd = lj_cdata_new(cts, id, sz); 822 CTInfo info = lj_ctype_info(cts, id, &sz);
823 GCcdata *cd = lj_cdata_newx(cts, id, sz, info);
754 setcdataV(J->L, o, cd); 824 setcdataV(J->L, o, cd);
755 if (ir->o == IR_CNEWI) { 825 if (ir->o == IR_CNEWI) {
756 uint8_t *p = (uint8_t *)cdataptr(cd); 826 uint8_t *p = (uint8_t *)cdataptr(cd);
757 lua_assert(sz == 4 || sz == 8); 827 lj_assertJ(sz == 4 || sz == 8, "sunk cdata with bad size %d", sz);
758 if (LJ_32 && sz == 8 && ir+1 < T->ir + T->nins && (ir+1)->o == IR_HIOP) { 828 if (LJ_32 && sz == 8 && ir+1 < T->ir + T->nins && (ir+1)->o == IR_HIOP) {
759 snap_restoredata(T, ex, snapno, rfilt, (ir+1)->op2, LJ_LE?p+4:p, 4); 829 snap_restoredata(J, T, ex, snapno, rfilt, (ir+1)->op2,
830 LJ_LE ? p+4 : p, 4);
760 if (LJ_BE) p += 4; 831 if (LJ_BE) p += 4;
761 sz = 4; 832 sz = 4;
762 } 833 }
763 snap_restoredata(T, ex, snapno, rfilt, ir->op2, p, sz); 834 snap_restoredata(J, T, ex, snapno, rfilt, ir->op2, p, sz);
764 } else { 835 } else {
765 IRIns *irs, *irlast = &T->ir[T->snap[snapno].ref]; 836 IRIns *irs, *irlast = &T->ir[T->snap[snapno].ref];
766 for (irs = ir+1; irs < irlast; irs++) 837 for (irs = ir+1; irs < irlast; irs++)
@@ -768,8 +839,11 @@ static void snap_unsink(jit_State *J, GCtrace *T, ExitState *ex,
768 IRIns *iro = &T->ir[T->ir[irs->op1].op2]; 839 IRIns *iro = &T->ir[T->ir[irs->op1].op2];
769 uint8_t *p = (uint8_t *)cd; 840 uint8_t *p = (uint8_t *)cd;
770 CTSize szs; 841 CTSize szs;
771 lua_assert(irs->o == IR_XSTORE && T->ir[irs->op1].o == IR_ADD); 842 lj_assertJ(irs->o == IR_XSTORE, "sunk store with bad op %d", irs->o);
772 lua_assert(iro->o == IR_KINT || iro->o == IR_KINT64); 843 lj_assertJ(T->ir[irs->op1].o == IR_ADD,
844 "sunk store with bad add op %d", T->ir[irs->op1].o);
845 lj_assertJ(iro->o == IR_KINT || iro->o == IR_KINT64,
846 "sunk store with bad const offset op %d", iro->o);
773 if (irt_is64(irs->t)) szs = 8; 847 if (irt_is64(irs->t)) szs = 8;
774 else if (irt_isi8(irs->t) || irt_isu8(irs->t)) szs = 1; 848 else if (irt_isi8(irs->t) || irt_isu8(irs->t)) szs = 1;
775 else if (irt_isi16(irs->t) || irt_isu16(irs->t)) szs = 2; 849 else if (irt_isi16(irs->t) || irt_isu16(irs->t)) szs = 2;
@@ -778,14 +852,16 @@ static void snap_unsink(jit_State *J, GCtrace *T, ExitState *ex,
778 p += (int64_t)ir_k64(iro)->u64; 852 p += (int64_t)ir_k64(iro)->u64;
779 else 853 else
780 p += iro->i; 854 p += iro->i;
781 lua_assert(p >= (uint8_t *)cdataptr(cd) && 855 lj_assertJ(p >= (uint8_t *)cdataptr(cd) &&
782 p + szs <= (uint8_t *)cdataptr(cd) + sz); 856 p + szs <= (uint8_t *)cdataptr(cd) + sz,
857 "sunk store with offset out of range");
783 if (LJ_32 && irs+1 < T->ir + T->nins && (irs+1)->o == IR_HIOP) { 858 if (LJ_32 && irs+1 < T->ir + T->nins && (irs+1)->o == IR_HIOP) {
784 lua_assert(szs == 4); 859 lj_assertJ(szs == 4, "sunk store with bad size %d", szs);
785 snap_restoredata(T, ex, snapno, rfilt, (irs+1)->op2, LJ_LE?p+4:p,4); 860 snap_restoredata(J, T, ex, snapno, rfilt, (irs+1)->op2,
861 LJ_LE ? p+4 : p, 4);
786 if (LJ_BE) p += 4; 862 if (LJ_BE) p += 4;
787 } 863 }
788 snap_restoredata(T, ex, snapno, rfilt, irs->op2, p, szs); 864 snap_restoredata(J, T, ex, snapno, rfilt, irs->op2, p, szs);
789 } 865 }
790 } 866 }
791 } else 867 } else
@@ -800,10 +876,12 @@ static void snap_unsink(jit_State *J, GCtrace *T, ExitState *ex,
800 if (irs->r == RID_SINK && snap_sunk_store(T, ir, irs)) { 876 if (irs->r == RID_SINK && snap_sunk_store(T, ir, irs)) {
801 IRIns *irk = &T->ir[irs->op1]; 877 IRIns *irk = &T->ir[irs->op1];
802 TValue tmp, *val; 878 TValue tmp, *val;
803 lua_assert(irs->o == IR_ASTORE || irs->o == IR_HSTORE || 879 lj_assertJ(irs->o == IR_ASTORE || irs->o == IR_HSTORE ||
804 irs->o == IR_FSTORE); 880 irs->o == IR_FSTORE,
881 "sunk store with bad op %d", irs->o);
805 if (irk->o == IR_FREF) { 882 if (irk->o == IR_FREF) {
806 lua_assert(irk->op2 == IRFL_TAB_META); 883 lj_assertJ(irk->op2 == IRFL_TAB_META,
884 "sunk store with bad field %d", irk->op2);
807 snap_restoreval(J, T, ex, snapno, rfilt, irs->op2, &tmp); 885 snap_restoreval(J, T, ex, snapno, rfilt, irs->op2, &tmp);
808 /* NOBARRIER: The table is new (marked white). */ 886 /* NOBARRIER: The table is new (marked white). */
809 setgcref(t->metatable, obj2gco(tabV(&tmp))); 887 setgcref(t->metatable, obj2gco(tabV(&tmp)));
@@ -814,7 +892,7 @@ static void snap_unsink(jit_State *J, GCtrace *T, ExitState *ex,
814 val = lj_tab_set(J->L, t, &tmp); 892 val = lj_tab_set(J->L, t, &tmp);
815 /* NOBARRIER: The table is new (marked white). */ 893 /* NOBARRIER: The table is new (marked white). */
816 snap_restoreval(J, T, ex, snapno, rfilt, irs->op2, val); 894 snap_restoreval(J, T, ex, snapno, rfilt, irs->op2, val);
817 if (LJ_SOFTFP && irs+1 < T->ir + T->nins && (irs+1)->o == IR_HIOP) { 895 if (LJ_SOFTFP32 && irs+1 < T->ir + T->nins && (irs+1)->o == IR_HIOP) {
818 snap_restoreval(J, T, ex, snapno, rfilt, (irs+1)->op2, &tmp); 896 snap_restoreval(J, T, ex, snapno, rfilt, (irs+1)->op2, &tmp);
819 val->u32.hi = tmp.u32.lo; 897 val->u32.hi = tmp.u32.lo;
820 } 898 }
@@ -832,11 +910,15 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
832 SnapShot *snap = &T->snap[snapno]; 910 SnapShot *snap = &T->snap[snapno];
833 MSize n, nent = snap->nent; 911 MSize n, nent = snap->nent;
834 SnapEntry *map = &T->snapmap[snap->mapofs]; 912 SnapEntry *map = &T->snapmap[snap->mapofs];
835 SnapEntry *flinks = &T->snapmap[snap_nextofs(T, snap)-1]; 913#if !LJ_FR2 || defined(LUA_USE_ASSERT)
836 int32_t ftsz0; 914 SnapEntry *flinks = &T->snapmap[snap_nextofs(T, snap)-1-LJ_FR2];
915#endif
916#if !LJ_FR2
917 ptrdiff_t ftsz0;
918#endif
837 TValue *frame; 919 TValue *frame;
838 BloomFilter rfilt = snap_renamefilter(T, snapno); 920 BloomFilter rfilt = snap_renamefilter(T, snapno);
839 const BCIns *pc = snap_pc(map[nent]); 921 const BCIns *pc = snap_pc(&map[nent]);
840 lua_State *L = J->L; 922 lua_State *L = J->L;
841 923
842 /* Set interpreter PC to the next PC to get correct error messages. */ 924 /* Set interpreter PC to the next PC to get correct error messages. */
@@ -849,8 +931,10 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
849 } 931 }
850 932
851 /* Fill stack slots with data from the registers and spill slots. */ 933 /* Fill stack slots with data from the registers and spill slots. */
852 frame = L->base-1; 934 frame = L->base-1-LJ_FR2;
935#if !LJ_FR2
853 ftsz0 = frame_ftsz(frame); /* Preserve link to previous frame in slot #0. */ 936 ftsz0 = frame_ftsz(frame); /* Preserve link to previous frame in slot #0. */
937#endif
854 for (n = 0; n < nent; n++) { 938 for (n = 0; n < nent; n++) {
855 SnapEntry sn = map[n]; 939 SnapEntry sn = map[n];
856 if (!(sn & SNAP_NORESTORE)) { 940 if (!(sn & SNAP_NORESTORE)) {
@@ -869,18 +953,27 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
869 continue; 953 continue;
870 } 954 }
871 snap_restoreval(J, T, ex, snapno, rfilt, ref, o); 955 snap_restoreval(J, T, ex, snapno, rfilt, ref, o);
872 if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM) && tvisint(o)) { 956 if (LJ_SOFTFP32 && (sn & SNAP_SOFTFPNUM) && tvisint(o)) {
873 TValue tmp; 957 TValue tmp;
874 snap_restoreval(J, T, ex, snapno, rfilt, ref+1, &tmp); 958 snap_restoreval(J, T, ex, snapno, rfilt, ref+1, &tmp);
875 o->u32.hi = tmp.u32.lo; 959 o->u32.hi = tmp.u32.lo;
960#if !LJ_FR2
876 } else if ((sn & (SNAP_CONT|SNAP_FRAME))) { 961 } else if ((sn & (SNAP_CONT|SNAP_FRAME))) {
877 /* Overwrite tag with frame link. */ 962 /* Overwrite tag with frame link. */
878 o->fr.tp.ftsz = snap_slot(sn) != 0 ? (int32_t)*flinks-- : ftsz0; 963 setframe_ftsz(o, snap_slot(sn) != 0 ? (int32_t)*flinks-- : ftsz0);
879 L->base = o+1; 964 L->base = o+1;
965#endif
966 } else if ((sn & SNAP_KEYINDEX)) {
967 /* A IRT_INT key index slot is restored as a number. Undo this. */
968 o->u32.lo = (uint32_t)(LJ_DUALNUM ? intV(o) : lj_num2int(numV(o)));
969 o->u32.hi = LJ_KEYINDEX;
880 } 970 }
881 } 971 }
882 } 972 }
883 lua_assert(map + nent == flinks); 973#if LJ_FR2
974 L->base += (map[nent+LJ_BE] & 0xff);
975#endif
976 lj_assertJ(map + nent == flinks, "inconsistent frames in snapshot");
884 977
885 /* Compute current stack top. */ 978 /* Compute current stack top. */
886 switch (bc_op(*pc)) { 979 switch (bc_op(*pc)) {