瀏覽代碼

First criteria for shifts minor<->major

Roberto Ierusalimschy 1 年之前
父節點
當前提交
925fe8a0f2
共有 8 個文件被更改,包括 187 次插入128 次删除
  1. 14 11
      lapi.c
  2. 7 6
      lbaselib.c
  3. 55 26
      lgc.c
  4. 26 22
      lgc.h
  5. 2 1
      lstate.c
  6. 5 4
      lstate.h
  7. 1 1
      lua.c
  8. 77 57
      manual/manual.of

+ 14 - 11
lapi.c

@@ -1204,26 +1204,29 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
       break;
       break;
     }
     }
     case LUA_GCGEN: {
     case LUA_GCGEN: {
-      unsigned int minormul = va_arg(argp, unsigned int);
-      unsigned int majormul = va_arg(argp, unsigned int);
+      int minormul = va_arg(argp, int);
+      int minormajor = va_arg(argp, int);
+      int majorminor = va_arg(argp, int);
       res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
       res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
-      if (minormul != 0)
+      if (minormul >= 0)
         setgcparam(g, genminormul, minormul);
         setgcparam(g, genminormul, minormul);
-      if (majormul != 0)
-        setgcparam(g, genmajormul, majormul);
+      if (minormajor >= 0)
+        setgcparam(g, minormajor, minormajor);
+      if (majorminor >= 0)
+        setgcparam(g, majorminor, majorminor);
       luaC_changemode(L, KGC_GENMINOR);
       luaC_changemode(L, KGC_GENMINOR);
       break;
       break;
     }
     }
     case LUA_GCINC: {
     case LUA_GCINC: {
-      unsigned int pause = va_arg(argp, unsigned int);
-      unsigned int stepmul = va_arg(argp, unsigned int);
-      unsigned int stepsize = va_arg(argp, unsigned int);
+      int pause = va_arg(argp, int);
+      int stepmul = va_arg(argp, int);
+      int stepsize = va_arg(argp, int);
       res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
       res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
-      if (pause != 0)
+      if (pause >= 0)
         setgcparam(g, gcpause, pause);
         setgcparam(g, gcpause, pause);
-      if (stepmul != 0)
+      if (stepmul >= 0)
         setgcparam(g, gcstepmul, stepmul);
         setgcparam(g, gcstepmul, stepmul);
-      if (stepsize != 0)
+      if (stepsize >= 0)
         g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
         g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
                                                       : log2maxs(l_obj);
                                                       : log2maxs(l_obj);
       luaC_changemode(L, KGC_INC);
       luaC_changemode(L, KGC_INC);

+ 7 - 6
lbaselib.c

@@ -224,14 +224,15 @@ static int luaB_collectgarbage (lua_State *L) {
       return 1;
       return 1;
     }
     }
     case LUA_GCGEN: {
     case LUA_GCGEN: {
-      int minormul = (int)luaL_optinteger(L, 2, 0);
-      int majormul = (int)luaL_optinteger(L, 3, 0);
-      return pushmode(L, lua_gc(L, o, minormul, majormul));
+      int minormul = (int)luaL_optinteger(L, 2, -1);
+      int majorminor = (int)luaL_optinteger(L, 3, -1);
+      int minormajor = (int)luaL_optinteger(L, 4, -1);
+      return pushmode(L, lua_gc(L, o, minormul, majorminor, minormajor));
     }
     }
     case LUA_GCINC: {
     case LUA_GCINC: {
-      int pause = (int)luaL_optinteger(L, 2, 0);
-      int stepmul = (int)luaL_optinteger(L, 3, 0);
-      int stepsize = (int)luaL_optinteger(L, 4, 0);
+      int pause = (int)luaL_optinteger(L, 2, -1);
+      int stepmul = (int)luaL_optinteger(L, 3, -1);
+      int stepsize = (int)luaL_optinteger(L, 4, -1);
       return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize));
       return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize));
     }
     }
     default: {
     default: {

+ 55 - 26
lgc.c

@@ -1205,20 +1205,21 @@ static void correctgraylists (global_State *g) {
 /*
 /*
 ** Mark black 'OLD1' objects when starting a new young collection.
 ** Mark black 'OLD1' objects when starting a new young collection.
 ** Gray objects are already in some gray list, and so will be visited in
 ** Gray objects are already in some gray list, and so will be visited in
-** the atomic step. The counter 'GCmajorminor' keeps how many objects to
-** become old before a major collection.
+** the atomic step. Returns the number of objects that became old.
 */
 */
-static void markold (global_State *g, GCObject *from, GCObject *to) {
+static l_obj markold (global_State *g, GCObject *from, GCObject *to) {
   GCObject *p;
   GCObject *p;
+  l_obj count = 0;
   for (p = from; p != to; p = p->next) {
   for (p = from; p != to; p = p->next) {
     if (getage(p) == G_OLD1) {
     if (getage(p) == G_OLD1) {
       lua_assert(!iswhite(p));
       lua_assert(!iswhite(p));
       setage(p, G_OLD);  /* now they are old */
       setage(p, G_OLD);  /* now they are old */
-      g->GCmajorminor--;  /* one more old object */
+      count++;  /* one more old object */
       if (isblack(p))
       if (isblack(p))
         reallymarkobject(g, p);
         reallymarkobject(g, p);
     }
     }
   }
   }
+  return count;
 }
 }
 
 
 
 
@@ -1240,7 +1241,7 @@ static void finishgencycle (lua_State *L, global_State *g) {
 */
 */
 static void atomic2major (lua_State *L, global_State *g) {
 static void atomic2major (lua_State *L, global_State *g) {
   l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
   l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
-  g->GCmajorminor = gettotalobjs(g);
+  g->GCmajorminor = g->marked;  /* number of live objects */
   g->gckind = KGC_GENMAJOR;
   g->gckind = KGC_GENMAJOR;
   g->reallyold = g->old1 = g->survival = NULL;
   g->reallyold = g->old1 = g->survival = NULL;
   g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
   g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
@@ -1249,30 +1250,54 @@ static void atomic2major (lua_State *L, global_State *g) {
 }
 }
 
 
 
 
+/*
+** Decide whether to shift to major mode. It tests two conditions:
+** 1) Whether the number of added old objects in this collection is more
+** than half the number of new objects. ("step" is the number of objects
+** created between minor collections. Except for forward barriers, it
+** is the maximum number of objects that can become old in each minor
+** collection.)
+** 2) Whether the accumulated number of added old objects is larger
+** than 'minormajor'% of the number of lived objects after the last
+** major collection. (That percentage is computed in 'limit'.)
+*/
+static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) {
+  l_obj step = applygcparam(g, genminormul, g->GCmajorminor);
+  l_obj limit = applygcparam(g, minormajor, g->GCmajorminor);
+//printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g));
+  if (addedold1 >= (step >> 1) || g->marked >= limit) {
+    atomic2major(L, g);  /* go to major mode */
+    return 1;
+  }
+  return 0;  /* stay in minor mode */
+}
+
 /*
 /*
 ** Does a young collection. First, mark 'OLD1' objects. Then does the
 ** Does a young collection. First, mark 'OLD1' objects. Then does the
 ** atomic step. Then, check whether to continue in minor mode. If so,
 ** atomic step. Then, check whether to continue in minor mode. If so,
 ** sweep all lists and advance pointers. Finally, finish the collection.
 ** sweep all lists and advance pointers. Finally, finish the collection.
 */
 */
 static void youngcollection (lua_State *L, global_State *g) {
 static void youngcollection (lua_State *L, global_State *g) {
+  l_obj addedold1 = 0;
+  l_obj marked = g->marked;  /* preserve 'g->marked' */
   GCObject **psurvival;  /* to point to first non-dead survival object */
   GCObject **psurvival;  /* to point to first non-dead survival object */
   GCObject *dummy;  /* dummy out parameter to 'sweepgen' */
   GCObject *dummy;  /* dummy out parameter to 'sweepgen' */
   lua_assert(g->gcstate == GCSpropagate);
   lua_assert(g->gcstate == GCSpropagate);
-  g->marked = 0;
   if (g->firstold1) {  /* are there regular OLD1 objects? */
   if (g->firstold1) {  /* are there regular OLD1 objects? */
-    markold(g, g->firstold1, g->reallyold);  /* mark them */
+    addedold1 += markold(g, g->firstold1, g->reallyold);  /* mark them */
     g->firstold1 = NULL;  /* no more OLD1 objects (for now) */
     g->firstold1 = NULL;  /* no more OLD1 objects (for now) */
   }
   }
-  markold(g, g->finobj, g->finobjrold);
-  markold(g, g->tobefnz, NULL);
+  addedold1 += markold(g, g->finobj, g->finobjrold);
+  addedold1 += markold(g, g->tobefnz, NULL);
+
+  atomic(L);  /* will lose 'g->marked' */
 
 
-  atomic(L);
+  /* keep total number of added old1 objects */
+  g->marked = marked + addedold1;
 
 
   /* decide whether to shift to major mode */
   /* decide whether to shift to major mode */
-  if (g->GCmajorminor <= 0) {  /* ?? */
-    atomic2major(L, g);  /* go to major mode */
+  if (checkminormajor(L, g, addedold1))
     return;  /* nothing else to be done here */
     return;  /* nothing else to be done here */
-  }
 
 
   /* sweep nursery and get a pointer to its last live element */
   /* sweep nursery and get a pointer to its last live element */
   g->gcstate = GCSswpallgc;
   g->gcstate = GCSswpallgc;
@@ -1319,7 +1344,8 @@ static void atomic2gen (lua_State *L, global_State *g) {
   sweep2old(L, &g->tobefnz);
   sweep2old(L, &g->tobefnz);
 
 
   g->gckind = KGC_GENMINOR;
   g->gckind = KGC_GENMINOR;
-  g->GCmajorminor = applygcparam(g, genmajormul, g->marked);
+  g->GCmajorminor = g->marked;  /* "base" for number of objects */
+  g->marked = 0;  /* to count the number of added old1 objects */
   finishgencycle(L, g);
   finishgencycle(L, g);
 }
 }
 
 
@@ -1329,7 +1355,7 @@ static void atomic2gen (lua_State *L, global_State *g) {
 ** total number of objects grows 'genminormul'%.
 ** total number of objects grows 'genminormul'%.
 */
 */
 static void setminordebt (global_State *g) {
 static void setminordebt (global_State *g) {
-  luaE_setdebt(g, applygcparam(g, genminormul, gettotalobjs(g)));
+  luaE_setdebt(g, applygcparam(g, genminormul, g->GCmajorminor));
 }
 }
 
 
 
 
@@ -1369,13 +1395,11 @@ static void enterinc (global_State *g) {
 */
 */
 void luaC_changemode (lua_State *L, int newmode) {
 void luaC_changemode (lua_State *L, int newmode) {
   global_State *g = G(L);
   global_State *g = G(L);
+  if (g->gckind == KGC_GENMAJOR)  /* doing major collections? */
+    g->gckind = KGC_INC;  /* already incremental but in name */
   if (newmode != g->gckind) {  /* does it need to change? */
   if (newmode != g->gckind) {  /* does it need to change? */
-    if (newmode == KGC_INC) {  /* entering incremental mode? */
-      if (g->gckind == KGC_GENMAJOR)
-        g->gckind = KGC_INC;  /* already incremental but in name */
-      else
-        enterinc(g);  /* entering incremental mode */
-    }
+    if (newmode == KGC_INC)  /* entering incremental mode? */
+      enterinc(g);  /* entering incremental mode */
     else {
     else {
       lua_assert(newmode == KGC_GENMINOR);
       lua_assert(newmode == KGC_GENMINOR);
       entergen(L, g);
       entergen(L, g);
@@ -1396,16 +1420,24 @@ static void fullgen (lua_State *L, global_State *g) {
 /*
 /*
 ** After an atomic incremental step from a major collection,
 ** After an atomic incremental step from a major collection,
 ** check whether collector could return to minor collections.
 ** check whether collector could return to minor collections.
+** It checks whether the number of objects 'tobecollected'
+** is greater than 'majorminor'% of the number of objects added
+** since the last collection ('addedobjs').
 */
 */
 static int checkmajorminor (lua_State *L, global_State *g) {
 static int checkmajorminor (lua_State *L, global_State *g) {
   if (g->gckind == KGC_GENMAJOR) {
   if (g->gckind == KGC_GENMAJOR) {
-    l_obj numobjs = gettotalobjs(g);  /* current count */
-    if (g->marked < numobjs - (numobjs >> 2)) {  /* ?? */
+    l_obj numobjs = gettotalobjs(g);
+    l_obj addedobjs = numobjs - g->GCmajorminor;
+    l_obj limit = applygcparam(g, majorminor, addedobjs);
+    l_obj tobecollected = numobjs - g->marked;
+//printf("-> minor? %ld %ld %ld\n", tobecollected, limit, numobjs);
+    if (tobecollected > limit) {
       atomic2gen(L, g);  /* return to generational mode */
       atomic2gen(L, g);  /* return to generational mode */
       setminordebt(g);
       setminordebt(g);
       return 0;  /* exit incremental collection */
       return 0;  /* exit incremental collection */
     }
     }
   }
   }
+  g->GCmajorminor = g->marked;  /* prepare for next collection */
   return 1;  /* stay doing incremental collections */
   return 1;  /* stay doing incremental collections */
 }
 }
 
 
@@ -1634,8 +1666,6 @@ void luaC_step (lua_State *L) {
   if (!gcrunning(g))  /* not running? */
   if (!gcrunning(g))  /* not running? */
     luaE_setdebt(g, 2000);
     luaE_setdebt(g, 2000);
   else {
   else {
-//printf("> step: %d  %d  %ld %ld -> ", g->gckind, g->gcstate, gettotalobjs(g), g->GCdebt);
-
     switch (g->gckind) {
     switch (g->gckind) {
       case KGC_INC: case KGC_GENMAJOR:
       case KGC_INC: case KGC_GENMAJOR:
         incstep(L, g);
         incstep(L, g);
@@ -1645,7 +1675,6 @@ void luaC_step (lua_State *L) {
         setminordebt(g);
         setminordebt(g);
         break;
         break;
     }
     }
-//printf("%d  %d  %ld %ld\n", g->gckind, g->gcstate, gettotalobjs(g), g->GCdebt);
   }
   }
 }
 }
 
 

+ 26 - 22
lgc.h

@@ -161,10 +161,24 @@
 
 
 /* Default Values for GC parameters */
 /* Default Values for GC parameters */
 
 
-/* generational */
+/*
+** Minor collections will shift to major ones after LUAI_MINORMAJOR%
+** objects become old.
+*/
+#define LUAI_MINORMAJOR         100
+
+/*
+** Major collections will shift to minor ones after a collection
+** collects at least LUAI_MAJORMINOR% of the new objects.
+*/
+#define LUAI_MAJORMINOR         80
+
+/*
+** A young (minor) collection will run after creating LUAI_GENMINORMUL%
+** new objects.
+*/
+#define LUAI_GENMINORMUL         20
 
 
-#define LUAI_GENMAJORMUL         100	/* major multiplier */
-#define LUAI_GENMINORMUL         20	/* minor multiplier */
 
 
 /* incremental */
 /* incremental */
 
 
@@ -187,27 +201,17 @@
 
 
 /*
 /*
 ** Macros to set and apply GC parameters. GC parameters are given in
 ** Macros to set and apply GC parameters. GC parameters are given in
-** percentage points, but are stored as lu_byte. To reduce their
-** values and avoid repeated divisions by 100, these macros store
-** the original parameter multiplied by 2^n and divided by 100.
-** To apply them, the value is divided by 2^n (a shift) and then
-** multiplied by the stored parameter, yielding
-** value / 2^n * (original parameter * 2^n / 100), or approximately
-** (value * original parameter / 100).
-**
-** For most parameters, which are typically larger than 100%, 2^n is
-** 16 (2^4), allowing maximum values up to ~1500%, with a granularity
-** of ~6%.  For the minor multiplier, which is typically smaller,
-** 2^n is 64 (2^6) to allow more precision. In that case, the maximum
-** value is ~400%, with a granularity of ~1.5%.
+** percentage points, but are stored as lu_byte. To avoid repeated
+** divisions by 100, these macros store the original parameter
+** multiplied by 128 and divided by 100.  To apply them, if it first
+** divides the value by 128 it may lose precision; if it first
+** multiplies by the parameter, it may overflow.  So, it first divides
+** by 32, then multiply by the parameter, and then divides the result by
+** 4.
 */
 */
-#define gcparamshift(p)  \
-  (offsetof(global_State, p) == offsetof(global_State, genminormul) ? 6 : 4)
-
-#define setgcparam(g,p,v)  \
-	(g->p = (cast_uint(v) << gcparamshift(p)) / 100u)
-#define applygcparam(g,p,v)	(((v) >> gcparamshift(p)) * g->p)
 
 
+#define setgcparam(g,p,v)	(g->gcp##p = (cast_uint(v) << 7) / 100u)
+#define applygcparam(g,p,v)	((((v) >> 5) * g->gcp##p) >> 2)
 
 
 
 
 /*
 /*

+ 2 - 1
lstate.c

@@ -368,8 +368,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned int seed) {
   setgcparam(g, gcpause, LUAI_GCPAUSE);
   setgcparam(g, gcpause, LUAI_GCPAUSE);
   setgcparam(g, gcstepmul, LUAI_GCMUL);
   setgcparam(g, gcstepmul, LUAI_GCMUL);
   g->gcstepsize = LUAI_GCSTEPSIZE;
   g->gcstepsize = LUAI_GCSTEPSIZE;
-  setgcparam(g, genmajormul, LUAI_GENMAJORMUL);
   setgcparam(g, genminormul, LUAI_GENMINORMUL);
   setgcparam(g, genminormul, LUAI_GENMINORMUL);
+  setgcparam(g, minormajor, LUAI_MINORMAJOR);
+  setgcparam(g, majorminor, LUAI_MAJORMINOR);
   for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
   for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
   if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
   if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
     /* memory allocation error: free partial state */
     /* memory allocation error: free partial state */

+ 5 - 4
lstate.h

@@ -264,16 +264,17 @@ typedef struct global_State {
   TValue l_registry;
   TValue l_registry;
   TValue nilvalue;  /* a nil value */
   TValue nilvalue;  /* a nil value */
   unsigned int seed;  /* randomized seed for hashes */
   unsigned int seed;  /* randomized seed for hashes */
+  unsigned short gcpgenminormul;  /* control minor generational collections */
+  unsigned short gcpmajorminor;  /* control shift major->minor */
+  unsigned short gcpminormajor;  /* control shift minor->major */
+  unsigned short gcpgcpause;  /* size of pause between successive GCs */
+  unsigned short gcpgcstepmul;  /* GC "speed" */
   lu_byte currentwhite;
   lu_byte currentwhite;
   lu_byte gcstate;  /* state of garbage collector */
   lu_byte gcstate;  /* state of garbage collector */
   lu_byte gckind;  /* kind of GC running */
   lu_byte gckind;  /* kind of GC running */
   lu_byte gcstopem;  /* stops emergency collections */
   lu_byte gcstopem;  /* stops emergency collections */
-  lu_byte genminormul;  /* control for minor generational collections */
-  lu_byte genmajormul;  /* control for major generational collections */
   lu_byte gcstp;  /* control whether GC is running */
   lu_byte gcstp;  /* control whether GC is running */
   lu_byte gcemergency;  /* true if this is an emergency collection */
   lu_byte gcemergency;  /* true if this is an emergency collection */
-  lu_byte gcpause;  /* size of pause between successive GCs */
-  lu_byte gcstepmul;  /* GC "speed" */
   lu_byte gcstepsize;  /* (log2 of) GC granularity */
   lu_byte gcstepsize;  /* (log2 of) GC granularity */
   GCObject *allgc;  /* list of all collectable objects */
   GCObject *allgc;  /* list of all collectable objects */
   GCObject **sweepgc;  /* current position of sweep in list */
   GCObject **sweepgc;  /* current position of sweep in list */

+ 1 - 1
lua.c

@@ -646,7 +646,7 @@ static int pmain (lua_State *L) {
   luai_openlibs(L);  /* open standard libraries */
   luai_openlibs(L);  /* open standard libraries */
   createargtable(L, argv, argc, script);  /* create table 'arg' */
   createargtable(L, argv, argc, script);  /* create table 'arg' */
   lua_gc(L, LUA_GCRESTART);  /* start GC... */
   lua_gc(L, LUA_GCRESTART);  /* start GC... */
-  lua_gc(L, LUA_GCGEN, 0, 0);  /* ...in generational mode */
+  lua_gc(L, LUA_GCGEN, -1, -1, -1);  /* ...in generational mode */
   if (!(args & has_E)) {  /* no option '-E'? */
   if (!(args & has_E)) {  /* no option '-E'? */
     if (handle_luainit(L) != LUA_OK)  /* run LUA_INIT */
     if (handle_luainit(L) != LUA_OK)  /* run LUA_INIT */
       return 0;  /* error running LUA_INIT */
       return 0;  /* error running LUA_INIT */

+ 77 - 57
manual/manual.of

@@ -621,7 +621,8 @@ that is inaccessible from Lua.
 another live object refer to the object.)
 another live object refer to the object.)
 Because Lua has no knowledge about @N{C code},
 Because Lua has no knowledge about @N{C code},
 it never collects objects accessible through the registry @see{registry},
 it never collects objects accessible through the registry @see{registry},
-which includes the global environment @see{globalenv}.
+which includes the global environment @see{globalenv} and
+the main thread.
 
 
 
 
 The garbage collector (GC) in Lua can work in two modes:
 The garbage collector (GC) in Lua can work in two modes:
@@ -638,8 +639,8 @@ therefore, optimal settings are also non-portable.
 You can change the GC mode and parameters by calling
 You can change the GC mode and parameters by calling
 @Lid{lua_gc} @N{in C}
 @Lid{lua_gc} @N{in C}
 or @Lid{collectgarbage} in Lua.
 or @Lid{collectgarbage} in Lua.
-You can also use these functions to control
-the collector directly (e.g., to stop and restart it).
+You can also use these functions to control the collector directly,
+for instance to stop or restart it.
 
 
 }
 }
 
 
@@ -656,39 +657,36 @@ and the @def{garbage-collector step size}.
 
 
 The garbage-collector pause
 The garbage-collector pause
 controls how long the collector waits before starting a new cycle.
 controls how long the collector waits before starting a new cycle.
-The collector starts a new cycle when the use of memory
-hits @M{n%} of the use after the previous collection.
+The collector starts a new cycle when the number of objects
+hits @M{n%} of the total after the previous collection.
 Larger values make the collector less aggressive.
 Larger values make the collector less aggressive.
 Values equal to or less than 100 mean the collector will not wait to
 Values equal to or less than 100 mean the collector will not wait to
 start a new cycle.
 start a new cycle.
-A value of 200 means that the collector waits for the total memory in use
-to double before starting a new cycle.
+A value of 200 means that the collector waits for
+the total number of objects to double before starting a new cycle.
 The default value is 200; the maximum value is 1000.
 The default value is 200; the maximum value is 1000.
 
 
 The garbage-collector step multiplier
 The garbage-collector step multiplier
 controls the speed of the collector relative to
 controls the speed of the collector relative to
-memory allocation,
+object creation,
 that is,
 that is,
-how many elements it marks or sweeps for each
-kilobyte of memory allocated.
-Larger values make the collector more aggressive but also increase
-the size of each incremental step.
-You should not use values less than 100,
-because they make the collector too slow and
-can result in the collector never finishing a cycle.
-The default value is 100;  the maximum value is 1000.
+how many objects it marks or sweeps for each object created.
+Larger values make the collector more aggressive.
+Beware that values too small can
+make the collector too slow to ever finish a cycle.
+The default value is 300;  the maximum value is 1000.
 
 
 The garbage-collector step size controls the
 The garbage-collector step size controls the
 size of each incremental step,
 size of each incremental step,
-specifically how many bytes the interpreter allocates
+specifically how many objects the interpreter creates
 before performing a step.
 before performing a step.
 This parameter is logarithmic:
 This parameter is logarithmic:
-A value of @M{n} means the interpreter will allocate @M{2@sp{n}}
-bytes between steps and perform equivalent work during the step.
+A value of @M{n} means the interpreter will create @M{2@sp{n}}
+objects between steps and perform equivalent work during the step.
 A large value (e.g., 60) makes the collector a stop-the-world
 A large value (e.g., 60) makes the collector a stop-the-world
 (non-incremental) collector.
 (non-incremental) collector.
-The default value is 13,
-which means steps of approximately @N{8 Kbytes}.
+The default value is 8,
+which means steps of approximately @N{256 objects}.
 
 
 }
 }
 
 
@@ -697,31 +695,44 @@ which means steps of approximately @N{8 Kbytes}.
 In generational mode,
 In generational mode,
 the collector does frequent @emph{minor} collections,
 the collector does frequent @emph{minor} collections,
 which traverses only objects recently created.
 which traverses only objects recently created.
-If after a minor collection the use of memory is still above a limit,
-the collector does a stop-the-world @emph{major} collection,
+If after a minor collection the number of objects is above a limit,
+the collector shifts to a @emph{major} collection,
 which traverses all objects.
 which traverses all objects.
-The generational mode uses two parameters:
-the @def{minor multiplier} and the @def{the major multiplier}.
+The collector will then stay doing major collections until
+it detects that the program is generating enough garbage to justify
+going back to minor collections.
+
+The generational mode uses three parameters:
+the @def{minor multiplier}, the @def{minor-major multiplier},
+and the @def{major-minor multiplier}.
 
 
 The minor multiplier controls the frequency of minor collections.
 The minor multiplier controls the frequency of minor collections.
 For a minor multiplier @M{x},
 For a minor multiplier @M{x},
-a new minor collection will be done when memory
-grows @M{x%} larger than the memory in use after the previous major
-collection.
+a new minor collection will be done when the number of objects
+grows @M{x%} larger than the number in use just after the last collection.
 For instance, for a multiplier of 20,
 For instance, for a multiplier of 20,
-the collector will do a minor collection when the use of memory
-gets 20% larger than the use after the previous major collection.
-The default value is 20; the maximum value is 200.
-
-The major multiplier controls the frequency of major collections.
-For a major multiplier @M{x},
-a new major collection will be done when memory
-grows @M{x%} larger than the memory in use after the previous major
-collection.
+the collector will do a minor collection when the number of objects
+gets 20% larger than the total after the last major collection.
+The default value is 20.
+
+The minor-major multiplier controls the shift to major collections.
+For a multiplier @M{x},
+the collector will shift to a major collection
+when the number of old objects grows @M{x%} larger
+than the total after the previous major collection.
 For instance, for a multiplier of 100,
 For instance, for a multiplier of 100,
-the collector will do a major collection when the use of memory
-gets larger than twice the use after the previous collection.
-The default value is 100; the maximum value is 1000.
+the collector will do a major collection when the number of old objects
+gets larger than twice the total after the previous major collection.
+The default value is 100.
+
+The major-minor multiplier controls the shift back to minor collections.
+For a multiplier @M{x},
+the collector will shift back to minor collections
+after a major collection collects at least @M{x%} of the allocated objects.
+In particular, for a multiplier of 0,
+the collector will immediately shift back to minor collections
+after doing one cycle of major collections.
+The default value is 20.
 
 
 }
 }
 
 
@@ -3311,9 +3322,8 @@ Returns the remainder of dividing the current amount of bytes of
 memory in use by Lua by 1024.
 memory in use by Lua by 1024.
 }
 }
 
 
-@item{@id{LUA_GCSTEP} @T{(int stepsize)}|
-Performs an incremental step of garbage collection,
-corresponding to the allocation of @id{stepsize} Kbytes.
+@item{@id{LUA_GCSTEP}|
+Performs a step of garbage collection.
 }
 }
 
 
 @item{@id{LUA_GCISRUNNING}|
 @item{@id{LUA_GCISRUNNING}|
@@ -3321,13 +3331,13 @@ Returns a boolean that tells whether the collector is running
 (i.e., not stopped).
 (i.e., not stopped).
 }
 }
 
 
-@item{@id{LUA_GCINC} (int pause, int stepmul, stepsize)|
+@item{@id{LUA_GCINC} (int pause, int stepmul, int stepsize)|
 Changes the collector to incremental mode
 Changes the collector to incremental mode
 with the given parameters @see{incmode}.
 with the given parameters @see{incmode}.
 Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}).
 Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}).
 }
 }
 
 
-@item{@id{LUA_GCGEN} (int minormul, int majormul)|
+@item{@id{LUA_GCGEN} (int minormul, int minormajor, int majorminor)|
 Changes the collector to generational mode
 Changes the collector to generational mode
 with the given parameters @see{genmode}.
 with the given parameters @see{genmode}.
 Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}).
 Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}).
@@ -6312,13 +6322,14 @@ gives the exact number of bytes in use by Lua.
 
 
 @item{@St{step}|
 @item{@St{step}|
 Performs a garbage-collection step.
 Performs a garbage-collection step.
-The step @Q{size} is controlled by @id{arg}.
-With a zero value,
-the collector will perform one basic (indivisible) step.
-For non-zero values,
-the collector will perform as if that amount of memory
-(in Kbytes) had been allocated by Lua.
-Returns @true if the step finished a collection cycle.
+In incremental mode,
+that step corresponds to the current step size;
+the function returns @true if the step finished a collection cycle.
+In generational mode,
+the step performs a full minor collection or
+a major collection,
+if the collector has scheduled one;
+the function returns @true if the step performed a major collection.
 }
 }
 
 
 @item{@St{isrunning}|
 @item{@St{isrunning}|
@@ -6332,15 +6343,15 @@ This option can be followed by three numbers:
 the garbage-collector pause,
 the garbage-collector pause,
 the step multiplier,
 the step multiplier,
 and the step size @see{incmode}.
 and the step size @see{incmode}.
-A zero means to not change that value.
+A -1 or absent value means to not change that value.
 }
 }
 
 
 @item{@St{generational}|
 @item{@St{generational}|
 Change the collector mode to generational.
 Change the collector mode to generational.
-This option can be followed by two numbers:
-the garbage-collector minor multiplier
-and the major multiplier @see{genmode}.
-A zero means to not change that value.
+This option can be followed by three numbers:
+the garbage-collector minor multiplier,
+the minor-major multiplier, and the major-minor multiplier @see{genmode}.
+A -1 or absent value means to not change that value.
 }
 }
 
 
 }
 }
@@ -9229,6 +9240,9 @@ declare a local variable with the same name in the loop body.
 @itemize{
 @itemize{
 
 
 @item{
 @item{
+There were several changes in the parameters
+for the options @St{incremental} and @St{generational}
+of the function @Lid{collectgarbage}.
 }
 }
 
 
 }
 }
@@ -9245,6 +9259,12 @@ it is equivalent to @Lid{lua_closethread} with
 @id{from} being @id{NULL}.
 @id{from} being @id{NULL}.
 }
 }
 
 
+@item{
+There were several changes in the parameters
+for the options @Lid{LUA_GCINC} and @Lid{LUA_GCGEN}
+of the function @Lid{lua_gc}.
+}
+
 }
 }
 
 
 }
 }