diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-05-30 15:54:49 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-05-30 15:54:49 -0300 |
| commit | 50a82ec1b9adafa108756077b018925131f131e8 (patch) | |
| tree | 0861e68fabf699e747fb99e635a66e7ff76ca122 | |
| parent | ed1751bc32bd295e27881e9d6f6bb17019d59c3e (diff) | |
| download | lua-50a82ec1b9adafa108756077b018925131f131e8.tar.gz lua-50a82ec1b9adafa108756077b018925131f131e8.tar.bz2 lua-50a82ec1b9adafa108756077b018925131f131e8.zip | |
gc tag methods for udata are called in (reverse) tag order
| -rw-r--r-- | lgc.c | 127 | ||||
| -rw-r--r-- | ltm.c | 3 | ||||
| -rw-r--r-- | ltm.h | 3 |
3 files changed, 87 insertions, 46 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 1.50 2000/05/11 18:57:19 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.51 2000/05/24 13:54:49 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 | */ |
| @@ -20,16 +20,6 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | static void luaD_gcTM (lua_State *L, const TObject *o) { | ||
| 24 | const TObject *im = luaT_getimbyObj(L, o, IM_GC); | ||
| 25 | if (ttype(im) != TAG_NIL) { | ||
| 26 | luaD_checkstack(L, 2); | ||
| 27 | *(L->top++) = *im; | ||
| 28 | *(L->top++) = *o; | ||
| 29 | luaD_call(L, L->top-2, 0); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | 23 | ||
| 34 | static int markobject (lua_State *L, TObject *o); | 24 | static int markobject (lua_State *L, TObject *o); |
| 35 | 25 | ||
| @@ -78,9 +68,9 @@ static void tablemark (lua_State *L, Hash *h) { | |||
| 78 | 68 | ||
| 79 | 69 | ||
| 80 | static void travstack (lua_State *L) { | 70 | static void travstack (lua_State *L) { |
| 81 | int i; | 71 | StkId o; |
| 82 | for (i = (L->top-1)-L->stack; i>=0; i--) | 72 | for (o=L->stack; o<L->top; o++) |
| 83 | markobject(L, L->stack+i); | 73 | markobject(L, o); |
| 84 | } | 74 | } |
| 85 | 75 | ||
| 86 | 76 | ||
| @@ -161,54 +151,101 @@ static void collecttable (lua_State *L) { | |||
| 161 | } | 151 | } |
| 162 | 152 | ||
| 163 | 153 | ||
| 154 | static void checktab (lua_State *L, stringtable *tb) { | ||
| 155 | if (tb->nuse < (lint32)(tb->size/4) && tb->size > 10) | ||
| 156 | luaS_resize(L, tb, tb->size/2); /* table is too big */ | ||
| 157 | } | ||
| 158 | |||
| 159 | |||
| 164 | /* | 160 | /* |
| 165 | ** collect all elements with `marked' < `limit'. | 161 | ** collect all elements with `marked' <= `limit'. |
| 166 | ** with limit=1, that means all unmarked elements; | 162 | ** with limit=0, that means all unmarked elements; |
| 167 | ** with limit=MAX_INT, that means all elements. | 163 | ** with limit=MAX_INT, that means all elements. |
| 168 | */ | 164 | */ |
| 169 | static void collectstringtab (lua_State *L, int limit, stringtable *tb) { | 165 | static void collectstringtab (lua_State *L, int limit) { |
| 170 | int i; | 166 | int i; |
| 171 | TObject o; /* to call userdata `gc' tag method */ | 167 | for (i=0; i<L->strt.size; i++) { /* for each list */ |
| 172 | ttype(&o) = TAG_USERDATA; | 168 | TString **p = &L->strt.hash[i]; |
| 173 | for (i=0; i<tb->size; i++) { /* for each list */ | ||
| 174 | TString **p = &tb->hash[i]; | ||
| 175 | TString *next; | 169 | TString *next; |
| 176 | while ((next = *p) != NULL) { | 170 | while ((next = *p) != NULL) { |
| 177 | if (next->marked >= limit) { | 171 | if (next->marked > limit) { /* preserve? */ |
| 178 | if (next->marked < FIXMARK) /* does not change FIXMARKs */ | 172 | if (next->marked < FIXMARK) /* does not change FIXMARKs */ |
| 179 | next->marked = 0; | 173 | next->marked = 0; |
| 180 | p = &next->nexthash; | 174 | p = &next->nexthash; |
| 181 | } | 175 | } |
| 182 | else { /* collect */ | 176 | else { /* collect */ |
| 183 | if (tb == &L->strt) /* is string? */ | ||
| 184 | L->nblocks -= gcsizestring(L, next->u.s.len); | ||
| 185 | else { | ||
| 186 | tsvalue(&o) = next; | ||
| 187 | luaD_gcTM(L, &o); | ||
| 188 | L->nblocks -= gcsizeudata; | ||
| 189 | } | ||
| 190 | *p = next->nexthash; | 177 | *p = next->nexthash; |
| 191 | tb->nuse--; | 178 | L->strt.nuse--; |
| 179 | L->nblocks -= gcsizestring(L, next->u.s.len); | ||
| 192 | luaM_free(L, next); | 180 | luaM_free(L, next); |
| 193 | } | 181 | } |
| 194 | } | 182 | } |
| 195 | } | 183 | } |
| 196 | if (tb->nuse < (lint32)(tb->size/4) && tb->size > 10) | 184 | checktab(L, &L->strt); |
| 197 | luaS_resize(L, tb, tb->size/2); /* table is too big */ | ||
| 198 | } | 185 | } |
| 199 | 186 | ||
| 200 | 187 | ||
| 201 | static void collectstring (lua_State *L, int limit) { | 188 | static void collectudatatab (lua_State *L, int all) { |
| 202 | collectstringtab(L, limit, &L->strt); | 189 | int i; |
| 203 | collectstringtab(L, limit, &L->udt); | 190 | for (i=0; i<L->udt.size; i++) { /* for each list */ |
| 191 | TString **p = &L->udt.hash[i]; | ||
| 192 | TString *next; | ||
| 193 | while ((next = *p) != NULL) { | ||
| 194 | LUA_ASSERT(L, next->marked <= 1, "udata cannot be fixed"); | ||
| 195 | if (next->marked > all) { /* preserve? */ | ||
| 196 | next->marked = 0; | ||
| 197 | p = &next->nexthash; | ||
| 198 | } | ||
| 199 | else { /* collect */ | ||
| 200 | int tag = next->u.d.tag; | ||
| 201 | if (tag > L->last_tag) tag = TAG_USERDATA; | ||
| 202 | *p = next->nexthash; | ||
| 203 | next->nexthash = L->IMtable[tag].collected; /* chain udata */ | ||
| 204 | L->IMtable[tag].collected = next; | ||
| 205 | L->nblocks -= gcsizeudata; | ||
| 206 | L->udt.nuse--; | ||
| 207 | } | ||
| 208 | } | ||
| 209 | } | ||
| 210 | checktab(L, &L->udt); | ||
| 211 | } | ||
| 212 | |||
| 213 | |||
| 214 | static void callgcTM (lua_State *L, const TObject *o) { | ||
| 215 | const TObject *im = luaT_getimbyObj(L, o, IM_GC); | ||
| 216 | if (ttype(im) != TAG_NIL) { | ||
| 217 | luaD_checkstack(L, 2); | ||
| 218 | *(L->top) = *im; | ||
| 219 | *(L->top+1) = *o; | ||
| 220 | L->top += 2; | ||
| 221 | luaD_call(L, L->top-2, 0); | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | |||
| 226 | static void callgcTMudata (lua_State *L) { | ||
| 227 | int tag; | ||
| 228 | TObject o; | ||
| 229 | ttype(&o) = TAG_USERDATA; | ||
| 230 | for (tag=L->last_tag; tag>=0; tag--) { | ||
| 231 | TString *udata = L->IMtable[tag].collected; | ||
| 232 | L->IMtable[tag].collected = NULL; | ||
| 233 | while (udata) { | ||
| 234 | TString *next = udata->nexthash; | ||
| 235 | tsvalue(&o) = udata; | ||
| 236 | callgcTM(L, &o); | ||
| 237 | luaM_free(L, udata); | ||
| 238 | udata = next; | ||
| 239 | } | ||
| 240 | } | ||
| 204 | } | 241 | } |
| 205 | 242 | ||
| 206 | 243 | ||
| 207 | static void markall (lua_State *L) { | 244 | static void markall (lua_State *L) { |
| 245 | luaT_travtagmethods(L, markobject); /* mark tag methods */ | ||
| 208 | travstack(L); /* mark stack objects */ | 246 | travstack(L); /* mark stack objects */ |
| 209 | tablemark(L, L->gt); /* mark global variable values and names */ | 247 | tablemark(L, L->gt); /* mark global variables */ |
| 210 | travlock(L); /* mark locked objects */ | 248 | travlock(L); /* mark locked objects */ |
| 211 | luaT_travtagmethods(L, markobject); /* mark tag methods */ | ||
| 212 | } | 249 | } |
| 213 | 250 | ||
| 214 | 251 | ||
| @@ -216,8 +253,10 @@ void luaC_collect (lua_State *L, int all) { | |||
| 216 | int oldah = L->allowhooks; | 253 | int oldah = L->allowhooks; |
| 217 | L->allowhooks = 0; /* stop debug hooks during GC */ | 254 | L->allowhooks = 0; /* stop debug hooks during GC */ |
| 218 | L->GCthreshold *= 4; /* to avoid GC during GC */ | 255 | L->GCthreshold *= 4; /* to avoid GC during GC */ |
| 256 | collectudatatab(L, all); | ||
| 257 | callgcTMudata(L); | ||
| 258 | collectstringtab(L, all?MAX_INT:0); | ||
| 219 | collecttable(L); | 259 | collecttable(L); |
| 220 | collectstring(L, all?MAX_INT:1); | ||
| 221 | collectproto(L); | 260 | collectproto(L); |
| 222 | collectclosure(L); | 261 | collectclosure(L); |
| 223 | L->allowhooks = oldah; /* restore hooks */ | 262 | L->allowhooks = oldah; /* restore hooks */ |
| @@ -235,7 +274,7 @@ long lua_collectgarbage (lua_State *L, long limit) { | |||
| 235 | L->Mbuffsize /= 2; /* still larger than Mbuffnext*2 */ | 274 | L->Mbuffsize /= 2; /* still larger than Mbuffnext*2 */ |
| 236 | luaM_reallocvector(L, L->Mbuffer, L->Mbuffsize, char); | 275 | luaM_reallocvector(L, L->Mbuffer, L->Mbuffsize, char); |
| 237 | } | 276 | } |
| 238 | luaD_gcTM(L, &luaO_nilobject); | 277 | callgcTM(L, &luaO_nilobject); |
| 239 | return recovered; | 278 | return recovered; |
| 240 | } | 279 | } |
| 241 | 280 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltm.c,v 1.39 2000/03/30 16:41:51 roberto Exp roberto $ | 2 | ** $Id: ltm.c,v 1.40 2000/05/24 13:54:49 roberto Exp roberto $ |
| 3 | ** Tag methods | 3 | ** Tag methods |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -61,6 +61,7 @@ static void init_entry (lua_State *L, int tag) { | |||
| 61 | int i; | 61 | int i; |
| 62 | for (i=0; i<IM_N; i++) | 62 | for (i=0; i<IM_N; i++) |
| 63 | ttype(luaT_getim(L, tag, i)) = TAG_NIL; | 63 | ttype(luaT_getim(L, tag, i)) = TAG_NIL; |
| 64 | L->IMtable[tag].collected = NULL; | ||
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | 67 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltm.h,v 1.11 2000/03/20 19:14:54 roberto Exp roberto $ | 2 | ** $Id: ltm.h,v 1.12 2000/03/30 16:41:51 roberto Exp roberto $ |
| 3 | ** Tag methods | 3 | ** Tag methods |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -37,6 +37,7 @@ typedef enum { | |||
| 37 | 37 | ||
| 38 | struct IM { | 38 | struct IM { |
| 39 | TObject int_method[IM_N]; | 39 | TObject int_method[IM_N]; |
| 40 | TString *collected; /* list of G. collected udata with this tag */ | ||
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 42 | 43 | ||
