aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc.c135
-rw-r--r--lgc.h6
-rw-r--r--lstate.c6
-rw-r--r--lstate.h6
4 files changed, 98 insertions, 55 deletions
diff --git a/lgc.c b/lgc.c
index 7c1aea5f..3dc486d3 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.39 2006/07/11 15:53:29 roberto Exp roberto $ 2** $Id: lgc.c,v 2.40 2006/09/11 14:07:24 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*/
@@ -44,10 +44,6 @@
44#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) 44#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT)
45 45
46 46
47#define KEYWEAK bitmask(KEYWEAKBIT)
48#define VALUEWEAK bitmask(VALUEWEAKBIT)
49
50
51 47
52#define markvalue(g,o) { checkconsistency(o); \ 48#define markvalue(g,o) { checkconsistency(o); \
53 if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } 49 if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
@@ -59,6 +55,12 @@
59#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) 55#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
60 56
61 57
58static void linktable (Table *h, GCObject **p) {
59 h->gclist = *p;
60 *p = obj2gco(h);
61}
62
63
62static void removeentry (Node *n) { 64static void removeentry (Node *n) {
63 lua_assert(ttisnil(gval(n))); 65 lua_assert(ttisnil(gval(n)));
64 if (iscollectable(gkey(n))) 66 if (iscollectable(gkey(n)))
@@ -93,8 +95,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
93 break; 95 break;
94 } 96 }
95 case LUA_TTABLE: { 97 case LUA_TTABLE: {
96 gco2h(o)->gclist = g->gray; 98 linktable(gco2h(o), &g->gray);
97 g->gray = o;
98 break; 99 break;
99 } 100 }
100 case LUA_TTHREAD: { 101 case LUA_TTHREAD: {
@@ -155,30 +156,48 @@ size_t luaC_separateudata (lua_State *L, int all) {
155} 156}
156 157
157 158
158static int traversetable (global_State *g, Table *h) { 159static void traverseweakvalue (global_State *g, Table *h) {
159 int i; 160 int i;
160 int weakkey = 0; 161 linktable(h, &g->weakvalue);
161 int weakvalue = 0; 162 i = sizenode(h);
162 const TValue *mode; 163 while (i--) {
163 markobject(g, h->metatable); 164 Node *n = gnode(h, i);
164 mode = gfasttm(g, h->metatable, TM_MODE); 165 lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
165 if (mode && ttisstring(mode)) { /* is there a weak mode? */ 166 if (ttisnil(gval(n)))
166 weakkey = (strchr(svalue(mode), 'k') != NULL); 167 removeentry(n); /* remove empty entries */
167 weakvalue = (strchr(svalue(mode), 'v') != NULL); 168 else {
168 if (weakkey || weakvalue) { /* is really weak? */ 169 lua_assert(!ttisnil(gkey(n)));
169 h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ 170 markvalue(g, gkey(n));
170 h->marked |= cast_byte((weakkey << KEYWEAKBIT) |
171 (weakvalue << VALUEWEAKBIT));
172 h->gclist = g->weak; /* must be cleared after GC, ... */
173 g->weak = obj2gco(h); /* ... so put in the appropriate list */
174 } 171 }
175 } 172 }
176 if (weakkey && weakvalue) return 1; 173}
177 if (!weakvalue) { 174
178 i = h->sizearray; 175
179 while (i--) 176static void traverseephemeron (global_State *g, Table *h) {
180 markvalue(g, &h->array[i]); 177 int i;
178 linktable(h, &g->weakkey);
179 i = h->sizearray;
180 while (i--) /* mark array part (numeric keys are 'strong') */
181 markvalue(g, &h->array[i]);
182 i = sizenode(h);
183 while (i--) {
184 Node *n = gnode(h, i);
185 lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
186 if (ttisnil(gval(n)))
187 removeentry(n); /* remove empty entries */
188 else {
189 lua_assert(!ttisnil(gkey(n)));
190 markvalue(g, gval(n));
191 }
181 } 192 }
193}
194
195
196static void traversestrongtable (global_State *g, Table *h) {
197 int i;
198 i = h->sizearray;
199 while (i--)
200 markvalue(g, &h->array[i]);
182 i = sizenode(h); 201 i = sizenode(h);
183 while (i--) { 202 while (i--) {
184 Node *n = gnode(h, i); 203 Node *n = gnode(h, i);
@@ -187,11 +206,33 @@ static int traversetable (global_State *g, Table *h) {
187 removeentry(n); /* remove empty entries */ 206 removeentry(n); /* remove empty entries */
188 else { 207 else {
189 lua_assert(!ttisnil(gkey(n))); 208 lua_assert(!ttisnil(gkey(n)));
190 if (!weakkey) markvalue(g, gkey(n)); 209 markvalue(g, gkey(n));
191 if (!weakvalue) markvalue(g, gval(n)); 210 markvalue(g, gval(n));
192 } 211 }
193 } 212 }
194 return weakkey || weakvalue; 213}
214
215
216static void traversetable (global_State *g, Table *h) {
217 const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
218 markobject(g, h->metatable);
219 if (mode && ttisstring(mode)) { /* is there a weak mode? */
220 int weakkey = (strchr(svalue(mode), 'k') != NULL);
221 int weakvalue = (strchr(svalue(mode), 'v') != NULL);
222 if (weakkey || weakvalue) { /* is really weak? */
223 black2gray(obj2gco(h)); /* keep table gray */
224 if (!weakkey) /* strong keys? */
225 traverseweakvalue(g, h);
226 else if (!weakvalue) /* strong values? */
227 traverseephemeron(g, h);
228 else {
229 lua_assert(weakkey && weakvalue); /* nothing to traverse now */
230 linktable(h, &g->weakkeyvalue);
231 }
232 return;
233 } /* else go through */
234 }
235 traversestrongtable(g, h);
195} 236}
196 237
197 238
@@ -282,8 +323,7 @@ static l_mem propagatemark (global_State *g) {
282 case LUA_TTABLE: { 323 case LUA_TTABLE: {
283 Table *h = gco2h(o); 324 Table *h = gco2h(o);
284 g->gray = h->gclist; 325 g->gray = h->gclist;
285 if (traversetable(g, h)) /* table is weak? */ 326 traversetable(g, h);
286 black2gray(o); /* keep it gray */
287 return sizeof(Table) + sizeof(TValue) * h->sizearray + 327 return sizeof(Table) + sizeof(TValue) * h->sizearray +
288 sizeof(Node) * sizenode(h); 328 sizeof(Node) * sizenode(h);
289 } 329 }
@@ -352,14 +392,10 @@ static void cleartable (GCObject *l) {
352 while (l) { 392 while (l) {
353 Table *h = gco2h(l); 393 Table *h = gco2h(l);
354 int i = h->sizearray; 394 int i = h->sizearray;
355 lua_assert(testbit(h->marked, VALUEWEAKBIT) || 395 while (i--) {
356 testbit(h->marked, KEYWEAKBIT)); 396 TValue *o = &h->array[i];
357 if (testbit(h->marked, VALUEWEAKBIT)) { 397 if (iscleared(o, 0)) /* value was collected? */
358 while (i--) { 398 setnilvalue(o); /* remove value */
359 TValue *o = &h->array[i];
360 if (iscleared(o, 0)) /* value was collected? */
361 setnilvalue(o); /* remove value */
362 }
363 } 399 }
364 i = sizenode(h); 400 i = sizenode(h);
365 while (i--) { 401 while (i--) {
@@ -516,7 +552,7 @@ static void markroot (lua_State *L) {
516 global_State *g = G(L); 552 global_State *g = G(L);
517 g->gray = NULL; 553 g->gray = NULL;
518 g->grayagain = NULL; 554 g->grayagain = NULL;
519 g->weak = NULL; 555 g->weakvalue = g->weakkey = g->weakkeyvalue = NULL;
520 markobject(g, g->mainthread); 556 markobject(g, g->mainthread);
521 /* make global table be traversed before main stack */ 557 /* make global table be traversed before main stack */
522 markvalue(g, gt(g->mainthread)); 558 markvalue(g, gt(g->mainthread));
@@ -543,13 +579,17 @@ static void atomic (lua_State *L) {
543 remarkupvals(g); 579 remarkupvals(g);
544 /* traverse objects cautch by write barrier and by 'remarkupvals' */ 580 /* traverse objects cautch by write barrier and by 'remarkupvals' */
545 propagateall(g); 581 propagateall(g);
546 /* remark weak tables */ 582 /* remark value-weak tables */
547 g->gray = g->weak; 583 g->gray = g->weakvalue;
548 g->weak = NULL; 584 g->weakvalue = NULL;
549 lua_assert(!iswhite(obj2gco(g->mainthread))); 585 lua_assert(!iswhite(obj2gco(g->mainthread)));
550 markobject(g, L); /* mark running thread */ 586 markobject(g, L); /* mark running thread */
551 markmt(g); /* mark basic metatables (again) */ 587 markmt(g); /* mark basic metatables (again) */
552 propagateall(g); 588 propagateall(g);
589 /* remark key-weak tables */
590 g->gray = g->weakkey;
591 g->weakkey = NULL;
592 propagateall(g);
553 /* remark gray again */ 593 /* remark gray again */
554 g->gray = g->grayagain; 594 g->gray = g->grayagain;
555 g->grayagain = NULL; 595 g->grayagain = NULL;
@@ -557,7 +597,10 @@ static void atomic (lua_State *L) {
557 udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ 597 udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */
558 marktmu(g); /* mark `preserved' userdata */ 598 marktmu(g); /* mark `preserved' userdata */
559 udsize += propagateall(g); /* remark, to propagate `preserveness' */ 599 udsize += propagateall(g); /* remark, to propagate `preserveness' */
560 cleartable(g->weak); /* remove collected objects from weak tables */ 600 /* remove collected objects from weak tables */
601 cleartable(g->weakvalue);
602 cleartable(g->weakkey);
603 cleartable(g->weakkeyvalue);
561 /* flip current white */ 604 /* flip current white */
562 g->currentwhite = cast_byte(otherwhite(g)); 605 g->currentwhite = cast_byte(otherwhite(g));
563 g->sweepstrgc = 0; 606 g->sweepstrgc = 0;
@@ -656,7 +699,7 @@ void luaC_fullgc (lua_State *L, int isemergency) {
656 /* reset other collector lists */ 699 /* reset other collector lists */
657 g->gray = NULL; 700 g->gray = NULL;
658 g->grayagain = NULL; 701 g->grayagain = NULL;
659 g->weak = NULL; 702 g->weakvalue = g->weakkey = g->weakkeyvalue = NULL;
660 g->gcstate = GCSsweepstring; 703 g->gcstate = GCSsweepstring;
661 } 704 }
662 lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); 705 lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);
diff --git a/lgc.h b/lgc.h
index bc220345..0b7be15e 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 2.15 2005/08/24 16:15:49 roberto Exp roberto $ 2** $Id: lgc.h,v 2.16 2006/07/11 15:53:29 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*/
@@ -44,8 +44,6 @@
44** bit 1 - object is white (type 1) 44** bit 1 - object is white (type 1)
45** bit 2 - object is black 45** bit 2 - object is black
46** bit 3 - for userdata: has been finalized 46** bit 3 - for userdata: has been finalized
47** bit 3 - for tables: has weak keys
48** bit 4 - for tables: has weak values
49** bit 5 - object is fixed (should not be collected) 47** bit 5 - object is fixed (should not be collected)
50** bit 6 - object is "super" fixed (only the main thread) 48** bit 6 - object is "super" fixed (only the main thread)
51*/ 49*/
@@ -55,8 +53,6 @@
55#define WHITE1BIT 1 53#define WHITE1BIT 1
56#define BLACKBIT 2 54#define BLACKBIT 2
57#define FINALIZEDBIT 3 55#define FINALIZEDBIT 3
58#define KEYWEAKBIT 3
59#define VALUEWEAKBIT 4
60#define FIXEDBIT 5 56#define FIXEDBIT 5
61#define SFIXEDBIT 6 57#define SFIXEDBIT 6
62#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) 58#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
diff --git a/lstate.c b/lstate.c
index dc2827c3..109f3f3f 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.39 2006/09/11 14:07:24 roberto Exp roberto $ 2** $Id: lstate.c,v 2.40 2006/10/10 17:40:17 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*/
@@ -182,7 +182,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
182 g->sweepgc = &g->rootgc; 182 g->sweepgc = &g->rootgc;
183 g->gray = NULL; 183 g->gray = NULL;
184 g->grayagain = NULL; 184 g->grayagain = NULL;
185 g->weak = NULL; 185 g->weakvalue = NULL;
186 g->weakkey = NULL;
187 g->weakkeyvalue = NULL;
186 g->tmudata = NULL; 188 g->tmudata = NULL;
187 g->totalbytes = sizeof(LG); 189 g->totalbytes = sizeof(LG);
188 g->gcpause = LUAI_GCPAUSE; 190 g->gcpause = LUAI_GCPAUSE;
diff --git a/lstate.h b/lstate.h
index 2cbcc7ce..393f477a 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.27 2006/09/19 13:57:50 roberto Exp roberto $ 2** $Id: lstate.h,v 2.28 2007/02/07 17:48:52 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*/
@@ -78,7 +78,9 @@ typedef struct global_State {
78 GCObject **sweepgc; /* position of sweep in `rootgc' */ 78 GCObject **sweepgc; /* position of sweep in `rootgc' */
79 GCObject *gray; /* list of gray objects */ 79 GCObject *gray; /* list of gray objects */
80 GCObject *grayagain; /* list of objects to be traversed atomically */ 80 GCObject *grayagain; /* list of objects to be traversed atomically */
81 GCObject *weak; /* list of weak tables (to be cleared) */ 81 GCObject *weakvalue; /* list of value-weak tables */
82 GCObject *weakkey; /* list of key-weak tables */
83 GCObject *weakkeyvalue; /* list of all-weak tables */
82 GCObject *tmudata; /* last element of list of userdata to be GC */ 84 GCObject *tmudata; /* last element of list of userdata to be GC */
83 Mbuffer buff; /* temporary buffer for string concatentation */ 85 Mbuffer buff; /* temporary buffer for string concatentation */
84 lu_mem GCthreshold; 86 lu_mem GCthreshold;