mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-12 09:24:07 +00:00
Make metamethod names proper GC roots.
This commit is contained in:
parent
87e4daf89c
commit
ef0904e80b
@ -1089,7 +1089,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|
||||
dasm_put(Dst, 1814);
|
||||
}
|
||||
dasm_put(Dst, 1823, ((char *)(&((GCfuncC *)0)->upvalue)), LJ_TSTR, ~LJ_TLIGHTUD, 1+1, LJ_TTAB, Dt6(->metatable), LJ_TNIL);
|
||||
dasm_put(Dst, 1902, DISPATCH_GL(mmname)+4*MM_metatable, LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), DtB(->next));
|
||||
dasm_put(Dst, 1902, DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable), LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), DtB(->next));
|
||||
dasm_put(Dst, 1960, LJ_TNIL, LJ_TUDATA, LJ_TISNUM, LJ_TNUMX, DISPATCH_GL(gcroot[GCROOT_BASEMT]));
|
||||
dasm_put(Dst, 2029, 2+1, LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->marked), LJ_GC_BLACK, Dt6(->marked), cast_byte(~LJ_GC_BLACK));
|
||||
dasm_put(Dst, 2098, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist), 2+1, LJ_TTAB, 1+1, LJ_TISNUM);
|
||||
|
@ -1089,7 +1089,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|
||||
dasm_put(Dst, 1790);
|
||||
}
|
||||
dasm_put(Dst, 1799, ((char *)(&((GCfuncC *)0)->upvalue)), LJ_TSTR, ~LJ_TLIGHTUD, 1+1, LJ_TTAB, Dt6(->metatable), LJ_TNIL);
|
||||
dasm_put(Dst, 1878, DISPATCH_GL(mmname)+4*MM_metatable, LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), DtB(->next));
|
||||
dasm_put(Dst, 1878, DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable), LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), DtB(->next));
|
||||
dasm_put(Dst, 1935, LJ_TNIL, LJ_TUDATA, LJ_TISNUM, LJ_TNUMX, DISPATCH_GL(gcroot[GCROOT_BASEMT]));
|
||||
dasm_put(Dst, 2003, 2+1, LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->marked), LJ_GC_BLACK, Dt6(->marked), cast_byte(~LJ_GC_BLACK));
|
||||
dasm_put(Dst, 2072, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist), 2+1, LJ_TTAB, 1+1, LJ_TISNUM);
|
||||
|
@ -1302,7 +1302,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|
||||
| test TAB:RB, TAB:RB
|
||||
| mov dword [BASE-4], LJ_TNIL
|
||||
| jz ->fff_res1
|
||||
| mov STR:RC, [DISPATCH+DISPATCH_GL(mmname)+4*MM_metatable]
|
||||
| mov STR:RC, [DISPATCH+DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable)]
|
||||
| mov dword [BASE-4], LJ_TTAB // Store metatable as default result.
|
||||
| mov [BASE-8], TAB:RB
|
||||
| mov RA, TAB:RB->hmask
|
||||
|
@ -1143,7 +1143,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|
||||
} else {
|
||||
dasm_put(Dst, 1769);
|
||||
}
|
||||
dasm_put(Dst, 1778, ((char *)(&((GCfuncC *)0)->upvalue)), LJ_TSTR, 1+1, LJ_TTAB, Dt6(->metatable), LJ_TNIL, DISPATCH_GL(mmname)+4*MM_metatable, LJ_TTAB);
|
||||
dasm_put(Dst, 1778, ((char *)(&((GCfuncC *)0)->upvalue)), LJ_TSTR, 1+1, LJ_TTAB, Dt6(->metatable), LJ_TNIL, DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable), LJ_TTAB);
|
||||
dasm_put(Dst, 1861, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), DtB(->next), LJ_TNIL);
|
||||
dasm_put(Dst, 1919, LJ_TUDATA, LJ_TISNUM, LJ_TNUMX, DISPATCH_GL(gcroot[GCROOT_BASEMT]), 2+1);
|
||||
dasm_put(Dst, 1982, LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->marked), LJ_GC_BLACK, Dt6(->marked), cast_byte(~LJ_GC_BLACK), DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist));
|
||||
|
@ -774,7 +774,6 @@ LJLIB_CF(string_format)
|
||||
LUALIB_API int luaopen_string(lua_State *L)
|
||||
{
|
||||
GCtab *mt;
|
||||
GCstr *mmstr;
|
||||
global_State *g;
|
||||
LJ_LIB_REG(L, string);
|
||||
#if defined(LUA_COMPAT_GFIND)
|
||||
@ -785,9 +784,7 @@ LUALIB_API int luaopen_string(lua_State *L)
|
||||
/* NOBARRIER: basemt is a GC root. */
|
||||
g = G(L);
|
||||
setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt));
|
||||
mmstr = strref(g->mmname[MM_index]);
|
||||
if (isdead(g, obj2gco(mmstr))) flipwhite(obj2gco(mmstr));
|
||||
settabV(L, lj_tab_setstr(L, mt, mmstr), tabV(L->top-1));
|
||||
settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1));
|
||||
mt->nomm = cast_byte(~(1u<<MM_index));
|
||||
return 1;
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ static const char *getfuncname(lua_State *L, TValue *frame, const char **name)
|
||||
if (bc_op(*ip) == BC_ITERC) slot -= 3;
|
||||
return getobjname(funcproto(fn), ip, slot, name);
|
||||
} else if (mm != MM_MAX) {
|
||||
*name = strdata(strref(G(L)->mmname[mm]));
|
||||
*name = strdata(mmname_str(G(L), mm));
|
||||
return "metamethod";
|
||||
} else {
|
||||
return NULL;
|
||||
|
@ -77,7 +77,7 @@ static void gc_mark(global_State *g, GCobj *o)
|
||||
static void gc_mark_gcroot(global_State *g)
|
||||
{
|
||||
ptrdiff_t i;
|
||||
for (i = 0; i < GCROOT__MAX; i++)
|
||||
for (i = 0; i < GCROOT_MAX; i++)
|
||||
if (gcref(g->gcroot[i]) != NULL)
|
||||
gc_markobj(g, gcref(g->gcroot[i]));
|
||||
}
|
||||
|
@ -28,14 +28,13 @@ void lj_meta_init(lua_State *L)
|
||||
#undef MMNAME
|
||||
global_State *g = G(L);
|
||||
const char *p, *q;
|
||||
uint32_t i;
|
||||
for (i = 0, p = metanames; *p; i++, p = q) {
|
||||
uint32_t mm;
|
||||
for (mm = 0, p = metanames; *p; mm++, p = q) {
|
||||
GCstr *s;
|
||||
for (q = p+2; *q && *q != '_'; q++) ;
|
||||
s = lj_str_new(L, p, (size_t)(q-p));
|
||||
fixstring(s); /* Never collect these names. */
|
||||
/* NOBARRIER: g->mmname[] is a GC root. */
|
||||
setgcref(g->mmname[i], obj2gco(s));
|
||||
/* NOBARRIER: g->gcroot[] is a GC root. */
|
||||
setgcref(g->gcroot[GCROOT_MMNAME+mm], obj2gco(s));
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,7 +61,7 @@ cTValue *lj_meta_lookup(lua_State *L, cTValue *o, MMS mm)
|
||||
else
|
||||
mt = tabref(basemt_obj(G(L), o));
|
||||
if (mt) {
|
||||
cTValue *mo = lj_tab_getstr(mt, strref(G(L)->mmname[mm]));
|
||||
cTValue *mo = lj_tab_getstr(mt, mmname_str(G(L), mm));
|
||||
if (mo)
|
||||
return mo;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ LJ_FUNC cTValue *lj_meta_lookup(lua_State *L, cTValue *o, MMS mm);
|
||||
|
||||
#define lj_meta_fastg(g, mt, mm) \
|
||||
((mt) == NULL ? NULL : ((mt)->nomm & (1u<<(mm))) ? NULL : \
|
||||
lj_meta_cache(mt, mm, strref((g)->mmname[mm])))
|
||||
lj_meta_cache(mt, mm, mmname_str(g, mm)))
|
||||
#define lj_meta_fast(L, mt, mm) lj_meta_fastg(G(L), mt, mm)
|
||||
|
||||
/* C helpers for some instructions, called from assembler VM. */
|
||||
|
10
src/lj_obj.h
10
src/lj_obj.h
@ -537,15 +537,18 @@ MMDEF(MMENUM)
|
||||
|
||||
/* GC root IDs. */
|
||||
typedef enum {
|
||||
GCROOT_MMNAME, /* Metamethod names. */
|
||||
GCROOT_MMNAME_LAST = GCROOT_MMNAME + MM_MAX-1,
|
||||
GCROOT_BASEMT, /* Metatables for base types. */
|
||||
GCROOT_BASEMT_NUM = ~LJ_TNUMX, /* Last base metatable. */
|
||||
GCROOT_BASEMT_NUM = GCROOT_BASEMT + ~LJ_TNUMX,
|
||||
GCROOT_IO_INPUT, /* Userdata for default I/O input file. */
|
||||
GCROOT_IO_OUTPUT, /* Userdata for default I/O output file. */
|
||||
GCROOT__MAX
|
||||
GCROOT_MAX
|
||||
} GCRootID;
|
||||
|
||||
#define basemt_it(g, it) ((g)->gcroot[GCROOT_BASEMT+~(it)])
|
||||
#define basemt_obj(g, o) ((g)->gcroot[GCROOT_BASEMT+itypemap(o)])
|
||||
#define mmname_str(g, mm) (strref((g)->gcroot[GCROOT_MMNAME+(mm)]))
|
||||
|
||||
typedef struct GCState {
|
||||
MSize total; /* Memory currently allocated. */
|
||||
@ -595,8 +598,7 @@ typedef struct global_State {
|
||||
BCIns bc_cfunc_ext; /* Bytecode for external C function calls. */
|
||||
GCRef jit_L; /* Current JIT code lua_State or NULL. */
|
||||
MRef jit_base; /* Current JIT code L->base. */
|
||||
GCRef gcroot[GCROOT__MAX]; /* GC roots. */
|
||||
GCRef mmname[MM_MAX]; /* Array holding metamethod names. */
|
||||
GCRef gcroot[GCROOT_MAX]; /* GC roots. */
|
||||
} global_State;
|
||||
|
||||
#define mainthread(g) (&gcref(g->mainthref)->th)
|
||||
|
@ -677,14 +677,12 @@ static int rec_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm)
|
||||
emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mix.tab, lj_ir_knull(J, IRT_TAB));
|
||||
nocheck:
|
||||
if (mt) {
|
||||
GCstr *mmstr = strref(J2G(J)->mmname[mm]);
|
||||
GCstr *mmstr = mmname_str(J2G(J), mm);
|
||||
cTValue *mo = lj_tab_getstr(mt, mmstr);
|
||||
if (mo && !tvisnil(mo))
|
||||
copyTV(J->L, &ix->mobjv, mo);
|
||||
ix->mtv = mt;
|
||||
settabV(J->L, &mix.tabv, mt);
|
||||
if (isdead(J2G(J), obj2gco(mmstr)))
|
||||
flipwhite(obj2gco(mmstr)); /* Need same logic as lj_str_new(). */
|
||||
setstrV(J->L, &mix.keyv, mmstr);
|
||||
mix.key = lj_ir_kstr(J, mmstr);
|
||||
mix.val = 0;
|
||||
@ -914,9 +912,9 @@ static int nommstr(jit_State *J, TRef key)
|
||||
if (tref_isstr(key)) {
|
||||
if (tref_isk(key)) {
|
||||
GCstr *str = ir_kstr(IR(tref_ref(key)));
|
||||
uint32_t i;
|
||||
for (i = 0; i <= MM_FAST; i++)
|
||||
if (strref(J2G(J)->mmname[i]) == str)
|
||||
uint32_t mm;
|
||||
for (mm = 0; mm <= MM_FAST; mm++)
|
||||
if (mmname_str(J2G(J), mm) == str)
|
||||
return 0; /* MUST be one the fast metamethod names. */
|
||||
} else {
|
||||
return 0; /* Variable string key MAY be a metamethod name. */
|
||||
@ -999,7 +997,7 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
|
||||
/* Need to duplicate the hasmm check for the early guards. */
|
||||
int hasmm = 0;
|
||||
if (ix->idxchain && mt) {
|
||||
cTValue *mo = lj_tab_getstr(mt, strref(J2G(J)->mmname[MM_newindex]));
|
||||
cTValue *mo = lj_tab_getstr(mt, mmname_str(J2G(J), MM_newindex));
|
||||
hasmm = mo && !tvisnil(mo);
|
||||
}
|
||||
if (hasmm)
|
||||
|
@ -88,7 +88,8 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
|
||||
for (o = gcref(g->strhash[h & g->strmask]); o != NULL; o = gcnext(o)) {
|
||||
GCstr *tso = gco2str(o);
|
||||
if (tso->len == len && (memcmp(str, strdata(tso), len) == 0)) {
|
||||
if (isdead(g, o)) flipwhite(o); /* Resurrect if dead. */
|
||||
/* Resurrect if dead. Can only happen with fixstring() (keywords). */
|
||||
if (isdead(g, o)) flipwhite(o);
|
||||
return tso; /* Return existing string. */
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user