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, 1814);
|
||||||
}
|
}
|
||||||
dasm_put(Dst, 1823, ((char *)(&((GCfuncC *)0)->upvalue)), LJ_TSTR, ~LJ_TLIGHTUD, 1+1, LJ_TTAB, Dt6(->metatable), LJ_TNIL);
|
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, 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, 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);
|
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, 1790);
|
||||||
}
|
}
|
||||||
dasm_put(Dst, 1799, ((char *)(&((GCfuncC *)0)->upvalue)), LJ_TSTR, ~LJ_TLIGHTUD, 1+1, LJ_TTAB, Dt6(->metatable), LJ_TNIL);
|
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, 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, 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);
|
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
|
| test TAB:RB, TAB:RB
|
||||||
| mov dword [BASE-4], LJ_TNIL
|
| mov dword [BASE-4], LJ_TNIL
|
||||||
| jz ->fff_res1
|
| 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 dword [BASE-4], LJ_TTAB // Store metatable as default result.
|
||||||
| mov [BASE-8], TAB:RB
|
| mov [BASE-8], TAB:RB
|
||||||
| mov RA, TAB:RB->hmask
|
| mov RA, TAB:RB->hmask
|
||||||
|
@ -1143,7 +1143,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|
|||||||
} else {
|
} else {
|
||||||
dasm_put(Dst, 1769);
|
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, 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, 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));
|
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)
|
LUALIB_API int luaopen_string(lua_State *L)
|
||||||
{
|
{
|
||||||
GCtab *mt;
|
GCtab *mt;
|
||||||
GCstr *mmstr;
|
|
||||||
global_State *g;
|
global_State *g;
|
||||||
LJ_LIB_REG(L, string);
|
LJ_LIB_REG(L, string);
|
||||||
#if defined(LUA_COMPAT_GFIND)
|
#if defined(LUA_COMPAT_GFIND)
|
||||||
@ -785,9 +784,7 @@ LUALIB_API int luaopen_string(lua_State *L)
|
|||||||
/* NOBARRIER: basemt is a GC root. */
|
/* NOBARRIER: basemt is a GC root. */
|
||||||
g = G(L);
|
g = G(L);
|
||||||
setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt));
|
setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt));
|
||||||
mmstr = strref(g->mmname[MM_index]);
|
settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1));
|
||||||
if (isdead(g, obj2gco(mmstr))) flipwhite(obj2gco(mmstr));
|
|
||||||
settabV(L, lj_tab_setstr(L, mt, mmstr), tabV(L->top-1));
|
|
||||||
mt->nomm = cast_byte(~(1u<<MM_index));
|
mt->nomm = cast_byte(~(1u<<MM_index));
|
||||||
return 1;
|
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;
|
if (bc_op(*ip) == BC_ITERC) slot -= 3;
|
||||||
return getobjname(funcproto(fn), ip, slot, name);
|
return getobjname(funcproto(fn), ip, slot, name);
|
||||||
} else if (mm != MM_MAX) {
|
} else if (mm != MM_MAX) {
|
||||||
*name = strdata(strref(G(L)->mmname[mm]));
|
*name = strdata(mmname_str(G(L), mm));
|
||||||
return "metamethod";
|
return "metamethod";
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -77,7 +77,7 @@ static void gc_mark(global_State *g, GCobj *o)
|
|||||||
static void gc_mark_gcroot(global_State *g)
|
static void gc_mark_gcroot(global_State *g)
|
||||||
{
|
{
|
||||||
ptrdiff_t i;
|
ptrdiff_t i;
|
||||||
for (i = 0; i < GCROOT__MAX; i++)
|
for (i = 0; i < GCROOT_MAX; i++)
|
||||||
if (gcref(g->gcroot[i]) != NULL)
|
if (gcref(g->gcroot[i]) != NULL)
|
||||||
gc_markobj(g, gcref(g->gcroot[i]));
|
gc_markobj(g, gcref(g->gcroot[i]));
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,13 @@ void lj_meta_init(lua_State *L)
|
|||||||
#undef MMNAME
|
#undef MMNAME
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
const char *p, *q;
|
const char *p, *q;
|
||||||
uint32_t i;
|
uint32_t mm;
|
||||||
for (i = 0, p = metanames; *p; i++, p = q) {
|
for (mm = 0, p = metanames; *p; mm++, p = q) {
|
||||||
GCstr *s;
|
GCstr *s;
|
||||||
for (q = p+2; *q && *q != '_'; q++) ;
|
for (q = p+2; *q && *q != '_'; q++) ;
|
||||||
s = lj_str_new(L, p, (size_t)(q-p));
|
s = lj_str_new(L, p, (size_t)(q-p));
|
||||||
fixstring(s); /* Never collect these names. */
|
/* NOBARRIER: g->gcroot[] is a GC root. */
|
||||||
/* NOBARRIER: g->mmname[] is a GC root. */
|
setgcref(g->gcroot[GCROOT_MMNAME+mm], obj2gco(s));
|
||||||
setgcref(g->mmname[i], obj2gco(s));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +61,7 @@ cTValue *lj_meta_lookup(lua_State *L, cTValue *o, MMS mm)
|
|||||||
else
|
else
|
||||||
mt = tabref(basemt_obj(G(L), o));
|
mt = tabref(basemt_obj(G(L), o));
|
||||||
if (mt) {
|
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)
|
if (mo)
|
||||||
return 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) \
|
#define lj_meta_fastg(g, mt, mm) \
|
||||||
((mt) == NULL ? NULL : ((mt)->nomm & (1u<<(mm))) ? NULL : \
|
((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)
|
#define lj_meta_fast(L, mt, mm) lj_meta_fastg(G(L), mt, mm)
|
||||||
|
|
||||||
/* C helpers for some instructions, called from assembler VM. */
|
/* 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. */
|
/* GC root IDs. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
GCROOT_MMNAME, /* Metamethod names. */
|
||||||
|
GCROOT_MMNAME_LAST = GCROOT_MMNAME + MM_MAX-1,
|
||||||
GCROOT_BASEMT, /* Metatables for base types. */
|
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_INPUT, /* Userdata for default I/O input file. */
|
||||||
GCROOT_IO_OUTPUT, /* Userdata for default I/O output file. */
|
GCROOT_IO_OUTPUT, /* Userdata for default I/O output file. */
|
||||||
GCROOT__MAX
|
GCROOT_MAX
|
||||||
} GCRootID;
|
} GCRootID;
|
||||||
|
|
||||||
#define basemt_it(g, it) ((g)->gcroot[GCROOT_BASEMT+~(it)])
|
#define basemt_it(g, it) ((g)->gcroot[GCROOT_BASEMT+~(it)])
|
||||||
#define basemt_obj(g, o) ((g)->gcroot[GCROOT_BASEMT+itypemap(o)])
|
#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 {
|
typedef struct GCState {
|
||||||
MSize total; /* Memory currently allocated. */
|
MSize total; /* Memory currently allocated. */
|
||||||
@ -595,8 +598,7 @@ typedef struct global_State {
|
|||||||
BCIns bc_cfunc_ext; /* Bytecode for external C function calls. */
|
BCIns bc_cfunc_ext; /* Bytecode for external C function calls. */
|
||||||
GCRef jit_L; /* Current JIT code lua_State or NULL. */
|
GCRef jit_L; /* Current JIT code lua_State or NULL. */
|
||||||
MRef jit_base; /* Current JIT code L->base. */
|
MRef jit_base; /* Current JIT code L->base. */
|
||||||
GCRef gcroot[GCROOT__MAX]; /* GC roots. */
|
GCRef gcroot[GCROOT_MAX]; /* GC roots. */
|
||||||
GCRef mmname[MM_MAX]; /* Array holding metamethod names. */
|
|
||||||
} global_State;
|
} global_State;
|
||||||
|
|
||||||
#define mainthread(g) (&gcref(g->mainthref)->th)
|
#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));
|
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 = strref(J2G(J)->mmname[mm]);
|
GCstr *mmstr = mmname_str(J2G(J), mm);
|
||||||
cTValue *mo = lj_tab_getstr(mt, mmstr);
|
cTValue *mo = lj_tab_getstr(mt, mmstr);
|
||||||
if (mo && !tvisnil(mo))
|
if (mo && !tvisnil(mo))
|
||||||
copyTV(J->L, &ix->mobjv, mo);
|
copyTV(J->L, &ix->mobjv, mo);
|
||||||
ix->mtv = mt;
|
ix->mtv = mt;
|
||||||
settabV(J->L, &mix.tabv, 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);
|
setstrV(J->L, &mix.keyv, mmstr);
|
||||||
mix.key = lj_ir_kstr(J, mmstr);
|
mix.key = lj_ir_kstr(J, mmstr);
|
||||||
mix.val = 0;
|
mix.val = 0;
|
||||||
@ -914,9 +912,9 @@ static int nommstr(jit_State *J, TRef key)
|
|||||||
if (tref_isstr(key)) {
|
if (tref_isstr(key)) {
|
||||||
if (tref_isk(key)) {
|
if (tref_isk(key)) {
|
||||||
GCstr *str = ir_kstr(IR(tref_ref(key)));
|
GCstr *str = ir_kstr(IR(tref_ref(key)));
|
||||||
uint32_t i;
|
uint32_t mm;
|
||||||
for (i = 0; i <= MM_FAST; i++)
|
for (mm = 0; mm <= MM_FAST; mm++)
|
||||||
if (strref(J2G(J)->mmname[i]) == str)
|
if (mmname_str(J2G(J), mm) == str)
|
||||||
return 0; /* MUST be one the fast metamethod names. */
|
return 0; /* MUST be one the fast metamethod names. */
|
||||||
} else {
|
} else {
|
||||||
return 0; /* Variable string key MAY be a metamethod name. */
|
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. */
|
/* Need to duplicate the hasmm check for the early guards. */
|
||||||
int hasmm = 0;
|
int hasmm = 0;
|
||||||
if (ix->idxchain && mt) {
|
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);
|
hasmm = mo && !tvisnil(mo);
|
||||||
}
|
}
|
||||||
if (hasmm)
|
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)) {
|
for (o = gcref(g->strhash[h & g->strmask]); o != NULL; o = gcnext(o)) {
|
||||||
GCstr *tso = gco2str(o);
|
GCstr *tso = gco2str(o);
|
||||||
if (tso->len == len && (memcmp(str, strdata(tso), len) == 0)) {
|
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. */
|
return tso; /* Return existing string. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user