aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lgc.c67
-rw-r--r--lgc.h12
-rw-r--r--llimits.h8
-rw-r--r--ltests.c8
-rw-r--r--manual/manual.of28
-rw-r--r--testes/gengc.lua11
6 files changed, 84 insertions, 50 deletions
diff --git a/lgc.c b/lgc.c
index ecd142cb..114b32d3 100644
--- a/lgc.c
+++ b/lgc.c
@@ -93,6 +93,7 @@
93*/ 93*/
94#define markobjectN(g,t) { if (t) markobject(g,t); } 94#define markobjectN(g,t) { if (t) markobject(g,t); }
95 95
96
96static void reallymarkobject (global_State *g, GCObject *o); 97static void reallymarkobject (global_State *g, GCObject *o);
97static l_obj atomic (lua_State *L); 98static l_obj atomic (lua_State *L);
98static void entersweep (lua_State *L); 99static void entersweep (lua_State *L);
@@ -831,10 +832,10 @@ static void freeobj (lua_State *L, GCObject *o) {
831** for next collection cycle. Return where to continue the traversal or 832** for next collection cycle. Return where to continue the traversal or
832** NULL if list is finished. 833** NULL if list is finished.
833*/ 834*/
834static GCObject **sweeplist (lua_State *L, GCObject **p, int countin) { 835static GCObject **sweeplist (lua_State *L, GCObject **p, l_obj countin) {
835 global_State *g = G(L); 836 global_State *g = G(L);
836 int ow = otherwhite(g); 837 int ow = otherwhite(g);
837 int i; 838 l_obj i;
838 int white = luaC_white(g); /* current white */ 839 int white = luaC_white(g); /* current white */
839 for (i = 0; *p != NULL && i < countin; i++) { 840 for (i = 0; *p != NULL && i < countin; i++) {
840 GCObject *curr = *p; 841 GCObject *curr = *p;
@@ -1357,8 +1358,8 @@ static void setminordebt (global_State *g) {
1357** collection. 1358** collection.
1358*/ 1359*/
1359static void entergen (lua_State *L, global_State *g) { 1360static void entergen (lua_State *L, global_State *g) {
1360 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ 1361 luaC_runtilstate(L, GCSpause, 1); /* prepare to start a new cycle */
1361 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1362 luaC_runtilstate(L, GCSpropagate, 1); /* start new cycle */
1362 atomic(L); /* propagates all and then do the atomic stuff */ 1363 atomic(L); /* propagates all and then do the atomic stuff */
1363 atomic2gen(L, g); 1364 atomic2gen(L, g);
1364 setminordebt(g); /* set debt assuming next cycle will be minor */ 1365 setminordebt(g); /* set debt assuming next cycle will be minor */
@@ -1515,10 +1516,14 @@ static l_obj atomic (lua_State *L) {
1515} 1516}
1516 1517
1517 1518
1519/*
1520** Do a sweep step. The normal case (not fast) sweeps at most GCSWEEPMAX
1521** elements. The fast case sweeps the whole list.
1522*/
1518static void sweepstep (lua_State *L, global_State *g, 1523static void sweepstep (lua_State *L, global_State *g,
1519 int nextstate, GCObject **nextlist) { 1524 int nextstate, GCObject **nextlist, int fast) {
1520 if (g->sweepgc) 1525 if (g->sweepgc)
1521 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); 1526 g->sweepgc = sweeplist(L, g->sweepgc, fast ? MAX_LOBJ : GCSWEEPMAX);
1522 else { /* enter next state */ 1527 else { /* enter next state */
1523 g->gcstate = nextstate; 1528 g->gcstate = nextstate;
1524 g->sweepgc = nextlist; 1529 g->sweepgc = nextlist;
@@ -1526,7 +1531,19 @@ static void sweepstep (lua_State *L, global_State *g,
1526} 1531}
1527 1532
1528 1533
1529static l_obj singlestep (lua_State *L) { 1534/*
1535** Performs one incremental "step" in an incremental garbage collection.
1536** For indivisible work, a step goes to the next state. When marking
1537** (propagating), a step traverses one object. When sweeping, a step
1538** sweeps GCSWEEPMAX objects, to avoid a big overhead for sweeping
1539** objects one by one. (Sweeping is inexpensive, no matter the
1540** object.) When 'fast' is true, 'singlestep' tries to finish a state
1541** "as fast as possible". In particular, it skips the propagation
1542** phase and leaves all objects to be traversed by the atomic phase:
1543** That avoids traversing twice some objects, such as theads and
1544** weak tables.
1545*/
1546static l_obj singlestep (lua_State *L, int fast) {
1530 global_State *g = G(L); 1547 global_State *g = G(L);
1531 l_obj work; 1548 l_obj work;
1532 lua_assert(!g->gcstopem); /* collector is not reentrant */ 1549 lua_assert(!g->gcstopem); /* collector is not reentrant */
@@ -1539,7 +1556,7 @@ static l_obj singlestep (lua_State *L) {
1539 break; 1556 break;
1540 } 1557 }
1541 case GCSpropagate: { 1558 case GCSpropagate: {
1542 if (g->gray == NULL) { /* no more gray objects? */ 1559 if (fast || g->gray == NULL) {
1543 g->gcstate = GCSenteratomic; /* finish propagate phase */ 1560 g->gcstate = GCSenteratomic; /* finish propagate phase */
1544 work = 0; 1561 work = 0;
1545 } 1562 }
@@ -1556,17 +1573,17 @@ static l_obj singlestep (lua_State *L) {
1556 break; 1573 break;
1557 } 1574 }
1558 case GCSswpallgc: { /* sweep "regular" objects */ 1575 case GCSswpallgc: { /* sweep "regular" objects */
1559 sweepstep(L, g, GCSswpfinobj, &g->finobj); 1576 sweepstep(L, g, GCSswpfinobj, &g->finobj, fast);
1560 work = GCSWEEPMAX; 1577 work = GCSWEEPMAX;
1561 break; 1578 break;
1562 } 1579 }
1563 case GCSswpfinobj: { /* sweep objects with finalizers */ 1580 case GCSswpfinobj: { /* sweep objects with finalizers */
1564 sweepstep(L, g, GCSswptobefnz, &g->tobefnz); 1581 sweepstep(L, g, GCSswptobefnz, &g->tobefnz, fast);
1565 work = GCSWEEPMAX; 1582 work = GCSWEEPMAX;
1566 break; 1583 break;
1567 } 1584 }
1568 case GCSswptobefnz: { /* sweep objects to be finalized */ 1585 case GCSswptobefnz: { /* sweep objects to be finalized */
1569 sweepstep(L, g, GCSswpend, NULL); 1586 sweepstep(L, g, GCSswpend, NULL, fast);
1570 work = GCSWEEPMAX; 1587 work = GCSWEEPMAX;
1571 break; 1588 break;
1572 } 1589 }
@@ -1596,14 +1613,15 @@ static l_obj singlestep (lua_State *L) {
1596 1613
1597 1614
1598/* 1615/*
1599** advances the garbage collector until it reaches a state allowed 1616** Advances the garbage collector until it reaches the given state.
1600** by 'statemask' 1617** (The option 'fast' is only for testing; in normal code, 'fast'
1618** here is always true.)
1601*/ 1619*/
1602void luaC_runtilstate (lua_State *L, int statesmask) { 1620void luaC_runtilstate (lua_State *L, int state, int fast) {
1603 global_State *g = G(L); 1621 global_State *g = G(L);
1604 lua_assert(g->gckind == KGC_INC); 1622 lua_assert(g->gckind == KGC_INC);
1605 while (!testbit(statesmask, g->gcstate)) 1623 while (state != g->gcstate)
1606 singlestep(L); 1624 singlestep(L, fast);
1607} 1625}
1608 1626
1609 1627
@@ -1618,8 +1636,13 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
1618static void incstep (lua_State *L, global_State *g) { 1636static void incstep (lua_State *L, global_State *g) {
1619 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; 1637 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1620 l_obj work2do = applygcparam(g, gcstepmul, stepsize); 1638 l_obj work2do = applygcparam(g, gcstepmul, stepsize);
1621 do { /* repeat until pause or enough "credit" (negative debt) */ 1639 int fast = 0;
1622 l_obj work = singlestep(L); /* perform one single step */ 1640 if (work2do == 0) { /* special case: do a full collection */
1641 work2do = MAX_LOBJ; /* do unlimited work */
1642 fast = 1;
1643 }
1644 do { /* repeat until pause or enough work */
1645 l_obj work = singlestep(L, fast); /* perform one single step */
1623 if (g->gckind == KGC_GENMINOR) /* returned to minor collections? */ 1646 if (g->gckind == KGC_GENMINOR) /* returned to minor collections? */
1624 return; /* nothing else to be done here */ 1647 return; /* nothing else to be done here */
1625 work2do -= work; 1648 work2do -= work;
@@ -1665,13 +1688,11 @@ static void fullinc (lua_State *L, global_State *g) {
1665 if (keepinvariant(g)) /* black objects? */ 1688 if (keepinvariant(g)) /* black objects? */
1666 entersweep(L); /* sweep everything to turn them back to white */ 1689 entersweep(L); /* sweep everything to turn them back to white */
1667 /* finish any pending sweep phase to start a new cycle */ 1690 /* finish any pending sweep phase to start a new cycle */
1668 luaC_runtilstate(L, bitmask(GCSpause)); 1691 luaC_runtilstate(L, GCSpause, 1);
1669 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1692 luaC_runtilstate(L, GCScallfin, 1); /* run up to finalizers */
1670 g->gcstate = GCSenteratomic; /* go straight to atomic phase ??? */
1671 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
1672 /* 'marked' must be correct after a full GC cycle */ 1693 /* 'marked' must be correct after a full GC cycle */
1673 lua_assert(g->marked == gettotalobjs(g)); 1694 lua_assert(g->marked == gettotalobjs(g));
1674 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1695 luaC_runtilstate(L, GCSpause, 1); /* finish collection */
1675 setpause(g); 1696 setpause(g);
1676} 1697}
1677 1698
diff --git a/lgc.h b/lgc.h
index 4cbc6e61..e8dee8a0 100644
--- a/lgc.h
+++ b/lgc.h
@@ -182,12 +182,14 @@
182 182
183/* incremental */ 183/* incremental */
184 184
185/* wait memory to double before starting new cycle */ 185/* Number of objects must be LUAI_GCPAUSE% before starting new cycle */
186#define LUAI_GCPAUSE 200 186#define LUAI_GCPAUSE 300
187 187
188#define LUAI_GCMUL 300 /* step multiplier */ 188/* Step multiplier. (Roughly, the collector handles LUAI_GCMUL% objects
189 for each new allocated object.) */
190#define LUAI_GCMUL 200
189 191
190/* how many objects to allocate before next GC step (log2) */ 192/* How many objects to allocate before next GC step (log2) */
191#define LUAI_GCSTEPSIZE 8 /* 256 objects */ 193#define LUAI_GCSTEPSIZE 8 /* 256 objects */
192 194
193 195
@@ -244,7 +246,7 @@
244LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); 246LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
245LUAI_FUNC void luaC_freeallobjects (lua_State *L); 247LUAI_FUNC void luaC_freeallobjects (lua_State *L);
246LUAI_FUNC void luaC_step (lua_State *L); 248LUAI_FUNC void luaC_step (lua_State *L);
247LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); 249LUAI_FUNC void luaC_runtilstate (lua_State *L, int state, int fast);
248LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); 250LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
249LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); 251LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz);
250LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, 252LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz,
diff --git a/llimits.h b/llimits.h
index 47dee9a6..3bcd1b7f 100644
--- a/llimits.h
+++ b/llimits.h
@@ -33,7 +33,8 @@ typedef unsigned long lu_mem;
33typedef long l_obj; 33typedef long l_obj;
34#endif /* } */ 34#endif /* } */
35 35
36#define MAX_LOBJ cast(l_obj, ~cast(lu_mem, 0) >> 1) 36#define MAX_LOBJ \
37 cast(l_obj, (cast(lu_mem, 1) << (sizeof(l_obj) * CHAR_BIT - 1)) - 1)
37 38
38 39
39/* chars used as small naturals (so that 'char' is reserved for characters) */ 40/* chars used as small naturals (so that 'char' is reserved for characters) */
@@ -44,7 +45,10 @@ typedef signed char ls_byte;
44/* maximum value for size_t */ 45/* maximum value for size_t */
45#define MAX_SIZET ((size_t)(~(size_t)0)) 46#define MAX_SIZET ((size_t)(~(size_t)0))
46 47
47/* maximum size visible for Lua (must be representable in a lua_Integer) */ 48/*
49** Maximum size for strings and userdata visible for Lua (should be
50** representable in a lua_Integer)
51*/
48#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \ 52#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \
49 : (size_t)(LUA_MAXINTEGER)) 53 : (size_t)(LUA_MAXINTEGER))
50 54
diff --git a/ltests.c b/ltests.c
index 9bc2f0da..51e4ff9b 100644
--- a/ltests.c
+++ b/ltests.c
@@ -941,10 +941,10 @@ static int gc_printobj (lua_State *L) {
941 941
942static int gc_state (lua_State *L) { 942static int gc_state (lua_State *L) {
943 static const char *statenames[] = { 943 static const char *statenames[] = {
944 "propagate", "atomic", "enteratomic", "sweepallgc", "sweepfinobj", 944 "propagate", "atomic", "sweepallgc", "sweepfinobj",
945 "sweeptobefnz", "sweepend", "callfin", "pause", ""}; 945 "sweeptobefnz", "sweepend", "callfin", "pause", ""};
946 static const int states[] = { 946 static const int states[] = {
947 GCSpropagate, GCSenteratomic, GCSatomic, GCSswpallgc, GCSswpfinobj, 947 GCSpropagate, GCSenteratomic, GCSswpallgc, GCSswpfinobj,
948 GCSswptobefnz, GCSswpend, GCScallfin, GCSpause, -1}; 948 GCSswptobefnz, GCSswpend, GCScallfin, GCSpause, -1};
949 int option = states[luaL_checkoption(L, 1, "", statenames)]; 949 int option = states[luaL_checkoption(L, 1, "", statenames)];
950 if (option == -1) { 950 if (option == -1) {
@@ -957,9 +957,9 @@ static int gc_state (lua_State *L) {
957 luaL_error(L, "cannot change states in generational mode"); 957 luaL_error(L, "cannot change states in generational mode");
958 lua_lock(L); 958 lua_lock(L);
959 if (option < g->gcstate) { /* must cross 'pause'? */ 959 if (option < g->gcstate) { /* must cross 'pause'? */
960 luaC_runtilstate(L, bitmask(GCSpause)); /* run until pause */ 960 luaC_runtilstate(L, GCSpause, 1); /* run until pause */
961 } 961 }
962 luaC_runtilstate(L, bitmask(option)); 962 luaC_runtilstate(L, option, 0); /* do not skip propagation state */
963 lua_assert(G(L)->gcstate == option); 963 lua_assert(G(L)->gcstate == option);
964 lua_unlock(L); 964 lua_unlock(L);
965 return 0; 965 return 0;
diff --git a/manual/manual.of b/manual/manual.of
index ef1bdfd2..e6a3cd9e 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -664,7 +664,7 @@ Values equal to or less than 100 mean the collector will not wait to
664start a new cycle. 664start a new cycle.
665A value of 200 means that the collector waits for 665A value of 200 means that the collector waits for
666the total number of objects to double before starting a new cycle. 666the total number of objects to double before starting a new cycle.
667The default value is 200; the maximum value is 1000. 667The default value is 300; the maximum value is 1000.
668 668
669The garbage-collector step multiplier 669The garbage-collector step multiplier
670controls the speed of the collector relative to 670controls the speed of the collector relative to
@@ -674,7 +674,9 @@ how many objects it marks or sweeps for each object created.
674Larger values make the collector more aggressive. 674Larger values make the collector more aggressive.
675Beware that values too small can 675Beware that values too small can
676make the collector too slow to ever finish a cycle. 676make the collector too slow to ever finish a cycle.
677The default value is 300; the maximum value is 1000. 677The default value is 200; the maximum value is 1000.
678As a special case, a zero value means unlimited work,
679effectively producing a non-incremental, stop-the-world collector.
678 680
679The garbage-collector step size controls the 681The garbage-collector step size controls the
680size of each incremental step, 682size of each incremental step,
@@ -682,9 +684,7 @@ specifically how many objects the interpreter creates
682before performing a step. 684before performing a step.
683This parameter is logarithmic: 685This parameter is logarithmic:
684A value of @M{n} means the interpreter will create @M{2@sp{n}} 686A value of @M{n} means the interpreter will create @M{2@sp{n}}
685objects between steps and perform equivalent work during the step. 687objects between steps.
686A large value (e.g., 60) makes the collector a stop-the-world
687(non-incremental) collector.
688The default value is 8, 688The default value is 8,
689which means steps of approximately @N{256 objects}. 689which means steps of approximately @N{256 objects}.
690 690
@@ -3306,43 +3306,43 @@ For options that need extra arguments,
3306they are listed after the option. 3306they are listed after the option.
3307@description{ 3307@description{
3308 3308
3309@item{@id{LUA_GCCOLLECT}| 3309@item{@defid{LUA_GCCOLLECT}|
3310Performs a full garbage-collection cycle. 3310Performs a full garbage-collection cycle.
3311} 3311}
3312 3312
3313@item{@id{LUA_GCSTOP}| 3313@item{@defid{LUA_GCSTOP}|
3314Stops the garbage collector. 3314Stops the garbage collector.
3315} 3315}
3316 3316
3317@item{@id{LUA_GCRESTART}| 3317@item{@defid{LUA_GCRESTART}|
3318Restarts the garbage collector. 3318Restarts the garbage collector.
3319} 3319}
3320 3320
3321@item{@id{LUA_GCCOUNT}| 3321@item{@defid{LUA_GCCOUNT}|
3322Returns the current amount of memory (in Kbytes) in use by Lua. 3322Returns the current amount of memory (in Kbytes) in use by Lua.
3323} 3323}
3324 3324
3325@item{@id{LUA_GCCOUNTB}| 3325@item{@defid{LUA_GCCOUNTB}|
3326Returns the remainder of dividing the current amount of bytes of 3326Returns the remainder of dividing the current amount of bytes of
3327memory in use by Lua by 1024. 3327memory in use by Lua by 1024.
3328} 3328}
3329 3329
3330@item{@id{LUA_GCSTEP}| 3330@item{@defid{LUA_GCSTEP}|
3331Performs a step of garbage collection. 3331Performs a step of garbage collection.
3332} 3332}
3333 3333
3334@item{@id{LUA_GCISRUNNING}| 3334@item{@defid{LUA_GCISRUNNING}|
3335Returns a boolean that tells whether the collector is running 3335Returns a boolean that tells whether the collector is running
3336(i.e., not stopped). 3336(i.e., not stopped).
3337} 3337}
3338 3338
3339@item{@id{LUA_GCINC} (int pause, int stepmul, int stepsize)| 3339@item{@defid{LUA_GCINC} (int pause, int stepmul, int stepsize)|
3340Changes the collector to incremental mode 3340Changes the collector to incremental mode
3341with the given parameters @see{incmode}. 3341with the given parameters @see{incmode}.
3342Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}). 3342Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}).
3343} 3343}
3344 3344
3345@item{@id{LUA_GCGEN} (int minormul, int minormajor, int majorminor)| 3345@item{@defid{LUA_GCGEN} (int minormul, int minormajor, int majorminor)|
3346Changes the collector to generational mode 3346Changes the collector to generational mode
3347with the given parameters @see{genmode}. 3347with the given parameters @see{genmode}.
3348Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}). 3348Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}).
diff --git a/testes/gengc.lua b/testes/gengc.lua
index 3d4f67f8..d708d7fc 100644
--- a/testes/gengc.lua
+++ b/testes/gengc.lua
@@ -162,9 +162,16 @@ end
162assert(collectgarbage'isrunning') 162assert(collectgarbage'isrunning')
163 163
164 164
165do print"testing stop-the-world collection"
166 collectgarbage("incremental", nil, 0)
165 167
166-- just to make sure 168 -- each step does a complete cycle
167assert(collectgarbage'isrunning') 169 assert(collectgarbage("step"))
170 assert(collectgarbage("step"))
171
172 -- back to default value
173 collectgarbage("incremental", nil, 200)
174end
168 175
169collectgarbage(oldmode) 176collectgarbage(oldmode)
170 177