Explorar o código

better way to control open upvalues

Roberto Ierusalimschy %!s(int64=21) %!d(string=hai) anos
pai
achega
a4e1230f95
Modificáronse 5 ficheiros con 159 adicións e 134 borrados
  1. 12 10
      lfunc.c
  2. 129 107
      lgc.c
  3. 3 2
      lgc.h
  4. 1 2
      lobject.h
  5. 14 13
      lstate.c

+ 12 - 10
lfunc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
+** $Id: lfunc.c,v 2.2 2004/02/16 19:09:52 roberto Exp roberto $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
@@ -34,6 +34,7 @@ Closure *luaF_newLclosure (lua_State *L, int nelems, TValue *e) {
   c->l.isC = 0;
   c->l.g = *e;
   c->l.nupvalues = cast(lu_byte, nelems);
+  while (nelems--) c->l.upvals[nelems] = NULL;
   return c;
 }
 
@@ -67,17 +68,18 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
 
 void luaF_close (lua_State *L, StkId level) {
   UpVal *uv;
+  global_State *g = G(L);
   while ((uv = ngcotouv(L->openupval)) != NULL && uv->v >= level) {
-    lu_byte mark = uv->marked;
-    lua_assert(!isblack(obj2gco(uv)));
-    setobj(L, &uv->value, uv->v);
-    luaC_barrier(L, uv, uv->v);
-    uv->v = &uv->value;  /* now current value lives here */
+    GCObject *o = obj2gco(uv);
+    lua_assert(!isblack(o));
     L->openupval = uv->next;  /* remove from `open' list */
-    luaC_link(L, obj2gco(uv), LUA_TUPVAL);
-    if (G(L)->gcstate == GCSpropagate)
-      uv->marked = mark;  /* preserve previous mark */
-    lua_assert(!isdead(G(L), obj2gco(uv)));
+    if (isdead(g, o))
+      luaM_freelem(L, uv);  /* free upvalue */
+    else {
+      setobj(L, &uv->value, uv->v);
+      uv->v = &uv->value;  /* now current value lives here */
+      luaC_linkupval(L, uv);  /* link upvalue into `gcroot' list */
+    }
   }
 }
 

+ 129 - 107
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.3 2004/02/16 19:09:52 roberto Exp roberto $
+** $Id: lgc.c,v 2.4 2004/03/09 17:34:35 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -27,15 +27,16 @@
 #define GCSWEEPCOST	sizeof(TValue)
 
 
-#define gray2black(x)	setbit((x)->gch.marked, BLACKBIT)
+#define FIXEDMASK	bitmask(FIXEDBIT)
 
 #define maskmarks \
 	cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT)))
+
 #define makewhite(g,x)	\
    ((x)->gch.marked = ((x)->gch.marked & maskmarks) | g->currentwhite)
 
-#define isgray(x)	(!isblack(x) && !iswhite(x))
 #define white2gray(x)	reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
+#define gray2black(x)	setbit((x)->gch.marked, BLACKBIT)
 #define black2gray(x)	resetbit((x)->gch.marked, BLACKBIT)
 
 #define stringmark(s)	reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
@@ -58,47 +59,10 @@
 
 
 
-
-/*
-** computes the size of a collectible object
-*/
-static size_t objsize (GCObject *o) {
-  switch (o->gch.tt) {
-    case LUA_TSTRING: {
-      TString *ts = rawgco2ts(o);
-      return sizestring(ts->tsv.len);
-    }
-    case LUA_TUSERDATA: {
-      Udata *u = rawgco2u(o);
-      return sizeudata(u->uv.len);
-    }
-    case LUA_TTABLE: {
-      Table *h = gco2h(o);
-      return sizeof(Table) + sizeof(TValue) * h->sizearray +
-                             sizeof(Node) * sizenode(h);
-    }
-    case LUA_TUPVAL:
-      return sizeof(UpVal);
-    case LUA_TFUNCTION: {
-      Closure *cl = gco2cl(o);
-      return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
-                           sizeLclosure(cl->l.nupvalues);
-    }
-    case LUA_TTHREAD: {
-      lua_State *th = gco2th(o);
-      return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
-             sizeof(CallInfo) * th->size_ci;
-    }
-    case LUA_TPROTO: {
-      Proto *p = gco2p(o);
-      return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
-             sizeof(Proto *) * p->sizep + sizeof(TValue) * p->sizek + 
-             sizeof(int) * p->sizelineinfo + sizeof(LocVar) * p->sizelocvars +
-             sizeof(TString *) * p->sizeupvalues;
-    }
-  }
-  lua_assert(0);
-  return 0;  /* to avoid warnings */
+static void removeentry (Node *n) {
+  setnilvalue(gval(n));  /* remove corresponding value ... */
+  if (iscollectable(gkey(n)))
+    setttype(gkey(n), LUA_TNONE);  /* dead key; remove it */
 }
 
 
@@ -115,29 +79,36 @@ static void reallymarkobject (global_State *g, GCObject *o) {
       if (mt) markobject(g, mt);
       return;
     }
+    case LUA_TUPVAL: {
+      UpVal *uv = gco2uv(o);
+      if (uv->v == &uv->value) {  /* closed? */
+        markvalue(g, uv->v);
+        gray2black(o);
+      }
+      return;
+    }
     case LUA_TFUNCTION: {
       gco2cl(o)->c.gclist = g->gray;
+      g->gray = o;
       break;
     }
     case LUA_TTABLE: {
       gco2h(o)->gclist = g->gray;
+      g->gray = o;
       break;
     }
     case LUA_TTHREAD: {
       gco2th(o)->gclist = g->gray;
+      g->gray = o;
       break;
     }
     case LUA_TPROTO: {
       gco2p(o)->gclist = g->gray;
-      break;
-    }
-    case LUA_TUPVAL: {
-      gco2uv(o)->gclist = g->gray;
+      g->gray = o;
       break;
     }
     default: lua_assert(0);
   }
-  g->gray = o;  /* finish list linking */
 }
 
 
@@ -157,8 +128,7 @@ size_t luaC_separateudata (lua_State *L, int all) {
   GCObject *curr;
   GCObject *collected = NULL;  /* to collect udata with gc event */
   GCObject **lastcollected = &collected;
-  while ((curr = *p) != NULL) {
-    lua_assert(curr->gch.tt == LUA_TUSERDATA);
+  while ((curr = *p)->gch.tt == LUA_TUSERDATA) {
     if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
       p = &curr->gch.next;  /* don't bother with them */
     else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
@@ -174,6 +144,7 @@ size_t luaC_separateudata (lua_State *L, int all) {
       lastcollected = &curr->gch.next;
     }
   }
+  lua_assert(curr == obj2gco(G(L)->mainthread));
   /* insert collected udata with gc event into `tmudata' list */
   *lastcollected = G(L)->tmudata;
   G(L)->tmudata = collected;
@@ -210,7 +181,9 @@ static int traversetable (global_State *g, Table *h) {
   i = sizenode(h);
   while (i--) {
     Node *n = gnode(h, i);
-    if (!ttisnil(gval(n))) {
+    if (ttisnil(gval(n)))
+      removeentry(n);  /* remove empty entries */
+    else {
       lua_assert(!ttisnil(gkey(n)));
       if (!weakkey) markvalue(g, gkey(n));
       if (!weakvalue) markvalue(g, gval(n));
@@ -274,20 +247,20 @@ static void checkstacksizes (lua_State *L, StkId max) {
 }
 
 
-static void traversestack (global_State *g, lua_State *L1) {
+static void traversestack (global_State *g, lua_State *l) {
   StkId o, lim;
   CallInfo *ci;
-  markvalue(g, gt(L1));
-  lim = L1->top;
-  for (ci = L1->base_ci; ci <= L1->ci; ci++) {
-    lua_assert(ci->top <= L1->stack_last);
+  markvalue(g, gt(l));
+  lim = l->top;
+  for (ci = l->base_ci; ci <= l->ci; ci++) {
+    lua_assert(ci->top <= l->stack_last);
     if (lim < ci->top) lim = ci->top;
   }
-  for (o = L1->stack; o < L1->top; o++)
+  for (o = l->stack; o < l->top; o++)
     markvalue(g, o);
   for (; o <= lim; o++)
     setnilvalue(o);
-  checkstacksizes(L1, lim);
+  checkstacksizes(l, lim);
 }
 
 
@@ -306,12 +279,16 @@ static l_mem propagatemarks (global_State *g, l_mem lim) {
         g->gray = h->gclist;
         if (traversetable(g, h))  /* table is weak? */
           black2gray(o);  /* keep it gray */
+        lim -= sizeof(Table) + sizeof(TValue) * h->sizearray +
+                               sizeof(Node) * sizenode(h);
         break;
       }
       case LUA_TFUNCTION: {
         Closure *cl = gco2cl(o);
         g->gray = cl->c.gclist;
         traverseclosure(g, cl);
+        lim -= (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
+                             sizeLclosure(cl->l.nupvalues);
         break;
       }
       case LUA_TTHREAD: {
@@ -321,29 +298,24 @@ static l_mem propagatemarks (global_State *g, l_mem lim) {
         g->grayagain = o;
         black2gray(o);
         traversestack(g, th);
+        lim -= sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+                                   sizeof(CallInfo) * th->size_ci;
         break;
       }
       case LUA_TPROTO: {
         Proto *p = gco2p(o);
         g->gray = p->gclist;
         traverseproto(g, p);
-        break;
-      }
-      case LUA_TUPVAL: {
-        UpVal *uv = gco2uv(o);
-        g->gray = uv->gclist;
-        if (uv->v != &uv->value) {  /* open? */
-          uv->gclist = g->grayagain;
-          g->grayagain = o;
-          black2gray(o);
-        }
-        else
-          markvalue(g, &uv->value);
+        lim -= sizeof(Proto) + sizeof(Instruction) * p->sizecode +
+                               sizeof(Proto *) * p->sizep +
+                               sizeof(TValue) * p->sizek + 
+                               sizeof(int) * p->sizelineinfo +
+                               sizeof(LocVar) * p->sizelocvars +
+                               sizeof(TString *) * p->sizeupvalues;
         break;
       }
       default: lua_assert(0);
     }
-    lim -= objsize(o);
     if (lim <= 0) return lim;
   }
   return lim;
@@ -368,13 +340,6 @@ static int iscleared (const TValue *o, int iskey) {
 }
 
 
-static void removekey (Node *n) {
-  setnilvalue(gval(n));  /* remove corresponding value ... */
-  if (iscollectable(gkey(n)))
-    setttype(gkey(n), LUA_TNONE);  /* dead key; remove it */
-}
-
-
 /*
 ** clear collected entries from weaktables
 */
@@ -396,7 +361,7 @@ static void cleartable (GCObject *l) {
       Node *n = gnode(h, i);
       if (!ttisnil(gval(n)) &&  /* non-empty entry? */
           (iscleared(gkey(n), 1) || iscleared(gval(n), 0)))
-        removekey(n);  /* remove entry from table */
+        removeentry(n);  /* remove entry from table */
     }
     l = h->gclist;
   }
@@ -427,22 +392,28 @@ static void freeobj (lua_State *L, GCObject *o) {
 }
 
 
-static void sweepupvalues (global_State *g, lua_State *L1) {
+static void sweepupvalues (global_State *g, lua_State *l) {
   GCObject *curr;
-  for (curr = L1->openupval; curr != NULL; curr = curr->gch.next)
+  for (curr = l->openupval; curr != NULL; curr = curr->gch.next)
     makewhite(g, curr);
 }
 
 
-static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
+/*
+** macros to test dead bit and optionally the fix bit
+*/
+#define makedeadmask(g,kf)	(otherwhite(g) | ((kf) ? FIXEDMASK : 0))
+#define notdead(mark,mask)	((((mark) ^ FIXEDMASK) & mask) != mask)
+
+
+static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed,
                              l_mem *plim) {
   GCObject *curr;
   global_State *g = G(L);
   l_mem lim = *plim;
-  int dead = otherwhite(g);
+  int deadmask = makedeadmask(g, keepfixed);
   while ((curr = *p) != NULL) {
-    int mark = curr->gch.marked;
-    if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
+    if (notdead(curr->gch.marked, deadmask)) {
       makewhite(g, curr);
       if (curr->gch.tt == LUA_TTHREAD)
         sweepupvalues(g, gco2th(curr));
@@ -450,6 +421,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
       lim -= GCSWEEPCOST;
     }
     else {
+      lua_assert(iswhite(curr));
       *p = curr->gch.next;
       if (curr == g->rootgc)  /* is the first element of the list? */
         g->rootgc = curr->gch.next;  /* adjust first */
@@ -463,22 +435,22 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
 }
 
 
-static l_mem sweepstrings (lua_State *L, int all, l_mem lim) {
+static l_mem sweepstrings (lua_State *L, int keepfixed, l_mem lim) {
   int i;
   global_State *g = G(L);
-  int dead = otherwhite(g);
+  int deadmask = makedeadmask(g, keepfixed);
   for (i = g->sweepstrgc; i < g->strt.size; i++) {  /* for each list */
     GCObject *curr;
     GCObject **p = &G(L)->strt.hash[i];
     while ((curr = *p) != NULL) {
-      int mark = curr->gch.marked;
       lu_mem size = sizestring(gco2ts(curr)->len);
-      if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
+      if (notdead(curr->gch.marked, deadmask)) {
         makewhite(g, curr);
         lua_assert(iswhite(curr) && !isdead(g, curr));
         p = &curr->gch.next;
       }
       else {
+        lua_assert(iswhite(curr));
         g->strt.nuse--;
         *p = curr->gch.next;
         luaM_free(L, curr, size);
@@ -538,10 +510,19 @@ void luaC_callGCTM (lua_State *L) {
 
 
 void luaC_sweepall (lua_State *L) {
+  global_State *g = G(L);
   l_mem dummy = MAXLMEM;
-  G(L)->sweepstrgc = 0;
-  sweepstrings(L, 1, dummy);
-  sweeplist(L, &G(L)->rootgc, 1, &dummy);
+  /* finish (occasional) current sweep */
+  markobject(g, g->mainthread);  /* cannot collect main thread */
+  sweepstrings(L, 0, MAXLMEM);
+  sweeplist(L, &g->rootgc, 0, &dummy);
+  /* do a whole new sweep */
+  markobject(g, g->mainthread);  /* cannot collect main thread */
+  g->currentwhite = otherwhite(g);
+  g->sweepgc = &g->rootgc;
+  g->sweepstrgc = 0;
+  sweepstrings(L, 0, MAXLMEM);
+  sweeplist(L, &g->rootgc, 0, &dummy);
 }
 
 
@@ -559,12 +540,30 @@ static void markroot (lua_State *L) {
 }
 
 
+static void remarkupvals (global_State *g) {
+  GCObject *o;
+  for (o = obj2gco(g->mainthread); o; o = o->gch.next) {
+    if (iswhite(o)) {
+      GCObject *curr;
+      for (curr = gco2th(o)->openupval; curr != NULL; curr = curr->gch.next) {
+        if (isgray(curr))
+          markvalue(g, gco2uv(curr)->v);
+      }
+    }
+  }
+}
+
+
 static void atomic (lua_State *L) {
   global_State *g = G(L);
   lua_assert(g->gray == NULL);
+  /* remark occasional upvalues of (maybe) dead threads */
+  remarkupvals(g);
   /* remark weak tables */
   g->gray = g->weak;
   g->weak = NULL;
+  lua_assert(!iswhite(obj2gco(g->mainthread)));
+  markobject(g, L);  /* mark running thread */
   propagatemarks(g, MAXLMEM);
   /* remark gray again */
   g->gray = g->grayagain;
@@ -576,8 +575,6 @@ static void atomic (lua_State *L) {
   cleartable(g->weak);  /* remove collected objects from weak tables */
   /* flip current white */
   g->currentwhite = otherwhite(g);
-  g->sweepgc = &g->rootgc;
-  g->sweepstrgc = 0;
   g->gcstate = GCSsweepstring;
 }
 
@@ -587,38 +584,41 @@ static l_mem singlestep (lua_State *L, l_mem lim) {
   switch (g->gcstate) {
     case GCSpropagate: {
       if (g->gray)
-        return propagatemarks(g, lim);
+        lim = propagatemarks(g, lim);
       else {  /* no more `gray' objects */
         atomic(L);  /* finish mark phase */
-        return 0;
+        lim = 0;
       }
+      break;
     }
     case GCSsweepstring: {
-      lim = sweepstrings(L, 0, lim);
+      lim = sweepstrings(L, 1, lim);
       if (g->sweepstrgc >= g->strt.size) {  /* nothing more to sweep? */
         g->sweepstrgc = 0;
         g->gcstate = GCSsweep;  /* end sweep-string phase */
       }
-      return lim;
+      break;
     }
     case GCSsweep: {
-      g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim);
+      g->sweepgc = sweeplist(L, g->sweepgc, 1, &lim);
       if (*g->sweepgc == NULL) {  /* nothing more to sweep? */
         checkSizes(L);
-        sweepupvalues(g, g->mainthread);
+        g->sweepgc = &g->rootgc;
         g->gcstate = GCSfinalize;  /* end sweep phase */
       }
-      return lim;
+      break;
     }
     case GCSfinalize: {
       if (g->tmudata)
         GCTM(L);
       else  /* no more `udata' to finalize */
         markroot(L);  /* may restart collection */
-      return 0;
+      lim = 0;
+      break;
     }
-    default: lua_assert(0); return 0;  /* to avoid warnings */
+    default: lua_assert(0);
   }
+  return lim;
 }
 
 
@@ -635,11 +635,15 @@ void luaC_step (lua_State *L) {
 
 void luaC_fullgc (lua_State *L) {
   global_State *g = G(L);
-  while (g->gcstate != GCSfinalize) singlestep(L, MAXLMEM);
+  while (g->gcstate != GCSfinalize) {
+    singlestep(L, MAXLMEM);
+  }
   markroot(L);
-  while (g->gcstate != GCSfinalize) singlestep(L, MAXLMEM);
-  luaC_callGCTM(L);  /* call finalizers */
+  while (g->gcstate != GCSfinalize) {
+    singlestep(L, MAXLMEM);
+  }
   g->GCthreshold = g->nblocks + GCSTEPSIZE;
+  luaC_callGCTM(L);  /* call finalizers */
 }
 
 
@@ -662,3 +666,21 @@ void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
   o->gch.tt = tt;
 }
 
+
+void luaC_linkupval (lua_State *L, UpVal *uv) {
+  global_State *g = G(L);
+  GCObject *o = obj2gco(uv);
+  o->gch.next = g->rootgc;  /* link upvalue into `rootgc' list */
+  g->rootgc = o;
+  if (isgray(o)) { 
+    if (g->gcstate == GCSpropagate) {
+      gray2black(o);  /* closed upvalues need barrier */
+      luaC_barrier(L, uv, uv->v);
+    }
+    else {  /* sweep phase: sweep it (turning it into white) */
+      makewhite(g, o);
+      lua_assert(g->gcstate != GCSfinalize);
+    }
+  }
+}
+

+ 3 - 2
lgc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.3 2004/02/16 19:09:52 roberto Exp roberto $
+** $Id: lgc.h,v 2.4 2004/03/09 17:34:35 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -58,7 +58,7 @@
 
 #define iswhite(x)      test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
 #define isblack(x)      testbit((x)->gch.marked, BLACKBIT)
-
+#define isgray(x)	(!isblack(x) && !iswhite(x))
 
 #define otherwhite(g)	(g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT))
 #define isdead(g,v)	((v)->gch.marked & otherwhite(g))
@@ -87,6 +87,7 @@ void luaC_sweepall (lua_State *L);
 void luaC_step (lua_State *L);
 void luaC_fullgc (lua_State *L);
 void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
+void luaC_linkupval (lua_State *L, UpVal *uv);
 void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
 
 

+ 1 - 2
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 2.2 2004/02/16 19:09:52 roberto Exp roberto $
+** $Id: lobject.h,v 2.3 2004/02/20 16:01:05 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -263,7 +263,6 @@ typedef struct LocVar {
 
 typedef struct UpVal {
   CommonHeader;
-  GCObject *gclist;
   TValue *v;  /* points to stack or to its own value */
   TValue value;  /* the value (when closed) */
 } UpVal;

+ 14 - 13
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 2.2 2003/12/12 18:29:34 roberto Exp roberto $
+** $Id: lstate.c,v 2.3 2004/02/16 19:09:52 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -93,7 +93,10 @@ static void f_luaopen (lua_State *L, void *ud) {
 }
 
 
-static void preinit_state (lua_State *L) {
+static void preinit_state (lua_State *L, global_State *g) {
+  L->l_G = g;
+  L->tt = LUA_TTHREAD;
+  L->marked = luaC_white(g);
   L->stack = NULL;
   L->stacksize = 0;
   L->errorJmp = NULL;
@@ -116,7 +119,7 @@ static void close_state (lua_State *L) {
   global_State *g = G(L);
   luaF_close(L, L->stack);  /* close all upvalues for this thread */
   luaC_sweepall(L);  /* collect all elements */
-  lua_assert(g->rootgc == NULL);
+  lua_assert(g->rootgc == obj2gco(L));
   luaS_freeall(L);
   luaZ_freebuffer(L, &g->buff);
   freestack(L, L);
@@ -127,9 +130,9 @@ static void close_state (lua_State *L) {
 
 lua_State *luaE_newthread (lua_State *L) {
   lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
-  luaC_link(L, obj2gco(L1), LUA_TTHREAD);
-  preinit_state(L1);
-  L1->l_G = L->l_G;
+  L1->next = L->next;  /* link new thread after `L' */
+  L->next = obj2gco(L1);
+  preinit_state(L1, G(L));
   stack_init(L1, L);  /* init stack */
   setobj2n(L, gt(L1), gt(L));  /* share table of globals */
   lua_assert(iswhite(obj2gco(L1)));
@@ -152,11 +155,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   if (l == NULL) return NULL;
   L = tostate(l);
   g = &((LG *)L)->g;
-  L->tt = LUA_TTHREAD;
-  L->marked = 0;
-  L->next = L->gclist = NULL;
-  preinit_state(L);
-  L->l_G = g;
+  L->next = NULL;
+  g->currentwhite = bitmask(WHITE0BIT);
+  preinit_state(L, g);
   g->realloc = f;
   g->ud = ud;
   g->mainthread = L;
@@ -168,9 +169,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   luaZ_initbuffer(L, &g->buff);
   g->panic = NULL;
   g->gcstate = GCSfinalize;
-  g->rootgc = NULL;
+  g->rootgc = obj2gco(L);
   g->sweepstrgc = 0;
-  g->currentwhite = bitmask(WHITE0BIT);
+  g->sweepgc = &g->rootgc;
   g->firstudata = NULL;
   g->gray = NULL;
   g->grayagain = NULL;