aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2015-05-19 01:59:29 +0200
committerMike Pall <mike>2015-05-19 01:59:29 +0200
commitb82fc3ddc032dfc3da813cda9715d356975922e7 (patch)
tree21e5a68db18a8b3bc339c0e1b3a5c8825ab1e75a
parentd8cfc370ef182ff3240ffd1e27e33d4594fde658 (diff)
downloadluajit-b82fc3ddc032dfc3da813cda9715d356975922e7.tar.gz
luajit-b82fc3ddc032dfc3da813cda9715d356975922e7.tar.bz2
luajit-b82fc3ddc032dfc3da813cda9715d356975922e7.zip
Bump table allocations retroactively if they grow later on.
-rw-r--r--src/lj_jit.h14
-rw-r--r--src/lj_record.c76
-rw-r--r--src/lj_tab.c6
-rw-r--r--src/lj_tab.h1
-rw-r--r--src/lj_trace.c12
-rw-r--r--src/lj_traceerr.h1
6 files changed, 101 insertions, 9 deletions
diff --git a/src/lj_jit.h b/src/lj_jit.h
index 4b51baeb..db3d89bb 100644
--- a/src/lj_jit.h
+++ b/src/lj_jit.h
@@ -290,6 +290,15 @@ typedef struct ScEvEntry {
290 uint8_t dir; /* Direction. 1: +, 0: -. */ 290 uint8_t dir; /* Direction. 1: +, 0: -. */
291} ScEvEntry; 291} ScEvEntry;
292 292
293/* Reverse bytecode map (IRRef -> PC). Only for selected instructions. */
294typedef struct RBCHashEntry {
295 MRef pc; /* Bytecode PC. */
296 IRRef ref; /* IR reference. */
297} RBCHashEntry;
298
299/* Number of slots in the reverse bytecode hash table. Must be a power of 2. */
300#define RBCHASH_SLOTS 8
301
293/* 128 bit SIMD constants. */ 302/* 128 bit SIMD constants. */
294enum { 303enum {
295 LJ_KSIMD_ABS, 304 LJ_KSIMD_ABS,
@@ -364,8 +373,9 @@ typedef struct jit_State {
364 373
365 PostProc postproc; /* Required post-processing after execution. */ 374 PostProc postproc; /* Required post-processing after execution. */
366#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI) 375#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
367 int needsplit; /* Need SPLIT pass. */ 376 uint8_t needsplit; /* Need SPLIT pass. */
368#endif 377#endif
378 uint8_t retryrec; /* Retry recording. */
369 379
370 GCRef *trace; /* Array of traces. */ 380 GCRef *trace; /* Array of traces. */
371 TraceNo freetrace; /* Start of scan for next free trace. */ 381 TraceNo freetrace; /* Start of scan for next free trace. */
@@ -382,6 +392,8 @@ typedef struct jit_State {
382 uint32_t penaltyslot; /* Round-robin index into penalty slots. */ 392 uint32_t penaltyslot; /* Round-robin index into penalty slots. */
383 uint32_t prngstate; /* PRNG state. */ 393 uint32_t prngstate; /* PRNG state. */
384 394
395 RBCHashEntry rbchash[RBCHASH_SLOTS]; /* Reverse bytecode map. */
396
385 BPropEntry bpropcache[BPROP_SLOTS]; /* Backpropagation cache slots. */ 397 BPropEntry bpropcache[BPROP_SLOTS]; /* Backpropagation cache slots. */
386 uint32_t bpropslot; /* Round-robin index into bpropcache slots. */ 398 uint32_t bpropslot; /* Round-robin index into bpropcache slots. */
387 399
diff --git a/src/lj_record.c b/src/lj_record.c
index 56038156..583f80aa 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -235,6 +235,8 @@ static void canonicalize_slots(jit_State *J)
235/* Stop recording. */ 235/* Stop recording. */
236void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk) 236void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk)
237{ 237{
238 if (J->retryrec)
239 lj_trace_err(J, LJ_TRERR_RETRY);
238 lj_trace_end(J); 240 lj_trace_end(J);
239 J->cur.linktype = (uint8_t)linktype; 241 J->cur.linktype = (uint8_t)linktype;
240 J->cur.link = (uint16_t)lnk; 242 J->cur.link = (uint16_t)lnk;
@@ -1127,6 +1129,60 @@ static void rec_mm_comp_cdata(jit_State *J, RecordIndex *ix, int op, MMS mm)
1127 1129
1128/* -- Indexed access ------------------------------------------------------ */ 1130/* -- Indexed access ------------------------------------------------------ */
1129 1131
1132/* Bump table allocations in bytecode when they grow during recording. */
1133static void rec_idx_bump(jit_State *J, RecordIndex *ix)
1134{
1135 RBCHashEntry *rbc = &J->rbchash[(ix->tab & (RBCHASH_SLOTS-1))];
1136 if (tref_ref(ix->tab) == rbc->ref) {
1137 const BCIns *pc = mref(rbc->pc, const BCIns);
1138 GCtab *tb = tabV(&ix->tabv);
1139 uint32_t nhbits;
1140 IRIns *ir;
1141 if (!tvisnil(&ix->keyv))
1142 (void)lj_tab_set(J->L, tb, &ix->keyv); /* Grow table right now. */
1143 nhbits = tb->hmask > 0 ? lj_fls(tb->hmask)+1 : 0;
1144 ir = IR(tref_ref(ix->tab));
1145 if (ir->o == IR_TNEW) {
1146 uint32_t ah = bc_d(*pc);
1147 uint32_t asize = ah & 0x7ff, hbits = ah >> 11;
1148 if (nhbits > hbits) hbits = nhbits;
1149 if (tb->asize > asize) {
1150 asize = tb->asize <= 0x7ff ? tb->asize : 0x7ff;
1151 }
1152 if ((asize | (hbits<<11)) != ah) { /* Has the size changed? */
1153 /* Patch bytecode, but continue recording (for more patching). */
1154 setbc_d(pc, (asize | (hbits<<11)));
1155 /* Patching TNEW operands is only safe if the trace is aborted. */
1156 ir->op1 = asize; ir->op2 = hbits;
1157 J->retryrec = 1; /* Abort the trace at the end of recording. */
1158 }
1159 } else if (ir->o == IR_TDUP) {
1160 GCtab *tpl = gco2tab(proto_kgc(J->pt, ~(ptrdiff_t)bc_d(*pc)));
1161 /* Grow template table, but preserve keys with nil values. */
1162 if (tb->asize > tpl->asize || (1u << nhbits)-1 > tpl->hmask) {
1163 Node *node = noderef(tpl->node);
1164 uint32_t i, hmask = tpl->hmask;
1165 for (i = 0; i <= hmask; i++) {
1166 if (!tvisnil(&node[i].key) && tvisnil(&node[i].val))
1167 settabV(J->L, &node[i].val, tpl);
1168 }
1169 if (!tvisnil(&ix->keyv) && tref_isk(ix->key)) {
1170 TValue *o = lj_tab_set(J->L, tpl, &ix->keyv);
1171 if (tvisnil(o)) settabV(J->L, o, tpl);
1172 }
1173 lj_tab_resize(J->L, tpl, tb->asize, nhbits);
1174 hmask = tpl->hmask;
1175 for (i = 0; i <= hmask; i++) {
1176 /* This is safe, since template tables only hold immutable values. */
1177 if (tvistab(&node[i].val))
1178 setnilV(&node[i].val);
1179 }
1180 J->retryrec = 1; /* Abort the trace at the end of recording. */
1181 }
1182 }
1183 }
1184}
1185
1130/* Record bounds-check. */ 1186/* Record bounds-check. */
1131static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) 1187static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize)
1132{ 1188{
@@ -1352,6 +1408,8 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix)
1352 key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT); 1408 key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT);
1353 xref = emitir(IRT(IR_NEWREF, IRT_P32), ix->tab, key); 1409 xref = emitir(IRT(IR_NEWREF, IRT_P32), ix->tab, key);
1354 keybarrier = 0; /* NEWREF already takes care of the key barrier. */ 1410 keybarrier = 0; /* NEWREF already takes care of the key barrier. */
1411 if ((J->flags & JIT_F_OPT_SINK)) /* Avoid a separate flag. */
1412 rec_idx_bump(J, ix);
1355 } 1413 }
1356 } else if (!lj_opt_fwd_wasnonnil(J, loadop, tref_ref(xref))) { 1414 } else if (!lj_opt_fwd_wasnonnil(J, loadop, tref_ref(xref))) {
1357 /* Cannot derive that the previous value was non-nil, must do checks. */ 1415 /* Cannot derive that the previous value was non-nil, must do checks. */
@@ -1390,9 +1448,16 @@ static void rec_tsetm(jit_State *J, BCReg ra, BCReg rn, int32_t i)
1390{ 1448{
1391 RecordIndex ix; 1449 RecordIndex ix;
1392 cTValue *basev = J->L->base; 1450 cTValue *basev = J->L->base;
1393 copyTV(J->L, &ix.tabv, &basev[ra-1]); 1451 GCtab *t = tabV(&basev[ra-1]);
1452 settabV(J->L, &ix.tabv, t);
1394 ix.tab = getslot(J, ra-1); 1453 ix.tab = getslot(J, ra-1);
1395 ix.idxchain = 0; 1454 ix.idxchain = 0;
1455 if ((J->flags & JIT_F_OPT_SINK)) {
1456 if (t->asize < i+rn-ra)
1457 lj_tab_reasize(J->L, t, i+rn-ra);
1458 setnilV(&ix.keyv);
1459 rec_idx_bump(J, &ix);
1460 }
1396 for (; ra < rn; i++, ra++) { 1461 for (; ra < rn; i++, ra++) {
1397 setintV(&ix.keyv, i); 1462 setintV(&ix.keyv, i);
1398 ix.key = lj_ir_kint(J, i); 1463 ix.key = lj_ir_kint(J, i);
@@ -1712,8 +1777,12 @@ static TRef rec_tnew(jit_State *J, uint32_t ah)
1712{ 1777{
1713 uint32_t asize = ah & 0x7ff; 1778 uint32_t asize = ah & 0x7ff;
1714 uint32_t hbits = ah >> 11; 1779 uint32_t hbits = ah >> 11;
1780 TRef tr;
1715 if (asize == 0x7ff) asize = 0x801; 1781 if (asize == 0x7ff) asize = 0x801;
1716 return emitir(IRTG(IR_TNEW, IRT_TAB), asize, hbits); 1782 tr = emitir(IRTG(IR_TNEW, IRT_TAB), asize, hbits);
1783 J->rbchash[(tr & (RBCHASH_SLOTS-1))].ref = tref_ref(tr);
1784 setmref(J->rbchash[(tr & (RBCHASH_SLOTS-1))].pc, J->pc);
1785 return tr;
1717} 1786}
1718 1787
1719/* -- Concatenation ------------------------------------------------------- */ 1788/* -- Concatenation ------------------------------------------------------- */
@@ -2139,6 +2208,8 @@ void lj_record_ins(jit_State *J)
2139 case BC_TDUP: 2208 case BC_TDUP:
2140 rc = emitir(IRTG(IR_TDUP, IRT_TAB), 2209 rc = emitir(IRTG(IR_TDUP, IRT_TAB),
2141 lj_ir_ktab(J, gco2tab(proto_kgc(J->pt, ~(ptrdiff_t)rc))), 0); 2210 lj_ir_ktab(J, gco2tab(proto_kgc(J->pt, ~(ptrdiff_t)rc))), 0);
2211 J->rbchash[(rc & (RBCHASH_SLOTS-1))].ref = tref_ref(rc);
2212 setmref(J->rbchash[(rc & (RBCHASH_SLOTS-1))].pc, pc);
2142 break; 2213 break;
2143 2214
2144 /* -- Calls and vararg handling ----------------------------------------- */ 2215 /* -- Calls and vararg handling ----------------------------------------- */
@@ -2352,6 +2423,7 @@ void lj_record_setup(jit_State *J)
2352 /* Initialize state related to current trace. */ 2423 /* Initialize state related to current trace. */
2353 memset(J->slot, 0, sizeof(J->slot)); 2424 memset(J->slot, 0, sizeof(J->slot));
2354 memset(J->chain, 0, sizeof(J->chain)); 2425 memset(J->chain, 0, sizeof(J->chain));
2426 memset(J->rbchash, 0, sizeof(J->rbchash));
2355 memset(J->bpropcache, 0, sizeof(J->bpropcache)); 2427 memset(J->bpropcache, 0, sizeof(J->bpropcache));
2356 J->scev.idx = REF_NIL; 2428 J->scev.idx = REF_NIL;
2357 setmref(J->scev.pc, NULL); 2429 setmref(J->scev.pc, NULL);
diff --git a/src/lj_tab.c b/src/lj_tab.c
index a9f43835..88bf1089 100644
--- a/src/lj_tab.c
+++ b/src/lj_tab.c
@@ -246,7 +246,7 @@ void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t)
246/* -- Table resizing ------------------------------------------------------ */ 246/* -- Table resizing ------------------------------------------------------ */
247 247
248/* Resize a table to fit the new array/hash part sizes. */ 248/* Resize a table to fit the new array/hash part sizes. */
249static void resizetab(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits) 249void lj_tab_resize(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits)
250{ 250{
251 Node *oldnode = noderef(t->node); 251 Node *oldnode = noderef(t->node);
252 uint32_t oldasize = t->asize; 252 uint32_t oldasize = t->asize;
@@ -383,7 +383,7 @@ static void rehashtab(lua_State *L, GCtab *t, cTValue *ek)
383 asize += countint(ek, bins); 383 asize += countint(ek, bins);
384 na = bestasize(bins, &asize); 384 na = bestasize(bins, &asize);
385 total -= na; 385 total -= na;
386 resizetab(L, t, asize, hsize2hbits(total)); 386 lj_tab_resize(L, t, asize, hsize2hbits(total));
387} 387}
388 388
389#if LJ_HASFFI 389#if LJ_HASFFI
@@ -395,7 +395,7 @@ void lj_tab_rehash(lua_State *L, GCtab *t)
395 395
396void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize) 396void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize)
397{ 397{
398 resizetab(L, t, nasize+1, t->hmask > 0 ? lj_fls(t->hmask)+1 : 0); 398 lj_tab_resize(L, t, nasize+1, t->hmask > 0 ? lj_fls(t->hmask)+1 : 0);
399} 399}
400 400
401/* -- Table getters ------------------------------------------------------- */ 401/* -- Table getters ------------------------------------------------------- */
diff --git a/src/lj_tab.h b/src/lj_tab.h
index 1da28bd9..7cf031be 100644
--- a/src/lj_tab.h
+++ b/src/lj_tab.h
@@ -44,6 +44,7 @@ LJ_FUNC void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t);
44#if LJ_HASFFI 44#if LJ_HASFFI
45LJ_FUNC void lj_tab_rehash(lua_State *L, GCtab *t); 45LJ_FUNC void lj_tab_rehash(lua_State *L, GCtab *t);
46#endif 46#endif
47LJ_FUNC void lj_tab_resize(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits);
47LJ_FUNCA void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize); 48LJ_FUNCA void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize);
48 49
49/* Caveat: all getters except lj_tab_get() can return NULL! */ 50/* Caveat: all getters except lj_tab_get() can return NULL! */
diff --git a/src/lj_trace.c b/src/lj_trace.c
index 39ff0461..79c50b0a 100644
--- a/src/lj_trace.c
+++ b/src/lj_trace.c
@@ -394,6 +394,7 @@ static void trace_start(jit_State *J)
394 J->guardemit.irt = 0; 394 J->guardemit.irt = 0;
395 J->postproc = LJ_POST_NONE; 395 J->postproc = LJ_POST_NONE;
396 lj_resetsplit(J); 396 lj_resetsplit(J);
397 J->retryrec = 0;
397 setgcref(J->cur.startpt, obj2gco(J->pt)); 398 setgcref(J->cur.startpt, obj2gco(J->pt));
398 399
399 L = J->L; 400 L = J->L;
@@ -510,10 +511,15 @@ static int trace_abort(jit_State *J)
510 } 511 }
511 /* Penalize or blacklist starting bytecode instruction. */ 512 /* Penalize or blacklist starting bytecode instruction. */
512 if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) { 513 if (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))) {
513 if (J->exitno == 0) 514 if (J->exitno == 0) {
514 penalty_pc(J, &gcref(J->cur.startpt)->pt, mref(J->cur.startpc, BCIns), e); 515 BCIns *startpc = mref(J->cur.startpc, BCIns);
515 else 516 if (e == LJ_TRERR_RETRY)
517 hotcount_set(J2GG(J), startpc+1, 1); /* Immediate retry. */
518 else
519 penalty_pc(J, &gcref(J->cur.startpt)->pt, startpc, e);
520 } else {
516 traceref(J, J->exitno)->link = J->exitno; /* Self-link is blacklisted. */ 521 traceref(J, J->exitno)->link = J->exitno; /* Self-link is blacklisted. */
522 }
517 } 523 }
518 524
519 /* Is there anything to abort? */ 525 /* Is there anything to abort? */
diff --git a/src/lj_traceerr.h b/src/lj_traceerr.h
index 5a2fe8bb..0f38562b 100644
--- a/src/lj_traceerr.h
+++ b/src/lj_traceerr.h
@@ -12,6 +12,7 @@ TREDEF(TRACEOV, "trace too long")
12TREDEF(STACKOV, "trace too deep") 12TREDEF(STACKOV, "trace too deep")
13TREDEF(SNAPOV, "too many snapshots") 13TREDEF(SNAPOV, "too many snapshots")
14TREDEF(BLACKL, "blacklisted") 14TREDEF(BLACKL, "blacklisted")
15TREDEF(RETRY, "retry recording")
15TREDEF(NYIBC, "NYI: bytecode %d") 16TREDEF(NYIBC, "NYI: bytecode %d")
16 17
17/* Recording loop ops. */ 18/* Recording loop ops. */