lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Friday 13, Roberto Ierusalimschy wrote:
> > BTW: I found another problem: luaX_setinput() calls next() which
> > in turn may call the reader function which in turn may run the GC.
> > But the chunkname string is still unanchored. It's only anchored
> > when open_func runs and anchors the prototype in the stack.

The attached patch includes the fix for this from Lua 5.2 as described by 
Roberto Ierusalimschy in his other e-mail.

>
> The problem may aslo arise if a program stops the collector and then
> goes on creating a lot of strings. This is not very smart of the part of
> the program, but the price can get very high. Maybe a solution would be
> not to stop resizing during a sweepstring phase. (The resize function
> could collect itself the dead strings, or it could advance the collector
> until it finishes that phase. But I am not sure if this is worth the
> extra complexity.)
>
> -- Roberto

The attached patch will do one step of the sweep strings phase of the GC from 
the string table resize function.  This will get the GC out of the sweep 
strings phase so that the string table can be resized.  Maybe it would be 
better to have it finish the whole sweep strings phase in the resize 
function, instead of just single stepping each time the resize function is 
called.

New strings should still be safe for premature collection since they will be 
marked with the current white color and not get collected during the sweep 
string phase.

I will update the Emergency GC patch to include these changes, even though it 
doesn't happen on this test case.

-- 
Robert G. Jakabosky
diff --git a/src/lgc.c b/src/lgc.c
index d9e0b78..89cafb5 100644
--- a/src/lgc.c
+++ b/src/lgc.c
@@ -552,6 +552,15 @@ static void atomic (lua_State *L) {
   g->estimate = g->totalbytes - udsize;  /* first estimate */
 }
 
+static void sweepstrstep (global_State *g, lua_State *L) {
+  lu_mem old = g->totalbytes;
+  sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
+  if (g->sweepstrgc >= g->strt.size)  /* nothing more to sweep? */
+    g->gcstate = GCSsweep;  /* end sweep-string phase */
+  lua_assert(old >= g->totalbytes);
+  g->estimate -= old - g->totalbytes;
+}
+
 
 static l_mem singlestep (lua_State *L) {
   global_State *g = G(L);
@@ -570,12 +579,7 @@ static l_mem singlestep (lua_State *L) {
       }
     }
     case GCSsweepstring: {
-      lu_mem old = g->totalbytes;
-      sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
-      if (g->sweepstrgc >= g->strt.size)  /* nothing more to sweep? */
-        g->gcstate = GCSsweep;  /* end sweep-string phase */
-      lua_assert(old >= g->totalbytes);
-      g->estimate -= old - g->totalbytes;
+      sweepstrstep(g, L);
       return GCSWEEPCOST;
     }
     case GCSsweep: {
@@ -633,6 +637,15 @@ void luaC_step (lua_State *L) {
 }
 
 
+int luaC_sweepstrgc (lua_State *L) {
+  global_State *g = G(L);
+  if (g->gcstate == GCSsweepstring) {
+    sweepstrstep(g, L);
+    return (g->gcstate == GCSsweepstring) ? 1 : 0;
+  }
+  return 0;
+}
+
 void luaC_fullgc (lua_State *L) {
   global_State *g = G(L);
   if (g->gcstate <= GCSpropagate) {
diff --git a/src/lgc.h b/src/lgc.h
index 5a8dc60..170fee2 100644
--- a/src/lgc.h
+++ b/src/lgc.h
@@ -101,6 +101,7 @@ LUAI_FUNC void luaC_callGCTM (lua_State *L);
 LUAI_FUNC void luaC_freeall (lua_State *L);
 LUAI_FUNC void luaC_step (lua_State *L);
 LUAI_FUNC void luaC_fullgc (lua_State *L);
+LUAI_FUNC int luaC_sweepstrgc (lua_State *L);
 LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
 LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
 LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
diff --git a/src/lparser.c b/src/lparser.c
index 1e2a9a8..31cc146 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -383,8 +383,11 @@ static void close_func (LexState *ls) {
 Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
   struct LexState lexstate;
   struct FuncState funcstate;
+  TString *tname = luaS_new(L, name);
+  setsvalue2s(L, L->top, tname);  /* protect name */
+  incr_top(L);
   lexstate.buff = buff;
-  luaX_setinput(L, &lexstate, z, luaS_new(L, name));
+  luaX_setinput(L, &lexstate, z, tname);
   open_func(&lexstate, &funcstate);
   funcstate.f->is_vararg = VARARG_ISVARARG;  /* main func. is always vararg */
   luaX_next(&lexstate);  /* read first token */
diff --git a/src/lstring.c b/src/lstring.c
index 4911315..fdb6f6a 100644
--- a/src/lstring.c
+++ b/src/lstring.c
@@ -23,7 +23,7 @@ void luaS_resize (lua_State *L, int newsize) {
   GCObject **newhash;
   stringtable *tb;
   int i;
-  if (G(L)->gcstate == GCSsweepstring)
+  if (luaC_sweepstrgc(L))
     return;  /* cannot resize during GC traverse */
   newhash = luaM_newvector(L, newsize, GCObject *);
   tb = &G(L)->strt;