aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-01-19 13:54:26 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-01-19 13:54:26 -0200
commit621ef9f7675829234e75b0b3e73afc7a1a74aa16 (patch)
tree5ced360a5af2f8dd0b57fc6849148b6dffa5c12a
parentd89a56f86921dc3c62edf0345748ba5c41b2632c (diff)
downloadlua-621ef9f7675829234e75b0b3e73afc7a1a74aa16.tar.gz
lua-621ef9f7675829234e75b0b3e73afc7a1a74aa16.tar.bz2
lua-621ef9f7675829234e75b0b3e73afc7a1a74aa16.zip
better control over GC collors of upvalues
-rw-r--r--lfunc.c12
-rw-r--r--lgc.h3
-rw-r--r--ltests.c17
3 files changed, 26 insertions, 6 deletions
diff --git a/lfunc.c b/lfunc.c
index 3171c5ec..65d70cfb 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -56,7 +56,11 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
56 UpVal *uv; 56 UpVal *uv;
57 while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { 57 while ((p = ngcotouv(*pp)) != NULL && p->v >= level) {
58 lua_assert(p->v != &p->u.value); 58 lua_assert(p->v != &p->u.value);
59 if (p->v == level) return p; 59 if (p->v == level) { /* found a corresponding upvalue? */
60 if (isdead(G(L), obj2gco(p))) /* is it dead? */
61 changewhite(obj2gco(p)); /* ressurect it */
62 return p;
63 }
60 pp = &p->next; 64 pp = &p->next;
61 } 65 }
62 uv = luaM_new(L, UpVal); /* not found: create a new one */ 66 uv = luaM_new(L, UpVal); /* not found: create a new one */
@@ -65,8 +69,6 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
65 uv->v = level; /* current value lives in the stack */ 69 uv->v = level; /* current value lives in the stack */
66 uv->next = *pp; /* chain it in the proper position */ 70 uv->next = *pp; /* chain it in the proper position */
67 *pp = obj2gco(uv); 71 *pp = obj2gco(uv);
68 lua_assert(g->uvhead.u.l.next->u.l.prev == &g->uvhead &&
69 g->uvhead.u.l.prev->u.l.next == &g->uvhead);
70 uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ 72 uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */
71 uv->u.l.next = g->uvhead.u.l.next; 73 uv->u.l.next = g->uvhead.u.l.next;
72 uv->u.l.next->u.l.prev = uv; 74 uv->u.l.next->u.l.prev = uv;
@@ -102,6 +104,10 @@ void luaF_close (lua_State *L, StkId level) {
102 else { 104 else {
103 unlinkupval(uv); 105 unlinkupval(uv);
104 setobj(L, &uv->u.value, uv->v); 106 setobj(L, &uv->u.value, uv->v);
107 if (isgray(o)) {
108 gray2black(o); /* closed upvalues are never gray */
109 luaC_barrier(L, uv, uv->v);
110 }
105 uv->v = &uv->u.value; /* now current value lives here */ 111 uv->v = &uv->u.value; /* now current value lives here */
106 luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ 112 luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
107 } 113 }
diff --git a/lgc.h b/lgc.h
index f8a18782..bec5a728 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 2.8 2004/08/30 13:44:44 roberto Exp roberto $ 2** $Id: lgc.h,v 2.9 2004/09/15 20:38:15 roberto Exp $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -66,6 +66,7 @@
66#define isdead(g,v) ((v)->gch.marked & otherwhite(g)) 66#define isdead(g,v) ((v)->gch.marked & otherwhite(g))
67 67
68#define changewhite(x) ((x)->gch.marked ^= bit2mask(WHITE0BIT, WHITE1BIT)) 68#define changewhite(x) ((x)->gch.marked ^= bit2mask(WHITE0BIT, WHITE1BIT))
69#define gray2black(x) setbit((x)->gch.marked, BLACKBIT)
69 70
70#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) 71#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
71 72
diff --git a/ltests.c b/ltests.c
index e99b432f..8686fa73 100644
--- a/ltests.c
+++ b/ltests.c
@@ -272,7 +272,13 @@ static void checkclosure (global_State *g, Closure *cl) {
272static void checkstack (global_State *g, lua_State *L1) { 272static void checkstack (global_State *g, lua_State *L1) {
273 StkId o; 273 StkId o;
274 CallInfo *ci; 274 CallInfo *ci;
275 GCObject *uvo;
275 lua_assert(!isdead(g, obj2gco(L1))); 276 lua_assert(!isdead(g, obj2gco(L1)));
277 for (uvo = L1->openupval; uvo != NULL; uvo = uvo->gch.next) {
278 UpVal *uv = gco2uv(uvo);
279 lua_assert(uv->v != &uv->u.value); /* must be open */
280 lua_assert(!isblack(uvo)); /* open upvalues cannot be black */
281 }
276 checkliveness(g, gt(L1)); 282 checkliveness(g, gt(L1));
277 if (L1->base_ci) { 283 if (L1->base_ci) {
278 for (ci = L1->base_ci; ci <= L1->ci; ci++) 284 for (ci = L1->base_ci; ci <= L1->ci; ci++)
@@ -300,6 +306,7 @@ printf(">>> %d %s %02x\n", g->gcstate, luaT_typenames[o->gch.tt], o->gch.marke
300 case LUA_TUPVAL: { 306 case LUA_TUPVAL: {
301 UpVal *uv = gco2uv(o); 307 UpVal *uv = gco2uv(o);
302 lua_assert(uv->v == &uv->u.value); /* must be closed */ 308 lua_assert(uv->v == &uv->u.value); /* must be closed */
309 lua_assert(!isgray(o)); /* closed upvalues are never gray */
303 checkvalref(g, o, uv->v); 310 checkvalref(g, o, uv->v);
304 break; 311 break;
305 } 312 }
@@ -333,14 +340,20 @@ printf(">>> %d %s %02x\n", g->gcstate, luaT_typenames[o->gch.tt], o->gch.marke
333int lua_checkmemory (lua_State *L) { 340int lua_checkmemory (lua_State *L) {
334 global_State *g = G(L); 341 global_State *g = G(L);
335 GCObject *o; 342 GCObject *o;
343 UpVal *uv;
336 checkstack(g, g->mainthread); 344 checkstack(g, g->mainthread);
337 for (o = g->rootgc; o != obj2gco(g->mainthread); o = o->gch.next) 345 for (o = g->rootgc; o != obj2gco(g->mainthread); o = o->gch.next)
338 checkobject(g, o); 346 checkobject(g, o);
339 checkobject(g, obj2gco(g->mainthread)); 347 for (o = o->gch.next; o != NULL; o = o->gch.next) {
340 for (o = g->mainthread->next; o != NULL; o = o->gch.next) {
341 lua_assert(o->gch.tt == LUA_TUSERDATA); 348 lua_assert(o->gch.tt == LUA_TUSERDATA);
342 checkobject(g, o); 349 checkobject(g, o);
343 } 350 }
351 for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
352 lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
353 lua_assert(uv->v != &uv->u.value); /* must be open */
354 lua_assert(!isblack(obj2gco(uv))); /* open upvalues are never black */
355 checkvalref(g, obj2gco(uv), uv->v);
356 }
344 return 0; 357 return 0;
345} 358}
346 359