diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-11-06 19:41:53 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-11-06 19:41:53 -0200 |
commit | 26bf2adaceb18877d836174226d2bfdc3f1fc512 (patch) | |
tree | b23ccd2e297e7c5e732ce65e88f35145271f7faa /lgc.c | |
parent | fd48dcc7c8734091181d8d0e54b0ba3d1770f4c3 (diff) | |
download | lua-26bf2adaceb18877d836174226d2bfdc3f1fc512.tar.gz lua-26bf2adaceb18877d836174226d2bfdc3f1fc512.tar.bz2 lua-26bf2adaceb18877d836174226d2bfdc3f1fc512.zip |
optimizations for space in LClosures and time cleanning weak tables
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 100 |
1 files changed, 52 insertions, 48 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.114 2001/10/25 19:14:14 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.115 2001/10/31 19:58:11 roberto Exp $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | typedef struct GCState { | 23 | typedef struct GCState { |
24 | Table *tmark; /* list of marked tables to be visited */ | 24 | Table *tmark; /* list of marked tables to be visited */ |
25 | Table *toclear; /* list of visited weak tables (to be cleared after GC) */ | ||
25 | } GCState; | 26 | } GCState; |
26 | 27 | ||
27 | 28 | ||
@@ -65,10 +66,10 @@ static void markclosure (GCState *st, Closure *cl) { | |||
65 | lua_assert(cl->l.nupvalues == cl->l.p->nupvalues); | 66 | lua_assert(cl->l.nupvalues == cl->l.p->nupvalues); |
66 | protomark(cl->l.p); | 67 | protomark(cl->l.p); |
67 | for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ | 68 | for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ |
68 | UpVal *u = cl->l.upvals[i].heap; | 69 | TObject *u = cl->l.upvals[i]; |
69 | if (u && !u->marked) { | 70 | if (isclosed(u)) { |
70 | u->marked = 1; | 71 | ttype(u-1) = LUA_TNIL; /* temporary value (to mark as visited) */ |
71 | markobject(st, &u->val); | 72 | markobject(st, u); |
72 | } | 73 | } |
73 | } | 74 | } |
74 | } | 75 | } |
@@ -148,6 +149,10 @@ static void removekey (Node *n) { | |||
148 | static void traversetable (GCState *st, Table *h) { | 149 | static void traversetable (GCState *st, Table *h) { |
149 | int i; | 150 | int i; |
150 | int mode = h->weakmode; | 151 | int mode = h->weakmode; |
152 | if (mode) { /* weak table? must be cleared after GC... */ | ||
153 | h->mark = st->toclear; /* put in the appropriate list */ | ||
154 | st->toclear = h; | ||
155 | } | ||
151 | if (!(mode & LUA_WEAK_VALUE)) { | 156 | if (!(mode & LUA_WEAK_VALUE)) { |
152 | i = sizearray(h); | 157 | i = sizearray(h); |
153 | while (i--) | 158 | while (i--) |
@@ -167,17 +172,15 @@ static void traversetable (GCState *st, Table *h) { | |||
167 | } | 172 | } |
168 | 173 | ||
169 | 174 | ||
170 | static void markall (lua_State *L) { | 175 | static void markall (lua_State *L, GCState *st) { |
171 | GCState st; | 176 | marktagmethods(G(L), st); /* mark tag methods */ |
172 | st.tmark = NULL; | 177 | markstacks(L, st); /* mark all stacks */ |
173 | marktagmethods(G(L), &st); /* mark tag methods */ | 178 | marktable(st, G(L)->type2tag); |
174 | markstacks(L, &st); /* mark all stacks */ | 179 | markobject(st, &G(L)->registry); |
175 | marktable(&st, G(L)->type2tag); | 180 | while (st->tmark) { /* mark tables */ |
176 | markobject(&st, &G(L)->registry); | 181 | Table *h = st->tmark; /* get first table from list */ |
177 | while (st.tmark) { /* mark tables */ | 182 | st->tmark = h->mark; /* remove it from list */ |
178 | Table *h = st.tmark; /* get first table from list */ | 183 | traversetable(st, h); |
179 | st.tmark = h->mark; /* remove it from list */ | ||
180 | traversetable(&st, h); | ||
181 | } | 184 | } |
182 | } | 185 | } |
183 | 186 | ||
@@ -198,30 +201,27 @@ static int hasmark (const TObject *o) { | |||
198 | } | 201 | } |
199 | 202 | ||
200 | 203 | ||
201 | static void cleardeadnodes (Table *h) { | 204 | /* |
202 | int i; | 205 | ** clear (set to nil) keys and values from weaktables that were collected |
203 | i = sizearray(h); | 206 | */ |
204 | while (i--) { | 207 | static void cleartables (Table *h) { |
205 | TObject *o = &h->array[i]; | 208 | for (; h; h = h->mark) { |
206 | if (!hasmark(o)) | 209 | int i; |
207 | setnilvalue(o); /* remove value */ | 210 | lua_assert(h->weakmode); |
208 | } | 211 | i = sizearray(h); |
209 | i = sizenode(h); | 212 | while (i--) { |
210 | while (i--) { | 213 | TObject *o = &h->array[i]; |
211 | Node *n = node(h, i); | 214 | if (!hasmark(o)) |
212 | if (!hasmark(val(n)) || !hasmark(key(n))) { | 215 | setnilvalue(o); /* remove value */ |
213 | setnilvalue(val(n)); /* remove value ... */ | 216 | } |
214 | removekey(n); /* ... and key */ | 217 | i = sizenode(h); |
218 | while (i--) { | ||
219 | Node *n = node(h, i); | ||
220 | if (!hasmark(val(n)) || !hasmark(key(n))) { | ||
221 | setnilvalue(val(n)); /* remove value ... */ | ||
222 | removekey(n); /* ... and key */ | ||
223 | } | ||
215 | } | 224 | } |
216 | } | ||
217 | } | ||
218 | |||
219 | |||
220 | static void cleartables (global_State *G) { | ||
221 | Table *h; | ||
222 | for (h = G->roottable; h; h = h->next) { | ||
223 | if (h->weakmode && ismarked(h)) | ||
224 | cleardeadnodes(h); | ||
225 | } | 225 | } |
226 | } | 226 | } |
227 | 227 | ||
@@ -284,16 +284,17 @@ static void collecttable (lua_State *L) { | |||
284 | 284 | ||
285 | 285 | ||
286 | static void collectupval (lua_State *L) { | 286 | static void collectupval (lua_State *L) { |
287 | UpVal **v = &G(L)->rootupval; | 287 | TObject **v = &G(L)->rootupval; |
288 | UpVal *curr; | 288 | TObject *curr; |
289 | while ((curr = *v) != NULL) { | 289 | while ((curr = *v) != NULL) { |
290 | if (curr->marked) { | 290 | if (ttype(curr) == LUA_TNIL) { /* was marked? */ |
291 | curr->marked = 0; | 291 | ttype(curr) = LUA_HEAPUPVAL; /* unmark */ |
292 | v = &curr->next; | 292 | v = &vvalue(curr); /* next */ |
293 | } | 293 | } |
294 | else { | 294 | else { |
295 | *v = curr->next; | 295 | lua_assert(ttype(curr) == LUA_HEAPUPVAL); |
296 | luaM_freelem(L, curr); | 296 | *v = vvalue(curr); /* next */ |
297 | luaM_freearray(L, curr, 2, TObject); | ||
297 | } | 298 | } |
298 | } | 299 | } |
299 | } | 300 | } |
@@ -411,8 +412,11 @@ void luaC_collect (lua_State *L, int all) { | |||
411 | 412 | ||
412 | 413 | ||
413 | void luaC_collectgarbage (lua_State *L) { | 414 | void luaC_collectgarbage (lua_State *L) { |
414 | markall(L); | 415 | GCState st; |
415 | cleartables(G(L)); | 416 | st.tmark = NULL; |
417 | st.toclear = NULL; | ||
418 | markall(L, &st); | ||
419 | cleartables(st.toclear); | ||
416 | luaC_collect(L, 0); | 420 | luaC_collect(L, 0); |
417 | checkMbuffer(L); | 421 | checkMbuffer(L); |
418 | G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ | 422 | G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ |