diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 50 |
1 files changed, 42 insertions, 8 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.96 2010/05/17 20:39:31 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.97 2010/06/02 18:36:58 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 | */ |
@@ -127,7 +127,7 @@ static int iscleared (const TValue *o, int iskey) { | |||
127 | ** barrier that moves collector forward, that is, mark the white object | 127 | ** barrier that moves collector forward, that is, mark the white object |
128 | ** being pointed by a black object. | 128 | ** being pointed by a black object. |
129 | */ | 129 | */ |
130 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | 130 | void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { |
131 | global_State *g = G(L); | 131 | global_State *g = G(L); |
132 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 132 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
133 | lua_assert(isgenerational(g) || g->gcstate != GCSpause); | 133 | lua_assert(isgenerational(g) || g->gcstate != GCSpause); |
@@ -143,19 +143,32 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | |||
143 | 143 | ||
144 | /* | 144 | /* |
145 | ** barrier that moves collector backward, that is, mark the black object | 145 | ** barrier that moves collector backward, that is, mark the black object |
146 | ** pointing to a white object as gray again. | 146 | ** pointing to a white object as gray again. (Current implementation |
147 | ** only works for tables; access to 'gclist' is not uniform across | ||
148 | ** different types.) | ||
147 | */ | 149 | */ |
148 | void luaC_barrierback (lua_State *L, Table *t) { | 150 | void luaC_barrierback_ (lua_State *L, GCObject *o) { |
149 | global_State *g = G(L); | 151 | global_State *g = G(L); |
150 | GCObject *o = obj2gco(t); | ||
151 | lua_assert(isblack(o) && !isdead(g, o)); | 152 | lua_assert(isblack(o) && !isdead(g, o)); |
152 | black2gray(o); /* make table gray (again) */ | 153 | black2gray(o); /* make object gray (again) */ |
153 | t->gclist = g->grayagain; | 154 | gco2t(o)->gclist = g->grayagain; |
154 | g->grayagain = o; | 155 | g->grayagain = o; |
155 | } | 156 | } |
156 | 157 | ||
157 | 158 | ||
158 | /* | 159 | /* |
160 | ** barrier for prototypes | ||
161 | */ | ||
162 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, GCObject *p) { | ||
163 | global_State *g = G(L); | ||
164 | lua_assert(isblack(p)); | ||
165 | black2gray(p); /* make object gray (again) */ | ||
166 | gco2p(p)->gclist = g->clearcache; | ||
167 | g->clearcache = p; | ||
168 | } | ||
169 | |||
170 | |||
171 | /* | ||
159 | ** check color (and invariants) for an upvalue that was closed, | 172 | ** check color (and invariants) for an upvalue that was closed, |
160 | ** i.e., moved into the 'allgc' list | 173 | ** i.e., moved into the 'allgc' list |
161 | */ | 174 | */ |
@@ -299,7 +312,7 @@ static void remarkupvals (global_State *g) { | |||
299 | static void markroot (lua_State *L) { | 312 | static void markroot (lua_State *L) { |
300 | global_State *g = G(L); | 313 | global_State *g = G(L); |
301 | g->gray = g->grayagain = NULL; | 314 | g->gray = g->grayagain = NULL; |
302 | g->weak = g->allweak = g->ephemeron = NULL; | 315 | g->weak = g->allweak = g->ephemeron = g->clearcache = NULL; |
303 | markobject(g, g->mainthread); | 316 | markobject(g, g->mainthread); |
304 | markvalue(g, &g->l_registry); | 317 | markvalue(g, &g->l_registry); |
305 | markmt(g); | 318 | markmt(g); |
@@ -409,8 +422,19 @@ static int traversetable (global_State *g, Table *h) { | |||
409 | } | 422 | } |
410 | 423 | ||
411 | 424 | ||
425 | /* | ||
426 | ** if prototype's cached closure is not marked, erase it so it | ||
427 | ** can be collected | ||
428 | */ | ||
429 | static void checkcache (Proto *p) { | ||
430 | if (p->cache && iswhite(obj2gco(p->cache))) | ||
431 | p->cache = NULL; /* allow cache to be collected */ | ||
432 | } | ||
433 | |||
434 | |||
412 | static int traverseproto (global_State *g, Proto *f) { | 435 | static int traverseproto (global_State *g, Proto *f) { |
413 | int i; | 436 | int i; |
437 | checkcache(f); | ||
414 | stringmark(f->source); | 438 | stringmark(f->source); |
415 | for (i = 0; i < f->sizek; i++) /* mark literals */ | 439 | for (i = 0; i < f->sizek; i++) /* mark literals */ |
416 | markvalue(g, &f->k[i]); | 440 | markvalue(g, &f->k[i]); |
@@ -534,6 +558,15 @@ static void convergeephemerons (global_State *g) { | |||
534 | */ | 558 | */ |
535 | 559 | ||
536 | /* | 560 | /* |
561 | ** clear cache field in all prototypes in list 'l' | ||
562 | */ | ||
563 | static void clearproto (GCObject *l) { | ||
564 | for (; l != NULL; l = gco2p(l)->gclist) | ||
565 | checkcache(gco2p(l)); | ||
566 | } | ||
567 | |||
568 | |||
569 | /* | ||
537 | ** clear collected entries from all weaktables in list 'l' | 570 | ** clear collected entries from all weaktables in list 'l' |
538 | */ | 571 | */ |
539 | static void cleartable (GCObject *l) { | 572 | static void cleartable (GCObject *l) { |
@@ -845,6 +878,7 @@ static void atomic (lua_State *L) { | |||
845 | cleartable(g->weak); | 878 | cleartable(g->weak); |
846 | cleartable(g->ephemeron); | 879 | cleartable(g->ephemeron); |
847 | cleartable(g->allweak); | 880 | cleartable(g->allweak); |
881 | clearproto(g->clearcache); | ||
848 | g->sweepstrgc = 0; /* prepare to sweep strings */ | 882 | g->sweepstrgc = 0; /* prepare to sweep strings */ |
849 | g->gcstate = GCSsweepstring; | 883 | g->gcstate = GCSsweepstring; |
850 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 884 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |