diff options
| -rw-r--r-- | lgc.c | 67 | ||||
| -rw-r--r-- | lgc.h | 12 | ||||
| -rw-r--r-- | llimits.h | 8 | ||||
| -rw-r--r-- | ltests.c | 8 | ||||
| -rw-r--r-- | manual/manual.of | 28 | ||||
| -rw-r--r-- | testes/gengc.lua | 11 |
6 files changed, 84 insertions, 50 deletions
| @@ -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 | |||
| 96 | static void reallymarkobject (global_State *g, GCObject *o); | 97 | static void reallymarkobject (global_State *g, GCObject *o); |
| 97 | static l_obj atomic (lua_State *L); | 98 | static l_obj atomic (lua_State *L); |
| 98 | static void entersweep (lua_State *L); | 99 | static 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 | */ |
| 834 | static GCObject **sweeplist (lua_State *L, GCObject **p, int countin) { | 835 | static 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 | */ |
| 1359 | static void entergen (lua_State *L, global_State *g) { | 1360 | static 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 | */ | ||
| 1518 | static void sweepstep (lua_State *L, global_State *g, | 1523 | static 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 | ||
| 1529 | static 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 | */ | ||
| 1546 | static 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 | */ |
| 1602 | void luaC_runtilstate (lua_State *L, int statesmask) { | 1620 | void 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) { | |||
| 1618 | static void incstep (lua_State *L, global_State *g) { | 1636 | static 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 | ||
| @@ -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 @@ | |||
| 244 | LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); | 246 | LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); |
| 245 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); | 247 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); |
| 246 | LUAI_FUNC void luaC_step (lua_State *L); | 248 | LUAI_FUNC void luaC_step (lua_State *L); |
| 247 | LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); | 249 | LUAI_FUNC void luaC_runtilstate (lua_State *L, int state, int fast); |
| 248 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); | 250 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); |
| 249 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); | 251 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); |
| 250 | LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, | 252 | LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, |
| @@ -33,7 +33,8 @@ typedef unsigned long lu_mem; | |||
| 33 | typedef long l_obj; | 33 | typedef 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 | ||
| @@ -941,10 +941,10 @@ static int gc_printobj (lua_State *L) { | |||
| 941 | 941 | ||
| 942 | static int gc_state (lua_State *L) { | 942 | static 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 | |||
| 664 | start a new cycle. | 664 | start a new cycle. |
| 665 | A value of 200 means that the collector waits for | 665 | A value of 200 means that the collector waits for |
| 666 | the total number of objects to double before starting a new cycle. | 666 | the total number of objects to double before starting a new cycle. |
| 667 | The default value is 200; the maximum value is 1000. | 667 | The default value is 300; the maximum value is 1000. |
| 668 | 668 | ||
| 669 | The garbage-collector step multiplier | 669 | The garbage-collector step multiplier |
| 670 | controls the speed of the collector relative to | 670 | controls the speed of the collector relative to |
| @@ -674,7 +674,9 @@ how many objects it marks or sweeps for each object created. | |||
| 674 | Larger values make the collector more aggressive. | 674 | Larger values make the collector more aggressive. |
| 675 | Beware that values too small can | 675 | Beware that values too small can |
| 676 | make the collector too slow to ever finish a cycle. | 676 | make the collector too slow to ever finish a cycle. |
| 677 | The default value is 300; the maximum value is 1000. | 677 | The default value is 200; the maximum value is 1000. |
| 678 | As a special case, a zero value means unlimited work, | ||
| 679 | effectively producing a non-incremental, stop-the-world collector. | ||
| 678 | 680 | ||
| 679 | The garbage-collector step size controls the | 681 | The garbage-collector step size controls the |
| 680 | size of each incremental step, | 682 | size of each incremental step, |
| @@ -682,9 +684,7 @@ specifically how many objects the interpreter creates | |||
| 682 | before performing a step. | 684 | before performing a step. |
| 683 | This parameter is logarithmic: | 685 | This parameter is logarithmic: |
| 684 | A value of @M{n} means the interpreter will create @M{2@sp{n}} | 686 | A value of @M{n} means the interpreter will create @M{2@sp{n}} |
| 685 | objects between steps and perform equivalent work during the step. | 687 | objects between steps. |
| 686 | A large value (e.g., 60) makes the collector a stop-the-world | ||
| 687 | (non-incremental) collector. | ||
| 688 | The default value is 8, | 688 | The default value is 8, |
| 689 | which means steps of approximately @N{256 objects}. | 689 | which means steps of approximately @N{256 objects}. |
| 690 | 690 | ||
| @@ -3306,43 +3306,43 @@ For options that need extra arguments, | |||
| 3306 | they are listed after the option. | 3306 | they are listed after the option. |
| 3307 | @description{ | 3307 | @description{ |
| 3308 | 3308 | ||
| 3309 | @item{@id{LUA_GCCOLLECT}| | 3309 | @item{@defid{LUA_GCCOLLECT}| |
| 3310 | Performs a full garbage-collection cycle. | 3310 | Performs a full garbage-collection cycle. |
| 3311 | } | 3311 | } |
| 3312 | 3312 | ||
| 3313 | @item{@id{LUA_GCSTOP}| | 3313 | @item{@defid{LUA_GCSTOP}| |
| 3314 | Stops the garbage collector. | 3314 | Stops the garbage collector. |
| 3315 | } | 3315 | } |
| 3316 | 3316 | ||
| 3317 | @item{@id{LUA_GCRESTART}| | 3317 | @item{@defid{LUA_GCRESTART}| |
| 3318 | Restarts the garbage collector. | 3318 | Restarts the garbage collector. |
| 3319 | } | 3319 | } |
| 3320 | 3320 | ||
| 3321 | @item{@id{LUA_GCCOUNT}| | 3321 | @item{@defid{LUA_GCCOUNT}| |
| 3322 | Returns the current amount of memory (in Kbytes) in use by Lua. | 3322 | Returns 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}| |
| 3326 | Returns the remainder of dividing the current amount of bytes of | 3326 | Returns the remainder of dividing the current amount of bytes of |
| 3327 | memory in use by Lua by 1024. | 3327 | memory in use by Lua by 1024. |
| 3328 | } | 3328 | } |
| 3329 | 3329 | ||
| 3330 | @item{@id{LUA_GCSTEP}| | 3330 | @item{@defid{LUA_GCSTEP}| |
| 3331 | Performs a step of garbage collection. | 3331 | Performs a step of garbage collection. |
| 3332 | } | 3332 | } |
| 3333 | 3333 | ||
| 3334 | @item{@id{LUA_GCISRUNNING}| | 3334 | @item{@defid{LUA_GCISRUNNING}| |
| 3335 | Returns a boolean that tells whether the collector is running | 3335 | Returns 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)| |
| 3340 | Changes the collector to incremental mode | 3340 | Changes the collector to incremental mode |
| 3341 | with the given parameters @see{incmode}. | 3341 | with the given parameters @see{incmode}. |
| 3342 | Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}). | 3342 | Returns 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)| |
| 3346 | Changes the collector to generational mode | 3346 | Changes the collector to generational mode |
| 3347 | with the given parameters @see{genmode}. | 3347 | with the given parameters @see{genmode}. |
| 3348 | Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}). | 3348 | Returns 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 | |||
| 162 | assert(collectgarbage'isrunning') | 162 | assert(collectgarbage'isrunning') |
| 163 | 163 | ||
| 164 | 164 | ||
| 165 | do 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 |
| 167 | assert(collectgarbage'isrunning') | 169 | assert(collectgarbage("step")) |
| 170 | assert(collectgarbage("step")) | ||
| 171 | |||
| 172 | -- back to default value | ||
| 173 | collectgarbage("incremental", nil, 200) | ||
| 174 | end | ||
| 168 | 175 | ||
| 169 | collectgarbage(oldmode) | 176 | collectgarbage(oldmode) |
| 170 | 177 | ||
