diff options
-rw-r--r-- | lfunc.c | 4 | ||||
-rw-r--r-- | lgc.c | 70 | ||||
-rw-r--r-- | lgc.h | 31 | ||||
-rw-r--r-- | lstring.c | 4 | ||||
-rw-r--r-- | lstring.h | 6 |
5 files changed, 69 insertions, 46 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 1.68 2003/10/02 19:21:09 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 1.69 2003/10/20 17:42:41 roberto Exp roberto $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -64,7 +64,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
64 | } | 64 | } |
65 | v = luaM_new(L, UpVal); /* not found: create a new one */ | 65 | v = luaM_new(L, UpVal); /* not found: create a new one */ |
66 | v->tt = LUA_TUPVAL; | 66 | v->tt = LUA_TUPVAL; |
67 | v->marked = 1; /* open upvalues should not be collected */ | 67 | v->marked = bitmask(BLACKBIT); /* open upvalues should not be collected */ |
68 | v->v = level; /* current value lives in the stack */ | 68 | v->v = level; /* current value lives in the stack */ |
69 | v->next = *pp; /* chain it in the proper position */ | 69 | v->next = *pp; /* chain it in the proper position */ |
70 | *pp = valtogco(v); | 70 | *pp = valtogco(v); |
@@ -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 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 1.20 2003/07/16 20:49:02 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 1.21 2003/07/29 19:25:37 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 | */ |
@@ -11,6 +11,35 @@ | |||
11 | #include "lobject.h" | 11 | #include "lobject.h" |
12 | 12 | ||
13 | 13 | ||
14 | /* | ||
15 | * ** some userful bit tricks | ||
16 | * */ | ||
17 | #define bitmask(b) (1<<(b)) | ||
18 | #define setbit(x,b) ((x) |= bitmask(b)) | ||
19 | #define resetbit(x,b) ((x) &= cast(lu_byte, ~bitmask(b))) | ||
20 | #define testbit(x,b) ((x) & bitmask(b)) | ||
21 | |||
22 | |||
23 | |||
24 | /* | ||
25 | ** Layout for bit use in `marked' field: | ||
26 | ** bit 0 - object is white (not used yet) | ||
27 | ** bit 1 - object is black | ||
28 | ** bit 2 - For userdata: is finalized; | ||
29 | for tables: has weak keys | ||
30 | ** bit 3 - for tables: has weak values | ||
31 | ** bit 4 - for strings: is fixed (should not be collected) | ||
32 | */ | ||
33 | |||
34 | #define WHITEBIT 0 | ||
35 | #define BLACKBIT 1 | ||
36 | #define FINALIZEDBIT 2 | ||
37 | #define KEYWEAKBIT 2 | ||
38 | #define VALUEWEAKBIT 3 | ||
39 | #define FIXEDBIT 4 | ||
40 | |||
41 | |||
42 | |||
14 | #define luaC_checkGC(L) { if (G(L)->nblocks >= G(L)->GCthreshold) \ | 43 | #define luaC_checkGC(L) { if (G(L)->nblocks >= G(L)->GCthreshold) \ |
15 | luaC_collectgarbage(L); } | 44 | luaC_collectgarbage(L); } |
16 | 45 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 1.78 2002/12/04 17:38:31 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 1.79 2003/04/28 19:26:16 roberto Exp roberto $ |
3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -91,7 +91,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | |||
91 | Udata *luaS_newudata (lua_State *L, size_t s) { | 91 | Udata *luaS_newudata (lua_State *L, size_t s) { |
92 | Udata *u; | 92 | Udata *u; |
93 | u = cast(Udata *, luaM_malloc(L, sizeudata(s))); | 93 | u = cast(Udata *, luaM_malloc(L, sizeudata(s))); |
94 | u->uv.marked = (1<<1); /* is not finalized */ | 94 | u->uv.marked = 0; /* is not finalized */ |
95 | u->uv.tt = LUA_TUSERDATA; | 95 | u->uv.tt = LUA_TUSERDATA; |
96 | u->uv.len = s; | 96 | u->uv.len = s; |
97 | u->uv.metatable = hvalue(defaultmeta(L)); | 97 | u->uv.metatable = hvalue(defaultmeta(L)); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.h,v 1.36 2002/04/30 13:01:48 roberto Exp roberto $ | 2 | ** $Id: lstring.h,v 1.37 2002/08/16 14:45:55 roberto Exp roberto $ |
3 | ** String table (keep all strings handled by Lua) | 3 | ** String table (keep all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -8,11 +8,11 @@ | |||
8 | #define lstring_h | 8 | #define lstring_h |
9 | 9 | ||
10 | 10 | ||
11 | #include "lgc.h" | ||
11 | #include "lobject.h" | 12 | #include "lobject.h" |
12 | #include "lstate.h" | 13 | #include "lstate.h" |
13 | 14 | ||
14 | 15 | ||
15 | |||
16 | #define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \ | 16 | #define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \ |
17 | (cast(lu_mem, l)+1)*sizeof(char)) | 17 | (cast(lu_mem, l)+1)*sizeof(char)) |
18 | 18 | ||
@@ -22,7 +22,7 @@ | |||
22 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ | 22 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ |
23 | (sizeof(s)/sizeof(char))-1)) | 23 | (sizeof(s)/sizeof(char))-1)) |
24 | 24 | ||
25 | #define luaS_fix(s) ((s)->tsv.marked |= (1<<4)) | 25 | #define luaS_fix(s) setbit((s)->tsv.marked, FIXEDBIT) |
26 | 26 | ||
27 | void luaS_resize (lua_State *L, int newsize); | 27 | void luaS_resize (lua_State *L, int newsize); |
28 | Udata *luaS_newudata (lua_State *L, size_t s); | 28 | Udata *luaS_newudata (lua_State *L, size_t s); |