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 */ |
