diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-01-19 13:54:26 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-01-19 13:54:26 -0200 |
| commit | 621ef9f7675829234e75b0b3e73afc7a1a74aa16 (patch) | |
| tree | 5ced360a5af2f8dd0b57fc6849148b6dffa5c12a | |
| parent | d89a56f86921dc3c62edf0345748ba5c41b2632c (diff) | |
| download | lua-621ef9f7675829234e75b0b3e73afc7a1a74aa16.tar.gz lua-621ef9f7675829234e75b0b3e73afc7a1a74aa16.tar.bz2 lua-621ef9f7675829234e75b0b3e73afc7a1a74aa16.zip | |
better control over GC collors of upvalues
| -rw-r--r-- | lfunc.c | 12 | ||||
| -rw-r--r-- | lgc.h | 3 | ||||
| -rw-r--r-- | ltests.c | 17 |
3 files changed, 26 insertions, 6 deletions
| @@ -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 | } |
| @@ -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 | ||
| @@ -272,7 +272,13 @@ static void checkclosure (global_State *g, Closure *cl) { | |||
| 272 | static void checkstack (global_State *g, lua_State *L1) { | 272 | static 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 | |||
| 333 | int lua_checkmemory (lua_State *L) { | 340 | int 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 | ||
