This commit is contained in:
Jude Melton-Houghton 2024-05-28 09:00:03 +08:00 committed by GitHub
commit fff6858a8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 39 additions and 11 deletions

View File

@ -238,6 +238,7 @@ static void LJ_FASTCALL recff_getmetatable(jit_State *J, RecordFFData *rd)
RecordIndex ix; RecordIndex ix;
ix.tab = tr; ix.tab = tr;
copyTV(J->L, &ix.tabv, &rd->argv[0]); copyTV(J->L, &ix.tabv, &rd->argv[0]);
ix.mtspec = 0;
if (lj_record_mm_lookup(J, &ix, MM_metatable)) if (lj_record_mm_lookup(J, &ix, MM_metatable))
J->base[0] = ix.mobj; J->base[0] = ix.mobj;
else else
@ -254,6 +255,7 @@ static void LJ_FASTCALL recff_setmetatable(jit_State *J, RecordFFData *rd)
RecordIndex ix; RecordIndex ix;
ix.tab = tr; ix.tab = tr;
copyTV(J->L, &ix.tabv, &rd->argv[0]); copyTV(J->L, &ix.tabv, &rd->argv[0]);
ix.mtspec = 0;
lj_record_mm_lookup(J, &ix, MM_metatable); /* Guard for no __metatable. */ lj_record_mm_lookup(J, &ix, MM_metatable); /* Guard for no __metatable. */
fref = emitir(IRT(IR_FREF, IRT_PGC), tr, IRFL_TAB_META); fref = emitir(IRT(IR_FREF, IRT_PGC), tr, IRFL_TAB_META);
mtref = tref_isnil(mt) ? lj_ir_knull(J, IRT_TAB) : mt; mtref = tref_isnil(mt) ? lj_ir_knull(J, IRT_TAB) : mt;
@ -402,6 +404,7 @@ static int recff_metacall(jit_State *J, RecordFFData *rd, MMS mm)
RecordIndex ix; RecordIndex ix;
ix.tab = J->base[0]; ix.tab = J->base[0];
copyTV(J->L, &ix.tabv, &rd->argv[0]); copyTV(J->L, &ix.tabv, &rd->argv[0]);
ix.mtspec = 1;
if (lj_record_mm_lookup(J, &ix, mm)) { /* Has metamethod? */ if (lj_record_mm_lookup(J, &ix, mm)) { /* Has metamethod? */
int errcode; int errcode;
TValue argv0; TValue argv0;
@ -561,6 +564,7 @@ static void LJ_FASTCALL recff_next(jit_State *J, RecordFFData *rd)
ix.idxchain = (J->framedepth && frame_islua(J->L->base-1) && ix.idxchain = (J->framedepth && frame_islua(J->L->base-1) &&
bc_b(frame_pc(J->L->base-1)[-1])-1 < 2); bc_b(frame_pc(J->L->base-1)[-1])-1 < 2);
ix.mobj = 0; /* We don't need the next index. */ ix.mobj = 0; /* We don't need the next index. */
ix.mtspec = 0;
rd->nres = lj_record_next(J, &ix); rd->nres = lj_record_next(J, &ix);
J->base[0] = ix.key; J->base[0] = ix.key;
J->base[1] = ix.val; J->base[1] = ix.val;

View File

@ -687,6 +687,7 @@ static LoopEvent rec_itern(jit_State *J, BCReg ra, BCReg rb)
copyTV(J->L, &ix.keyv, &J->L->base[ra-1]); copyTV(J->L, &ix.keyv, &J->L->base[ra-1]);
ix.idxchain = (rb < 3); /* Omit value type check, if unused. */ ix.idxchain = (rb < 3); /* Omit value type check, if unused. */
ix.mobj = 1; /* We need the next index, too. */ ix.mobj = 1; /* We need the next index, too. */
ix.mtspec = 0;
J->maxslot = ra + lj_record_next(J, &ix); J->maxslot = ra + lj_record_next(J, &ix);
J->needsnap = 1; J->needsnap = 1;
if (!tref_isnil(ix.key)) { /* Looping back? */ if (!tref_isnil(ix.key)) { /* Looping back? */
@ -819,6 +820,7 @@ static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs)
if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */ if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */
ix.tab = fbase[0]; ix.tab = fbase[0];
copyTV(J->L, &ix.tabv, functv); copyTV(J->L, &ix.tabv, functv);
ix.mtspec = 1;
if (!lj_record_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj)) if (!lj_record_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj))
lj_trace_err(J, LJ_TRERR_NOMM); lj_trace_err(J, LJ_TRERR_NOMM);
for (i = ++nargs; i > LJ_FR2; i--) /* Shift arguments up. */ for (i = ++nargs; i > LJ_FR2; i--) /* Shift arguments up. */
@ -1110,8 +1112,15 @@ int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm)
GG_OFS(g.gcroot[GCROOT_BASEMT+itypemap(&ix->tabv)])); GG_OFS(g.gcroot[GCROOT_BASEMT+itypemap(&ix->tabv)]));
goto nocheck; goto nocheck;
} }
ix->mt = mt ? mix.tab : TREF_NIL; if (ix->mtspec && mt) {
emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mix.tab, lj_ir_knull(J, IRT_TAB)); TRef kmt = lj_ir_ktab(J, mt);
emitir(IRTG(IR_EQ, IRT_TAB), mix.tab, kmt);
mix.tab = kmt;
ix->mt = kmt;
} else {
ix->mt = mt ? mix.tab : TREF_NIL;
emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mix.tab, lj_ir_knull(J, IRT_TAB));
}
nocheck: nocheck:
if (mt) { if (mt) {
GCstr *mmstr = mmname_str(J2G(J), mm); GCstr *mmstr = mmname_str(J2G(J), mm);
@ -1165,6 +1174,7 @@ static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv)
RecordIndex ix; RecordIndex ix;
ix.tab = tr; ix.tab = tr;
copyTV(J->L, &ix.tabv, tv); copyTV(J->L, &ix.tabv, tv);
ix.mtspec = 1;
if (lj_record_mm_lookup(J, &ix, MM_len)) { if (lj_record_mm_lookup(J, &ix, MM_len)) {
BCReg func = rec_mm_prep(J, lj_cont_ra); BCReg func = rec_mm_prep(J, lj_cont_ra);
TRef *base = J->base + func; TRef *base = J->base + func;
@ -2116,6 +2126,7 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
ix.tab = top[-1]; ix.tab = top[-1];
ix.key = top[0]; ix.key = top[0];
memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */ memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */
ix.mtspec = 1;
rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */ rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */
memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */
return 0; /* No result yet. */ return 0; /* No result yet. */
@ -2320,6 +2331,7 @@ void lj_record_ins(jit_State *J)
rc = lj_ir_kint(J, 0); rc = lj_ir_kint(J, 0);
ta = IRT_INT; ta = IRT_INT;
} else { } else {
ix.mtspec = 1;
rec_mm_comp(J, &ix, (int)op); rec_mm_comp(J, &ix, (int)op);
break; break;
} }
@ -2343,10 +2355,12 @@ void lj_record_ins(jit_State *J)
int diff; int diff;
rec_comp_prep(J); rec_comp_prep(J);
diff = lj_record_objcmp(J, ra, rc, rav, rcv); diff = lj_record_objcmp(J, ra, rc, rav, rcv);
if (diff == 2 || !(tref_istab(ra) || tref_isudata(ra))) if (diff == 2 || !(tref_istab(ra) || tref_isudata(ra))) {
rec_comp_fixup(J, J->pc, ((int)op & 1) == !diff); rec_comp_fixup(J, J->pc, ((int)op & 1) == !diff);
else if (diff == 1) /* Only check __eq if different, but same type. */ } else if (diff == 1) { /* Only check __eq if different, but same type. */
ix.mtspec = 1;
rec_mm_equal(J, &ix, (int)op); rec_mm_equal(J, &ix, (int)op);
}
} }
break; break;
@ -2397,6 +2411,7 @@ void lj_record_ins(jit_State *J)
} else { } else {
ix.tab = rc; ix.tab = rc;
copyTV(J->L, &ix.tabv, rcv); copyTV(J->L, &ix.tabv, rcv);
ix.mtspec = 1;
rc = rec_mm_arith(J, &ix, MM_unm); rc = rec_mm_arith(J, &ix, MM_unm);
} }
break; break;
@ -2413,27 +2428,33 @@ void lj_record_ins(jit_State *J)
case BC_ADDVN: case BC_SUBVN: case BC_MULVN: case BC_DIVVN: case BC_ADDVN: case BC_SUBVN: case BC_MULVN: case BC_DIVVN:
case BC_ADDVV: case BC_SUBVV: case BC_MULVV: case BC_DIVVV: { case BC_ADDVV: case BC_SUBVV: case BC_MULVV: case BC_DIVVV: {
MMS mm = bcmode_mm(op); MMS mm = bcmode_mm(op);
if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) {
rc = lj_opt_narrow_arith(J, rb, rc, rbv, rcv, rc = lj_opt_narrow_arith(J, rb, rc, rbv, rcv,
(int)mm - (int)MM_add + (int)IR_ADD); (int)mm - (int)MM_add + (int)IR_ADD);
else } else {
ix.mtspec = 1;
rc = rec_mm_arith(J, &ix, mm); rc = rec_mm_arith(J, &ix, mm);
}
break; break;
} }
case BC_MODVN: case BC_MODVV: case BC_MODVN: case BC_MODVV:
recmod: recmod:
if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) {
rc = lj_opt_narrow_mod(J, rb, rc, rbv, rcv); rc = lj_opt_narrow_mod(J, rb, rc, rbv, rcv);
else } else {
ix.mtspec = 1;
rc = rec_mm_arith(J, &ix, MM_mod); rc = rec_mm_arith(J, &ix, MM_mod);
}
break; break;
case BC_POW: case BC_POW:
if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) {
rc = lj_opt_narrow_arith(J, rb, rc, rbv, rcv, IR_POW); rc = lj_opt_narrow_arith(J, rb, rc, rbv, rcv, IR_POW);
else } else {
ix.mtspec = 1;
rc = rec_mm_arith(J, &ix, MM_pow); rc = rec_mm_arith(J, &ix, MM_pow);
}
break; break;
/* -- Miscellaneous ops ------------------------------------------------- */ /* -- Miscellaneous ops ------------------------------------------------- */
@ -2487,6 +2508,7 @@ void lj_record_ins(jit_State *J)
settabV(J->L, &ix.tabv, tabref(J->fn->l.env)); settabV(J->L, &ix.tabv, tabref(J->fn->l.env));
ix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), getcurrf(J), IRFL_FUNC_ENV); ix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), getcurrf(J), IRFL_FUNC_ENV);
ix.idxchain = LJ_MAX_IDXCHAIN; ix.idxchain = LJ_MAX_IDXCHAIN;
ix.mtspec = 0;
rc = lj_record_idx(J, &ix); rc = lj_record_idx(J, &ix);
break; break;
@ -2496,6 +2518,7 @@ void lj_record_ins(jit_State *J)
/* fallthrough */ /* fallthrough */
case BC_TGETV: case BC_TGETS: case BC_TSETV: case BC_TSETS: case BC_TGETV: case BC_TGETS: case BC_TSETV: case BC_TSETS:
ix.idxchain = LJ_MAX_IDXCHAIN; ix.idxchain = LJ_MAX_IDXCHAIN;
ix.mtspec = tref_isk(ix.key) && tref_isstr(ix.key);
rc = lj_record_idx(J, &ix); rc = lj_record_idx(J, &ix);
break; break;
case BC_TGETR: case BC_TSETR: case BC_TGETR: case BC_TSETR:

View File

@ -23,7 +23,8 @@ typedef struct RecordIndex {
TRef val; /* Value reference for a store or 0 for a load. */ TRef val; /* Value reference for a store or 0 for a load. */
TRef mt; /* Metatable reference. */ TRef mt; /* Metatable reference. */
TRef mobj; /* Metamethod object reference. */ TRef mobj; /* Metamethod object reference. */
int idxchain; /* Index indirections left or 0 for raw lookup. */ short idxchain; /* Index indirections left or 0 for raw lookup. */
short mtspec; /* Specialize to metatable. */
} RecordIndex; } RecordIndex;
LJ_FUNC int lj_record_objcmp(jit_State *J, TRef a, TRef b, LJ_FUNC int lj_record_objcmp(jit_State *J, TRef a, TRef b,