Bläddra i källkod

Make metamethod names proper GC roots.

Mike Pall 15 år sedan
förälder
incheckning
ef0904e80b
12 ändrade filer med 26 tillägg och 29 borttagningar
  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. */
     }
   }