diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-10-02 11:47:43 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-10-02 11:47:43 -0300 |
commit | 78bc8e553d4190fc3b90be5b621fc0f3507586ef (patch) | |
tree | 9bd9317e1a56960b944549d44a20b91024574c19 /lgc.c | |
parent | dad808a73a98a23729614b8814728d76b4e5d577 (diff) | |
download | lua-78bc8e553d4190fc3b90be5b621fc0f3507586ef.tar.gz lua-78bc8e553d4190fc3b90be5b621fc0f3507586ef.tar.bz2 lua-78bc8e553d4190fc3b90be5b621fc0f3507586ef.zip |
new API for garbage collector
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 68 |
1 files changed, 31 insertions, 37 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.67 2000/09/25 14:52:10 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.68 2000/09/29 12:42:13 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 | */ |
@@ -235,18 +235,13 @@ static void checktab (lua_State *L, stringtable *tb) { | |||
235 | } | 235 | } |
236 | 236 | ||
237 | 237 | ||
238 | /* | 238 | static void collectstrings (lua_State *L, int all) { |
239 | ** collect all elements with `marked' <= `limit'. | ||
240 | ** with limit=0, that means all unmarked elements; | ||
241 | ** with limit=MAX_INT, that means all elements. | ||
242 | */ | ||
243 | static void collectstringtab (lua_State *L, int limit) { | ||
244 | int i; | 239 | int i; |
245 | for (i=0; i<L->strt.size; i++) { /* for each list */ | 240 | for (i=0; i<L->strt.size; i++) { /* for each list */ |
246 | TString **p = &L->strt.hash[i]; | 241 | TString **p = &L->strt.hash[i]; |
247 | TString *next; | 242 | TString *next; |
248 | while ((next = *p) != NULL) { | 243 | while ((next = *p) != NULL) { |
249 | if ((int)next->marked > limit) { /* preserve? */ | 244 | if (next->marked && !all) { /* preserve? */ |
250 | if (next->marked < FIXMARK) /* does not change FIXMARKs */ | 245 | if (next->marked < FIXMARK) /* does not change FIXMARKs */ |
251 | next->marked = 0; | 246 | next->marked = 0; |
252 | p = &next->nexthash; | 247 | p = &next->nexthash; |
@@ -263,14 +258,14 @@ static void collectstringtab (lua_State *L, int limit) { | |||
263 | } | 258 | } |
264 | 259 | ||
265 | 260 | ||
266 | static void collectudatatab (lua_State *L, int all) { | 261 | static void collectudata (lua_State *L, int all) { |
267 | int i; | 262 | int i; |
268 | for (i=0; i<L->udt.size; i++) { /* for each list */ | 263 | for (i=0; i<L->udt.size; i++) { /* for each list */ |
269 | TString **p = &L->udt.hash[i]; | 264 | TString **p = &L->udt.hash[i]; |
270 | TString *next; | 265 | TString *next; |
271 | while ((next = *p) != NULL) { | 266 | while ((next = *p) != NULL) { |
272 | LUA_ASSERT(next->marked <= 1, "udata cannot be fixed"); | 267 | LUA_ASSERT(next->marked <= 1, "udata cannot be fixed"); |
273 | if ((int)next->marked > all) { /* preserve? */ | 268 | if (next->marked && !all) { /* preserve? */ |
274 | next->marked = 0; | 269 | next->marked = 0; |
275 | p = &next->nexthash; | 270 | p = &next->nexthash; |
276 | } | 271 | } |
@@ -289,14 +284,28 @@ static void collectudatatab (lua_State *L, int all) { | |||
289 | } | 284 | } |
290 | 285 | ||
291 | 286 | ||
287 | #define MINBUFFER 256 | ||
288 | static void checkMbuffer (lua_State *L) { | ||
289 | if (L->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */ | ||
290 | size_t newsize = L->Mbuffsize/2; /* still larger than MINBUFFER */ | ||
291 | L->nblocks += (newsize - L->Mbuffsize)*sizeof(char); | ||
292 | L->Mbuffsize = newsize; | ||
293 | luaM_reallocvector(L, L->Mbuffer, newsize, char); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | |||
292 | static void callgcTM (lua_State *L, const TObject *o) { | 298 | static void callgcTM (lua_State *L, const TObject *o) { |
293 | const TObject *im = luaT_getimbyObj(L, o, IM_GC); | 299 | const TObject *im = luaT_getimbyObj(L, o, IM_GC); |
294 | if (ttype(im) != TAG_NIL) { | 300 | if (ttype(im) != TAG_NIL) { |
301 | int oldah = L->allowhooks; | ||
302 | L->allowhooks = 0; /* stop debug hooks during GC tag methods */ | ||
295 | luaD_checkstack(L, 2); | 303 | luaD_checkstack(L, 2); |
296 | *(L->top) = *im; | 304 | *(L->top) = *im; |
297 | *(L->top+1) = *o; | 305 | *(L->top+1) = *o; |
298 | L->top += 2; | 306 | L->top += 2; |
299 | luaD_call(L, L->top-2, 0); | 307 | luaD_call(L, L->top-2, 0); |
308 | L->allowhooks = oldah; /* restore hooks */ | ||
300 | } | 309 | } |
301 | } | 310 | } |
302 | 311 | ||
@@ -305,56 +314,41 @@ static void callgcTMudata (lua_State *L) { | |||
305 | int tag; | 314 | int tag; |
306 | TObject o; | 315 | TObject o; |
307 | ttype(&o) = TAG_USERDATA; | 316 | ttype(&o) = TAG_USERDATA; |
308 | for (tag=L->last_tag; tag>=0; tag--) { | 317 | L->GCthreshold = 2*L->nblocks; /* avoid GC during tag methods */ |
309 | TString *udata = L->IMtable[tag].collected; | 318 | for (tag=L->last_tag; tag>=0; tag--) { /* for each tag (in reverse order) */ |
310 | L->IMtable[tag].collected = NULL; | 319 | TString *udata; |
311 | while (udata) { | 320 | while ((udata = L->IMtable[tag].collected) != NULL) { |
312 | TString *next = udata->nexthash; | 321 | L->IMtable[tag].collected = udata->nexthash; /* remove it from list */ |
313 | tsvalue(&o) = udata; | 322 | tsvalue(&o) = udata; |
314 | callgcTM(L, &o); | 323 | callgcTM(L, &o); |
315 | luaM_free(L, udata); | 324 | luaM_free(L, udata); |
316 | udata = next; | ||
317 | } | 325 | } |
318 | } | 326 | } |
319 | } | 327 | } |
320 | 328 | ||
321 | 329 | ||
322 | void luaC_collect (lua_State *L, int all) { | 330 | void luaC_collect (lua_State *L, int all) { |
323 | int oldah = L->allowhooks; | 331 | collectudata(L, all); |
324 | L->allowhooks = 0; /* stop debug hooks during GC */ | ||
325 | L->GCthreshold *= 4; /* to avoid GC during GC */ | ||
326 | collectudatatab(L, all); | ||
327 | callgcTMudata(L); | 332 | callgcTMudata(L); |
328 | collectstringtab(L, all?MAX_INT:0); | 333 | collectstrings(L, all); |
329 | collecttable(L); | 334 | collecttable(L); |
330 | collectproto(L); | 335 | collectproto(L); |
331 | collectclosure(L); | 336 | collectclosure(L); |
332 | L->allowhooks = oldah; /* restore hooks */ | ||
333 | } | 337 | } |
334 | 338 | ||
335 | 339 | ||
336 | #define MINBUFFER 256 | 340 | static void luaC_collectgarbage (lua_State *L) { |
337 | |||
338 | long lua_collectgarbage (lua_State *L, long limit) { | ||
339 | unsigned long recovered = L->nblocks; /* to subtract `nblocks' after gc */ | ||
340 | markall(L); | 341 | markall(L); |
341 | invalidaterefs(L); | 342 | invalidaterefs(L); /* check unlocked references */ |
342 | luaC_collect(L, 0); | 343 | luaC_collect(L, 0); |
343 | recovered = recovered - L->nblocks; | 344 | checkMbuffer(L); |
344 | L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit; | 345 | L->GCthreshold = 2*L->nblocks; /* set new threshold */ |
345 | if (L->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */ | ||
346 | size_t diff = L->Mbuffsize/2; | ||
347 | L->Mbuffsize -= diff; /* still larger than MINBUFFER */ | ||
348 | L->nblocks -= diff*sizeof(char); | ||
349 | luaM_reallocvector(L, L->Mbuffer, L->Mbuffsize, char); | ||
350 | } | ||
351 | callgcTM(L, &luaO_nilobject); | 346 | callgcTM(L, &luaO_nilobject); |
352 | return recovered; | ||
353 | } | 347 | } |
354 | 348 | ||
355 | 349 | ||
356 | void luaC_checkGC (lua_State *L) { | 350 | void luaC_checkGC (lua_State *L) { |
357 | if (L->nblocks >= L->GCthreshold) | 351 | if (L->nblocks >= L->GCthreshold) |
358 | lua_collectgarbage(L, 0); | 352 | luaC_collectgarbage(L); |
359 | } | 353 | } |
360 | 354 | ||