diff options
author | Mike Pall <mike> | 2015-05-19 01:59:29 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2015-05-19 01:59:29 +0200 |
commit | b82fc3ddc032dfc3da813cda9715d356975922e7 (patch) | |
tree | 21e5a68db18a8b3bc339c0e1b3a5c8825ab1e75a /src/lj_record.c | |
parent | d8cfc370ef182ff3240ffd1e27e33d4594fde658 (diff) | |
download | luajit-b82fc3ddc032dfc3da813cda9715d356975922e7.tar.gz luajit-b82fc3ddc032dfc3da813cda9715d356975922e7.tar.bz2 luajit-b82fc3ddc032dfc3da813cda9715d356975922e7.zip |
Bump table allocations retroactively if they grow later on.
Diffstat (limited to 'src/lj_record.c')
-rw-r--r-- | src/lj_record.c | 76 |
1 files changed, 74 insertions, 2 deletions
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. */ |
236 | void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk) | 236 | void 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. */ | ||
1133 | static 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. */ |
1131 | static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) | 1187 | static 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); |