Use constant metatable if it already exists

This helps in the case of

   o:a()
   o.a(o)

But not in the case of

   o.a(o)
   o:a()
This commit is contained in:
Jude Melton-Houghton 2022-09-19 14:30:26 -04:00
parent b4d853342c
commit 035550b4f7

View File

@ -1060,6 +1060,7 @@ int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm)
{ {
RecordIndex mix; RecordIndex mix;
GCtab *mt; GCtab *mt;
TRef kmt;
if (tref_istab(ix->tab)) { if (tref_istab(ix->tab)) {
mt = tabref(tabV(&ix->tabv)->metatable); mt = tabref(tabV(&ix->tabv)->metatable);
mix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_TAB_META); mix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_TAB_META);
@ -1104,8 +1105,22 @@ 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;
} }
if (ix->mtspec && mt) { kmt = 0;
TRef kmt = lj_ir_ktab(J, mt); if (mt) {
/* Constify metatable or try to find existing constant. */
if (ix->mtspec) {
kmt = lj_ir_ktab(J, mt);
} else {
IRRef ref;
for (ref = J->chain[IR_KGC]; ref; ref = J->cur.ir[ref].prev) {
if (ir_kgc(&J->cur.ir[ref]) == obj2gco(mt)) {
kmt = TREF(ref, IRT_TAB);
break;
}
}
}
}
if (kmt) {
emitir(IRTG(IR_EQ, IRT_TAB), mix.tab, kmt); emitir(IRTG(IR_EQ, IRT_TAB), mix.tab, kmt);
mix.tab = kmt; mix.tab = kmt;
ix->mt = kmt; ix->mt = kmt;