瀏覽代碼

new function 'luaC_runtilstate' to advance GC until a "valid" state

Roberto Ierusalimschy 15 年之前
父節點
當前提交
a2a2abcba4
共有 4 個文件被更改,包括 35 次插入21 次删除
  1. 20 8
      lgc.c
  2. 8 9
      lgc.h
  3. 3 3
      lstring.c
  4. 4 1
      ltests.c

+ 20 - 8
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.62 2009/11/18 13:13:47 roberto Exp roberto $
+** $Id: lgc.c,v 2.63 2009/11/26 11:39:20 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -785,6 +785,21 @@ void luaC_step (lua_State *L) {
 }
 
 
+/*
+** advances the garbage collector until it reaches a "valid" state
+** (defined by the caller)
+*/
+void luaC_runtilstate (lua_State *L, int validstates) {
+  global_State *g = G(L);
+  while (!(g->gcstate & validstates))
+    singlestep(L);
+}
+
+
+/*
+** performs a full GC cycle; if "isememrgency", does not call
+** finalizers (which could change stack positions)
+*/
 void luaC_fullgc (lua_State *L, int isemergency) {
   global_State *g = G(L);
   lua_assert(g->gckind == KGC_NORMAL);
@@ -796,16 +811,13 @@ void luaC_fullgc (lua_State *L, int isemergency) {
     g->gcstate = GCSsweepstring;
   }
   /* finish any pending sweep phase */
-  while (issweep(g)) singlestep(L);
+  luaC_runtilstate(L, ~(GCSsweepstring | GCSsweep));
   markroot(L);  /* start a new collection */
   /* run collector up to finalizers */
-  while (g->gcstate != GCSfinalize)
-    singlestep(L);
+  luaC_runtilstate(L, GCSfinalize);
   g->gckind = KGC_NORMAL;
-  if (!isemergency) {  /* do not run finalizers during emergency GC */
-    while (g->gcstate != GCSpause)
-      singlestep(L);
-  }
+  if (!isemergency)   /* do not run finalizers during emergency GC */
+   luaC_runtilstate(L, ~GCSfinalize);
   g->GCthreshold = (g->totalbytes/100) * g->gcpause;
 }
 

+ 8 - 9
lgc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.23 2009/11/18 13:13:47 roberto Exp roberto $
+** $Id: lgc.h,v 2.24 2009/11/26 11:39:20 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -14,16 +14,14 @@
 /*
 ** Possible states of the Garbage Collector
 */
-#define GCSpause	0
-#define GCSpropagate	1
-#define GCSatomic	2
-#define GCSsweepstring	3
-#define GCSsweep	4
-#define GCSfinalize	5
+#define GCSpause	1
+#define GCSpropagate	2
+#define GCSatomic	4
+#define GCSsweepstring	8
+#define GCSsweep	16
+#define GCSfinalize	32
 
 
-#define issweep(g)  (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep)
-
 
 /*
 ** some useful bit tricks
@@ -98,6 +96,7 @@
 LUAI_FUNC void luaC_separateudata (lua_State *L, int all);
 LUAI_FUNC void luaC_freeallobjects (lua_State *L);
 LUAI_FUNC void luaC_step (lua_State *L);
+LUAI_FUNC void luaC_runtilstate (lua_State *L, int validstates);
 LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
 LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
 LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);

+ 3 - 3
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 2.12 2009/04/17 14:40:13 roberto Exp roberto $
+** $Id: lstring.c,v 2.13 2009/04/29 17:09:41 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -22,8 +22,8 @@
 void luaS_resize (lua_State *L, int newsize) {
   int i;
   stringtable *tb = &G(L)->strt;
-  if (G(L)->gcstate == GCSsweepstring)
-    return;  /* cannot resize during GC traverse */
+  /* cannot resize while GC is traversing strings */
+  luaC_runtilstate(L, ~GCSsweepstring);
   if (newsize > tb->size) {
     luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
     for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL;

+ 4 - 1
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.81 2009/12/01 16:49:48 roberto Exp roberto $
+** $Id: ltests.c,v 2.82 2009/12/10 18:21:28 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -167,6 +167,9 @@ void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
 ** =======================================================
 */
 
+#define issweep(g)  (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep)
+
+
 static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
   if (isdead(g,t)) return 0;
   if (g->gcstate == GCSpropagate)