Browse Source

Make metamethod names proper GC roots.

Mike Pall 15 năm trước cách đây
mục cha
commit
ef0904e80b
12 tập tin đã thay đổi với 26 bổ sung29 xóa
  1. 1 1
      src/buildvm_x64.h
  2. 1 1
      src/buildvm_x64win.h
  3. 1 1
      src/buildvm_x86.dasc
  4. 1 1
      src/buildvm_x86.h
  5. 1 4
      src/lib_string.c
  6. 1 1
      src/lj_err.c
  7. 1 1
      src/lj_gc.c
  8. 5 6
      src/lj_meta.c
  9. 1 1
      src/lj_meta.h
  10. 6 4
      src/lj_obj.h
  11. 5 7
      src/lj_record.c
  12. 2 1
      src/lj_str.c

+ 1 - 1
src/buildvm_x64.h

@@ -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);

+ 1 - 1
src/buildvm_x64win.h

@@ -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);

+ 1 - 1
src/buildvm_x86.dasc

@@ -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

+ 1 - 1
src/buildvm_x86.h

@@ -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));

+ 1 - 4
src/lib_string.c

@@ -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;
 }

+ 1 - 1
src/lj_err.c

@@ -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;

+ 1 - 1
src/lj_gc.c

@@ -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]));
 }

+ 5 - 6
src/lj_meta.c

@@ -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;
   }

+ 1 - 1
src/lj_meta.h

@@ -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. */

+ 6 - 4
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)

+ 5 - 7
src/lj_record.c

@@ -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)

+ 2 - 1
src/lj_str.c

@@ -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. */
     }
   }