diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-11-17 17:50:05 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-11-17 17:50:05 -0200 |
commit | ab7d9bfd0c38f1dd8eda40ae3c1f1c686564a92d (patch) | |
tree | e7f5231cc02b89b2507ad846d5d547e35e9c4153 /lgc.c | |
parent | 921b1723e2fddde0382143b28b5be3b7128204b8 (diff) | |
download | lua-ab7d9bfd0c38f1dd8eda40ae3c1f1c686564a92d.tar.gz lua-ab7d9bfd0c38f1dd8eda40ae3c1f1c686564a92d.tar.bz2 lua-ab7d9bfd0c38f1dd8eda40ae3c1f1c686564a92d.zip |
cleaner code for manipulation of `marked' field
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 70 |
1 files changed, 32 insertions, 38 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.176 2003/07/29 19:25:37 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.177 2003/08/27 21:01:44 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 | */ |
@@ -29,45 +29,38 @@ typedef struct GCState { | |||
29 | } GCState; | 29 | } GCState; |
30 | 30 | ||
31 | 31 | ||
32 | /* | ||
33 | ** some userful bit tricks | ||
34 | */ | ||
35 | #define setbit(x,b) ((x) |= (1<<(b))) | ||
36 | #define resetbit(x,b) ((x) &= cast(lu_byte, ~(1<<(b)))) | ||
37 | #define testbit(x,b) ((x) & (1<<(b))) | ||
38 | 32 | ||
39 | #define unmark(x) resetbit((x)->gch.marked, 0) | 33 | #define unblack(x) resetbit((x)->gch.marked, BLACKBIT) |
40 | #define ismarked(x) ((x)->gch.marked & ((1<<4)|1)) | 34 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) |
35 | #define blacken(x) setbit((x)->gch.marked, BLACKBIT) | ||
41 | 36 | ||
42 | #define stringmark(s) setbit((s)->tsv.marked, 0) | 37 | #define stringmark(s) setbit((s)->tsv.marked, BLACKBIT) |
43 | 38 | ||
44 | 39 | ||
45 | #define isfinalized(u) (!testbit((u)->uv.marked, 1)) | 40 | #define isfinalized(u) testbit((u)->uv.marked, FINALIZEDBIT) |
46 | #define markfinalized(u) resetbit((u)->uv.marked, 1) | 41 | #define markfinalized(u) setbit((u)->uv.marked, FINALIZEDBIT) |
47 | 42 | ||
48 | 43 | ||
49 | #define KEYWEAKBIT 1 | 44 | #define KEYWEAK bitmask(KEYWEAKBIT) |
50 | #define VALUEWEAKBIT 2 | 45 | #define VALUEWEAK bitmask(VALUEWEAKBIT) |
51 | #define KEYWEAK (1<<KEYWEAKBIT) | ||
52 | #define VALUEWEAK (1<<VALUEWEAKBIT) | ||
53 | 46 | ||
54 | 47 | ||
55 | 48 | ||
56 | #define markobject(st,o) { checkconsistency(o); \ | 49 | #define markobject(st,o) { checkconsistency(o); \ |
57 | if (iscollectable(o) && !ismarked(gcvalue(o))) reallymarkobject(st,gcvalue(o)); } | 50 | if (iscollectable(o) && !isblack(gcvalue(o))) reallymarkobject(st,gcvalue(o)); } |
58 | 51 | ||
59 | #define condmarkobject(st,o,c) { checkconsistency(o); \ | 52 | #define condmarkobject(st,o,c) { checkconsistency(o); \ |
60 | if (iscollectable(o) && !ismarked(gcvalue(o)) && (c)) \ | 53 | if (iscollectable(o) && !isblack(gcvalue(o)) && (c)) \ |
61 | reallymarkobject(st,gcvalue(o)); } | 54 | reallymarkobject(st,gcvalue(o)); } |
62 | 55 | ||
63 | #define markvalue(st,t) { if (!ismarked(valtogco(t))) \ | 56 | #define markvalue(st,t) { if (!isblack(valtogco(t))) \ |
64 | reallymarkobject(st, valtogco(t)); } | 57 | reallymarkobject(st, valtogco(t)); } |
65 | 58 | ||
66 | 59 | ||
67 | 60 | ||
68 | static void reallymarkobject (GCState *st, GCObject *o) { | 61 | static void reallymarkobject (GCState *st, GCObject *o) { |
69 | lua_assert(!ismarked(o)); | 62 | lua_assert(!isblack(o)); |
70 | setbit(o->gch.marked, 0); /* mark object */ | 63 | blacken(o); |
71 | switch (o->gch.tt) { | 64 | switch (o->gch.tt) { |
72 | case LUA_TUSERDATA: { | 65 | case LUA_TUSERDATA: { |
73 | markvalue(st, gcotou(o)->uv.metatable); | 66 | markvalue(st, gcotou(o)->uv.metatable); |
@@ -101,7 +94,7 @@ static void reallymarkobject (GCState *st, GCObject *o) { | |||
101 | static void marktmu (GCState *st) { | 94 | static void marktmu (GCState *st) { |
102 | GCObject *u; | 95 | GCObject *u; |
103 | for (u = st->g->tmudata; u; u = u->gch.next) { | 96 | for (u = st->g->tmudata; u; u = u->gch.next) { |
104 | unmark(u); /* may be marked, if left from previous GC */ | 97 | unblack(u); /* may be marked, if left from previous GC */ |
105 | reallymarkobject(st, u); | 98 | reallymarkobject(st, u); |
106 | } | 99 | } |
107 | } | 100 | } |
@@ -116,7 +109,7 @@ size_t luaC_separateudata (lua_State *L) { | |||
116 | GCObject **lastcollected = &collected; | 109 | GCObject **lastcollected = &collected; |
117 | while ((curr = *p) != NULL) { | 110 | while ((curr = *p) != NULL) { |
118 | lua_assert(curr->gch.tt == LUA_TUSERDATA); | 111 | lua_assert(curr->gch.tt == LUA_TUSERDATA); |
119 | if (ismarked(curr) || isfinalized(gcotou(curr))) | 112 | if (isblack(curr) || isfinalized(gcotou(curr))) |
120 | p = &curr->gch.next; /* don't bother with them */ | 113 | p = &curr->gch.next; /* don't bother with them */ |
121 | 114 | ||
122 | else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { | 115 | else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { |
@@ -216,9 +209,9 @@ static void traverseclosure (GCState *st, Closure *cl) { | |||
216 | markvalue(st, cl->l.p); | 209 | markvalue(st, cl->l.p); |
217 | for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ | 210 | for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ |
218 | UpVal *u = cl->l.upvals[i]; | 211 | UpVal *u = cl->l.upvals[i]; |
219 | if (!u->marked) { | 212 | if (!isblack(valtogco(u))) { |
213 | blacken(valtogco(u)); | ||
220 | markobject(st, &u->value); | 214 | markobject(st, &u->value); |
221 | u->marked = 1; | ||
222 | } | 215 | } |
223 | } | 216 | } |
224 | } | 217 | } |
@@ -300,7 +293,7 @@ static int iscleared (const TObject *o, int iskey) { | |||
300 | stringmark(tsvalue(o)); /* strings are `values', so are never weak */ | 293 | stringmark(tsvalue(o)); /* strings are `values', so are never weak */ |
301 | return 0; | 294 | return 0; |
302 | } | 295 | } |
303 | return !ismarked(gcvalue(o)) || | 296 | return !isblack(gcvalue(o)) || |
304 | (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); | 297 | (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); |
305 | } | 298 | } |
306 | 299 | ||
@@ -319,8 +312,9 @@ static void cleartable (GCObject *l) { | |||
319 | while (l) { | 312 | while (l) { |
320 | Table *h = gcotoh(l); | 313 | Table *h = gcotoh(l); |
321 | int i = h->sizearray; | 314 | int i = h->sizearray; |
322 | lua_assert(h->marked & (KEYWEAK | VALUEWEAK)); | 315 | lua_assert(testbit(h->marked, VALUEWEAKBIT) || |
323 | if (h->marked & VALUEWEAK) { | 316 | testbit(h->marked, KEYWEAKBIT)); |
317 | if (testbit(h->marked, VALUEWEAKBIT)) { | ||
324 | while (i--) { | 318 | while (i--) { |
325 | TObject *o = &h->array[i]; | 319 | TObject *o = &h->array[i]; |
326 | if (iscleared(o, 0)) /* value was collected? */ | 320 | if (iscleared(o, 0)) /* value was collected? */ |
@@ -363,12 +357,12 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
363 | } | 357 | } |
364 | 358 | ||
365 | 359 | ||
366 | static int sweeplist (lua_State *L, GCObject **p, int limit) { | 360 | static int sweeplist (lua_State *L, GCObject **p, int mask) { |
367 | GCObject *curr; | 361 | GCObject *curr; |
368 | int count = 0; /* number of collected items */ | 362 | int count = 0; /* number of collected items */ |
369 | while ((curr = *p) != NULL) { | 363 | while ((curr = *p) != NULL) { |
370 | if (curr->gch.marked > limit) { | 364 | if (curr->gch.marked & mask) { |
371 | unmark(curr); | 365 | unblack(curr); |
372 | p = &curr->gch.next; | 366 | p = &curr->gch.next; |
373 | } | 367 | } |
374 | else { | 368 | else { |
@@ -381,10 +375,10 @@ static int sweeplist (lua_State *L, GCObject **p, int limit) { | |||
381 | } | 375 | } |
382 | 376 | ||
383 | 377 | ||
384 | static void sweepstrings (lua_State *L, int all) { | 378 | static void sweepstrings (lua_State *L, int mask) { |
385 | int i; | 379 | int i; |
386 | for (i=0; i<G(L)->strt.size; i++) { /* for each list */ | 380 | for (i=0; i<G(L)->strt.size; i++) { /* for each list */ |
387 | G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], all); | 381 | G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], mask); |
388 | } | 382 | } |
389 | } | 383 | } |
390 | 384 | ||
@@ -426,7 +420,7 @@ void luaC_callGCTM (lua_State *L) { | |||
426 | udata->uv.next = G(L)->rootudata; /* return it to `root' list */ | 420 | udata->uv.next = G(L)->rootudata; /* return it to `root' list */ |
427 | G(L)->rootudata = o; | 421 | G(L)->rootudata = o; |
428 | setuvalue(L->top - 1, udata); /* keep a reference to it */ | 422 | setuvalue(L->top - 1, udata); /* keep a reference to it */ |
429 | unmark(o); | 423 | unblack(o); |
430 | do1gcTM(L, udata); | 424 | do1gcTM(L, udata); |
431 | } | 425 | } |
432 | L->top--; | 426 | L->top--; |
@@ -435,10 +429,10 @@ void luaC_callGCTM (lua_State *L) { | |||
435 | 429 | ||
436 | 430 | ||
437 | void luaC_sweep (lua_State *L, int all) { | 431 | void luaC_sweep (lua_State *L, int all) { |
438 | if (all) all = 256; /* larger than any mark */ | 432 | int mask = (all) ? 0 : (bitmask(BLACKBIT) | bitmask(FIXEDBIT)); |
439 | sweeplist(L, &G(L)->rootudata, all); | 433 | sweeplist(L, &G(L)->rootudata, mask); |
440 | sweepstrings(L, all); | 434 | sweepstrings(L, mask); |
441 | sweeplist(L, &G(L)->rootgc, all); | 435 | sweeplist(L, &G(L)->rootgc, mask); |
442 | } | 436 | } |
443 | 437 | ||
444 | 438 | ||