diff options
-rw-r--r-- | lgc.c | 21 | ||||
-rw-r--r-- | lgc.h | 9 | ||||
-rw-r--r-- | lstate.c | 20 | ||||
-rw-r--r-- | lstate.h | 25 | ||||
-rw-r--r-- | ltests.c | 19 |
5 files changed, 47 insertions, 47 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.160 2013/09/11 12:47:48 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.161 2013/09/11 13:24:55 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -304,7 +304,7 @@ static void markbeingfnz (global_State *g) { | |||
304 | ** thread.) | 304 | ** thread.) |
305 | */ | 305 | */ |
306 | static void remarkupvals (global_State *g) { | 306 | static void remarkupvals (global_State *g) { |
307 | GCObject *thread = hvalue(&g->l_registry)->next; | 307 | GCObject *thread = g->mainthread->next; |
308 | for (; thread != NULL; thread = gch(thread)->next) { | 308 | for (; thread != NULL; thread = gch(thread)->next) { |
309 | lua_assert(!isblack(thread)); /* threads are never black */ | 309 | lua_assert(!isblack(thread)); /* threads are never black */ |
310 | if (!isgray(thread)) { /* dead thread? */ | 310 | if (!isgray(thread)) { /* dead thread? */ |
@@ -933,10 +933,9 @@ static void localmarkthread (lua_State *l) { | |||
933 | ** a thread) | 933 | ** a thread) |
934 | */ | 934 | */ |
935 | static void localmark (global_State *g) { | 935 | static void localmark (global_State *g) { |
936 | GCObject *thread = hvalue(&g->l_registry)->next; | 936 | GCObject *thread = obj2gco(g->mainthread); |
937 | for (; thread != NULL; thread = gch(thread)->next) /* traverse all threads */ | 937 | for (; thread != NULL; thread = gch(thread)->next) /* traverse all threads */ |
938 | localmarkthread(gco2th(thread)); | 938 | localmarkthread(gco2th(thread)); |
939 | localmarkthread(g->mainthread); | ||
940 | } | 939 | } |
941 | 940 | ||
942 | 941 | ||
@@ -1057,12 +1056,14 @@ void luaC_freeallobjects (lua_State *L) { | |||
1057 | separatetobefnz(g, 1); /* separate all objects with finalizers */ | 1056 | separatetobefnz(g, 1); /* separate all objects with finalizers */ |
1058 | lua_assert(g->finobj == NULL && g->localfin == NULL); | 1057 | lua_assert(g->finobj == NULL && g->localfin == NULL); |
1059 | callallpendingfinalizers(L, 0); | 1058 | callallpendingfinalizers(L, 0); |
1059 | lua_assert(g->tobefnz == NULL); | ||
1060 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ | 1060 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ |
1061 | g->gckind = KGC_NORMAL; | 1061 | g->gckind = KGC_NORMAL; |
1062 | sweepwholelist(L, &g->localgc); | ||
1062 | sweepwholelist(L, &g->localfin); /* finalizers can create objs. with fins. */ | 1063 | sweepwholelist(L, &g->localfin); /* finalizers can create objs. with fins. */ |
1063 | sweepwholelist(L, &g->finobj); | 1064 | sweepwholelist(L, &g->finobj); |
1064 | sweepwholelist(L, &g->localgc); | ||
1065 | sweepwholelist(L, &g->allgc); | 1065 | sweepwholelist(L, &g->allgc); |
1066 | sweepwholelist(L, &g->mainthread->next); | ||
1066 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ | 1067 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ |
1067 | lua_assert(g->strt.nuse == 0); | 1068 | lua_assert(g->strt.nuse == 0); |
1068 | } | 1069 | } |
@@ -1163,11 +1164,13 @@ static lu_mem singlestep (lua_State *L) { | |||
1163 | return sweepstep(L, g, GCSsweeptobefnz, &g->tobefnz); | 1164 | return sweepstep(L, g, GCSsweeptobefnz, &g->tobefnz); |
1164 | } | 1165 | } |
1165 | case GCSsweeptobefnz: { | 1166 | case GCSsweeptobefnz: { |
1166 | return sweepstep(L, g, GCSsweepmainth, NULL); | 1167 | return sweepstep(L, g, GCSsweepthreads, &g->mainthread->next); |
1168 | } | ||
1169 | case GCSsweepthreads: { | ||
1170 | return sweepstep(L, g, GCSsweepend, NULL); | ||
1167 | } | 1171 | } |
1168 | case GCSsweepmainth: { /* sweep main thread */ | 1172 | case GCSsweepend: { |
1169 | GCObject *mt = obj2gco(g->mainthread); | 1173 | makewhite(g, obj2gco(g->mainthread)); /* sweep main thread */ |
1170 | sweeplist(L, &mt, 1); | ||
1171 | checkBuffer(L); | 1174 | checkBuffer(L); |
1172 | g->gcstate = GCSpause; /* finish collection */ | 1175 | g->gcstate = GCSpause; /* finish collection */ |
1173 | return GCSWEEPCOST; | 1176 | return GCSWEEPCOST; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.72 2013/09/11 12:26:14 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.73 2013/09/11 12:47:48 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -43,12 +43,13 @@ | |||
43 | #define GCSsweepfin 4 | 43 | #define GCSsweepfin 4 |
44 | #define GCSsweepall 5 | 44 | #define GCSsweepall 5 |
45 | #define GCSsweeptobefnz 6 | 45 | #define GCSsweeptobefnz 6 |
46 | #define GCSsweepmainth 7 | 46 | #define GCSsweepthreads 7 |
47 | #define GCSpause 8 | 47 | #define GCSsweepend 8 |
48 | #define GCSpause 9 | ||
48 | 49 | ||
49 | 50 | ||
50 | #define issweepphase(g) \ | 51 | #define issweepphase(g) \ |
51 | (GCSsweeplocal <= (g)->gcstate && (g)->gcstate <= GCSsweepmainth) | 52 | (GCSsweeplocal <= (g)->gcstate && (g)->gcstate <= GCSsweepend) |
52 | 53 | ||
53 | 54 | ||
54 | /* | 55 | /* |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.111 2013/09/05 19:31:49 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.112 2013/09/11 12:26:14 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -165,14 +165,6 @@ static void init_registry (lua_State *L, global_State *g) { | |||
165 | sethvalue(L, &g->l_registry, registry); | 165 | sethvalue(L, &g->l_registry, registry); |
166 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); | 166 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); |
167 | nolocal(obj2gco(registry)); | 167 | nolocal(obj2gco(registry)); |
168 | /* registry is the first "regular" object created by a state; move it | ||
169 | from 'localgc' to 'allgc' so that it act as a "sentinel" there */ | ||
170 | lua_assert(g->allgc == NULL && | ||
171 | registry->next == NULL && | ||
172 | g->localgc == obj2gco(registry)); | ||
173 | g->allgc = g->localgc; | ||
174 | g->localgc = NULL; | ||
175 | l_setbit(registry->marked, LOCALMARK); /* mark that it is not in 'localgc' */ | ||
176 | /* registry[LUA_RIDX_MAINTHREAD] = L */ | 168 | /* registry[LUA_RIDX_MAINTHREAD] = L */ |
177 | setthvalue(L, &temp, L); /* temp = L */ | 169 | setthvalue(L, &temp, L); /* temp = L */ |
178 | luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); | 170 | luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); |
@@ -243,11 +235,11 @@ LUA_API lua_State *lua_newthread (lua_State *L) { | |||
243 | luaC_checkGC(L); | 235 | luaC_checkGC(L); |
244 | /* create new thread */ | 236 | /* create new thread */ |
245 | L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; | 237 | L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; |
246 | L1->marked = luaC_white(g) | bitmask(LOCALMARK) | bitmask(NOLOCALBIT); | 238 | L1->marked = luaC_white(g) | bit2mask(NOLOCALBIT, LOCALMARK); |
247 | L1->tt = LUA_TTHREAD; | 239 | L1->tt = LUA_TTHREAD; |
248 | /* link it after 'l_registry' */ | 240 | /* link it on list of threads */ |
249 | L1->next = hvalue(&g->l_registry)->next; | 241 | L1->next = g->mainthread->next; |
250 | hvalue(&g->l_registry)->next = obj2gco(L1); | 242 | g->mainthread->next = obj2gco(L1); |
251 | setthvalue(L, L->top, L1); | 243 | setthvalue(L, L->top, L1); |
252 | api_incr_top(L); | 244 | api_incr_top(L); |
253 | preinit_state(L1, g); | 245 | preinit_state(L1, g); |
@@ -283,7 +275,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
283 | L->next = NULL; | 275 | L->next = NULL; |
284 | L->tt = LUA_TTHREAD; | 276 | L->tt = LUA_TTHREAD; |
285 | g->currentwhite = bitmask(WHITE0BIT); | 277 | g->currentwhite = bitmask(WHITE0BIT); |
286 | L->marked = luaC_white(g) | bitmask(NOLOCALBIT); | 278 | L->marked = luaC_white(g) | bit2mask(NOLOCALBIT, LOCALMARK); |
287 | g->gckind = KGC_NORMAL; | 279 | g->gckind = KGC_NORMAL; |
288 | preinit_state(L, g); | 280 | preinit_state(L, g); |
289 | g->frealloc = f; | 281 | g->frealloc = f; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.93 2013/09/03 15:37:10 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.94 2013/09/05 19:31:49 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -16,20 +16,19 @@ | |||
16 | 16 | ||
17 | /* | 17 | /* |
18 | 18 | ||
19 | ** Some notes about garbage-collected objects: All objects in Lua must | 19 | ** Some notes about garbage-collected objects: All objects in Lua must |
20 | ** be kept somehow accessible until being freed. | 20 | ** be kept somehow accessible until being freed, so all objects always |
21 | ** belong to one (and only one) of these lists, using field 'next' of | ||
22 | ** the 'CommonHeader' for the link: | ||
21 | ** | 23 | ** |
22 | ** Lua keeps most objects linked in list g->allgc. The link uses field | 24 | ** mainthread->next: all threads; |
23 | ** 'next' of the CommonHeader. Threads (except the main one) ar kept | 25 | ** localgc: all local objects not marked for finalization; |
24 | ** at the end of the 'allgc' list, after the 'l_registry' (which is | 26 | ** localfin: all local objects marked for finalization; |
25 | ** the first object to be added to the list). | 27 | ** allgc: all non local objects not marked for finalization; |
26 | ** | 28 | ** finobj: all non local objects marked for finalization; |
27 | ** List 'fixedgc' keep objects that are not to be collected (currently | 29 | ** tobefnz: all objects ready to be finalized; |
30 | ** fixedgc: all objects that are not to be collected (currently | ||
28 | ** only small strings, such as reserved words). | 31 | ** only small strings, such as reserved words). |
29 | ** | ||
30 | ** Live objects with finalizers are kept in the list g->finobj. The | ||
31 | ** list g->tobefnz links all objects being finalized. In particular, an | ||
32 | ** object has its FINALIZEDBIT set iff it is in one of these lists. | ||
33 | 32 | ||
34 | */ | 33 | */ |
35 | 34 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 2.156 2013/09/11 12:26:14 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.157 2013/09/11 12:47:48 roberto Exp roberto $ |
3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -423,7 +423,6 @@ int lua_checkmemory (lua_State *L) { | |||
423 | global_State *g = G(L); | 423 | global_State *g = G(L); |
424 | GCObject *o; | 424 | GCObject *o; |
425 | int maybedead; | 425 | int maybedead; |
426 | int isthread; | ||
427 | if (keepinvariant(g)) { | 426 | if (keepinvariant(g)) { |
428 | lua_assert(!iswhite(obj2gco(g->mainthread))); | 427 | lua_assert(!iswhite(obj2gco(g->mainthread))); |
429 | lua_assert(!iswhite(gcvalue(&g->l_registry))); | 428 | lua_assert(!iswhite(gcvalue(&g->l_registry))); |
@@ -443,14 +442,20 @@ int lua_checkmemory (lua_State *L) { | |||
443 | /* check 'allgc' list */ | 442 | /* check 'allgc' list */ |
444 | checkgray(g, g->allgc); | 443 | checkgray(g, g->allgc); |
445 | maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSsweepall); | 444 | maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSsweepall); |
446 | isthread = 0; /* not traversing threads (yet) */ | ||
447 | for (o = g->allgc; o != NULL; o = gch(o)->next) { | 445 | for (o = g->allgc; o != NULL; o = gch(o)->next) { |
448 | if (gch(o)->tt == LUA_TTHREAD) isthread = 1; /* now travesing threads... */ | ||
449 | else lua_assert(!isthread); /* ... and only threads */ | ||
450 | checkobject(g, o, maybedead); | 446 | checkobject(g, o, maybedead); |
451 | lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); | 447 | lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); |
452 | lua_assert(testbit(o->gch.marked, NOLOCALBIT)); | 448 | lua_assert(testbit(o->gch.marked, NOLOCALBIT)); |
453 | } | 449 | } |
450 | /* check thread list */ | ||
451 | checkgray(g, obj2gco(g->mainthread)); | ||
452 | maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSsweepthreads); | ||
453 | for (o = obj2gco(g->mainthread); o != NULL; o = gch(o)->next) { | ||
454 | checkobject(g, o, maybedead); | ||
455 | lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); | ||
456 | lua_assert(testbit(o->gch.marked, NOLOCALBIT)); | ||
457 | lua_assert(gch(o)->tt == LUA_TTHREAD); | ||
458 | } | ||
454 | /* check 'localfin' list */ | 459 | /* check 'localfin' list */ |
455 | checkgray(g, g->localfin); | 460 | checkgray(g, g->localfin); |
456 | for (o = g->localfin; o != NULL; o = gch(o)->next) { | 461 | for (o = g->localfin; o != NULL; o = gch(o)->next) { |
@@ -650,8 +655,8 @@ static int gc_local (lua_State *L) { | |||
650 | 655 | ||
651 | static int gc_state (lua_State *L) { | 656 | static int gc_state (lua_State *L) { |
652 | static const char *statenames[] = {"propagate", "atomic", | 657 | static const char *statenames[] = {"propagate", "atomic", |
653 | "sweeplocal", "sweeplocfin", "sweepfin", "sweepall", "sweeptobefnz", | 658 | "sweeplocal", "sweeplocfin", "sweepfin", "sweepall", |
654 | "sweepmainth", "pause", ""}; | 659 | "sweeptobefnz", "sweepthreads", "sweepend", "pause", ""}; |
655 | int option = luaL_checkoption(L, 1, "", statenames); | 660 | int option = luaL_checkoption(L, 1, "", statenames); |
656 | if (option == GCSpause + 1) { | 661 | if (option == GCSpause + 1) { |
657 | lua_pushstring(L, statenames[G(L)->gcstate]); | 662 | lua_pushstring(L, statenames[G(L)->gcstate]); |