diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-12-11 14:52:57 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-12-11 14:52:57 -0200 |
| commit | ed9be5e1f0d4b68aa848f85744ad959d7a57c9f4 (patch) | |
| tree | 595b3182d3974a1b5d72821e52c69d97e6ad5f7f | |
| parent | 9d801f43d47967a533b399352fab63c4a62ffae7 (diff) | |
| download | lua-ed9be5e1f0d4b68aa848f85744ad959d7a57c9f4.tar.gz lua-ed9be5e1f0d4b68aa848f85744ad959d7a57c9f4.tar.bz2 lua-ed9be5e1f0d4b68aa848f85744ad959d7a57c9f4.zip | |
reentrant implementation of garbage collection
| -rw-r--r-- | lgc.c | 49 | ||||
| -rw-r--r-- | lstate.c | 4 | ||||
| -rw-r--r-- | lstate.h | 3 |
3 files changed, 31 insertions, 25 deletions
| @@ -136,6 +136,8 @@ static void markudet (lua_State *L, GCState *st) { | |||
| 136 | Udata *u; | 136 | Udata *u; |
| 137 | for (u = G(L)->rootudata; u; u = u->uv.next) | 137 | for (u = G(L)->rootudata; u; u = u->uv.next) |
| 138 | marktable(st, u->uv.eventtable); | 138 | marktable(st, u->uv.eventtable); |
| 139 | for (u = G(L)->tmudata; u; u = u->uv.next) | ||
| 140 | marktable(st, u->uv.eventtable); | ||
| 139 | } | 141 | } |
| 140 | 142 | ||
| 141 | 143 | ||
| @@ -290,27 +292,30 @@ static void collecttable (lua_State *L) { | |||
| 290 | } | 292 | } |
| 291 | 293 | ||
| 292 | 294 | ||
| 293 | static Udata *collectudata (lua_State *L, int keep) { | 295 | static void collectudata (lua_State *L) { |
| 294 | Udata **p = &G(L)->rootudata; | 296 | Udata **p = &G(L)->rootudata; |
| 295 | Udata *curr; | 297 | Udata *curr; |
| 296 | Udata *collected = NULL; | 298 | Udata *collected = NULL; /* to collect udata with gc event */ |
| 299 | Udata **lastcollected = &collected; | ||
| 297 | while ((curr = *p) != NULL) { | 300 | while ((curr = *p) != NULL) { |
| 298 | if (isudmarked(curr)) { | 301 | if (isudmarked(curr)) { |
| 299 | unmarkud(curr); | 302 | unmarkud(curr); |
| 300 | p = &curr->uv.next; | 303 | p = &curr->uv.next; |
| 301 | } | 304 | } |
| 302 | else { /* collect */ | 305 | else { |
| 303 | const TObject *tm = fasttm(L, curr->uv.eventtable, TM_GC); | ||
| 304 | *p = curr->uv.next; | 306 | *p = curr->uv.next; |
| 305 | if (keep || tm != NULL) { | 307 | if (fasttm(L, curr->uv.eventtable, TM_GC) != NULL) { /* gc event? */ |
| 306 | curr->uv.next = collected; | 308 | curr->uv.next = NULL; /* link `curr' at the end of `collected' list */ |
| 307 | collected = curr; | 309 | *lastcollected = curr; |
| 310 | lastcollected = &curr->uv.next; | ||
| 308 | } | 311 | } |
| 309 | else /* no gc action; delete udata */ | 312 | else /* no gc event; delete udata */ |
| 310 | luaM_free(L, curr, sizeudata(curr->uv.len)); | 313 | luaM_free(L, curr, sizeudata(curr->uv.len)); |
| 311 | } | 314 | } |
| 312 | } | 315 | } |
| 313 | return collected; | 316 | /* insert collected udata with gc event into `tmudata' list */ |
| 317 | *lastcollected = G(L)->tmudata; | ||
| 318 | G(L)->tmudata = collected; | ||
| 314 | } | 319 | } |
| 315 | 320 | ||
| 316 | 321 | ||
| @@ -365,12 +370,12 @@ static void callgcTM (lua_State *L, Udata *udata) { | |||
| 365 | } | 370 | } |
| 366 | 371 | ||
| 367 | 372 | ||
| 368 | static void callgcTMudata (lua_State *L, Udata *c) { | 373 | static void callgcTMudata (lua_State *L) { |
| 369 | luaD_checkstack(L, 3); | 374 | luaD_checkstack(L, 3); |
| 370 | L->top++; /* reserve space to keep udata while runs its gc method */ | 375 | L->top++; /* reserve space to keep udata while runs its gc method */ |
| 371 | while (c != NULL) { | 376 | while (G(L)->tmudata != NULL) { |
| 372 | Udata *udata = c; | 377 | Udata *udata = G(L)->tmudata; |
| 373 | c = udata->uv.next; /* remove udata from list */ | 378 | G(L)->tmudata = udata->uv.next; /* remove udata from list */ |
| 374 | udata->uv.next = G(L)->rootudata; /* resurect it */ | 379 | udata->uv.next = G(L)->rootudata; /* resurect it */ |
| 375 | G(L)->rootudata = udata; | 380 | G(L)->rootudata = udata; |
| 376 | setuvalue(L->top - 1, udata); | 381 | setuvalue(L->top - 1, udata); |
| @@ -383,34 +388,32 @@ static void callgcTMudata (lua_State *L, Udata *c) { | |||
| 383 | 388 | ||
| 384 | 389 | ||
| 385 | void luaC_callallgcTM (lua_State *L) { | 390 | void luaC_callallgcTM (lua_State *L) { |
| 386 | if (G(L)->rootudata) { /* avoid problems with incomplete states */ | 391 | lua_assert(G(L)->tmudata == NULL); |
| 387 | Udata *c = collectudata(L, 1); /* collect all udata */ | 392 | G(L)->tmudata = G(L)->rootudata; /* all udata must be collected */ |
| 388 | callgcTMudata(L, c); /* call their GC tag methods */ | 393 | G(L)->rootudata = NULL; |
| 389 | } | 394 | callgcTMudata(L); /* call their GC tag methods */ |
| 390 | } | 395 | } |
| 391 | 396 | ||
| 392 | 397 | ||
| 393 | Udata *luaC_collect (lua_State *L, int all) { | 398 | void luaC_collect (lua_State *L, int all) { |
| 394 | Udata *c = collectudata(L, 0); | 399 | collectudata(L); |
| 395 | collectstrings(L, all); | 400 | collectstrings(L, all); |
| 396 | collecttable(L); | 401 | collecttable(L); |
| 397 | collectproto(L); | 402 | collectproto(L); |
| 398 | collectupval(L); | 403 | collectupval(L); |
| 399 | collectclosures(L); | 404 | collectclosures(L); |
| 400 | return c; | ||
| 401 | } | 405 | } |
| 402 | 406 | ||
| 403 | 407 | ||
| 404 | void luaC_collectgarbage (lua_State *L) { | 408 | void luaC_collectgarbage (lua_State *L) { |
| 405 | Udata *c; | ||
| 406 | GCState st; | 409 | GCState st; |
| 407 | st.tmark = NULL; | 410 | st.tmark = NULL; |
| 408 | st.toclear = NULL; | 411 | st.toclear = NULL; |
| 409 | markall(L, &st); | 412 | markall(L, &st); |
| 410 | cleartables(st.toclear); | 413 | cleartables(st.toclear); |
| 411 | c = luaC_collect(L, 0); | 414 | luaC_collect(L, 0); |
| 412 | checkMbuffer(L); | 415 | checkMbuffer(L); |
| 413 | G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ | 416 | G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ |
| 414 | callgcTMudata(L, c); | 417 | callgcTMudata(L); |
| 415 | } | 418 | } |
| 416 | 419 | ||
| @@ -59,8 +59,9 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
| 59 | G(L)->rootproto = NULL; | 59 | G(L)->rootproto = NULL; |
| 60 | G(L)->rootcl = NULL; | 60 | G(L)->rootcl = NULL; |
| 61 | G(L)->roottable = NULL; | 61 | G(L)->roottable = NULL; |
| 62 | G(L)->rootudata = NULL; | ||
| 63 | G(L)->rootupval = NULL; | 62 | G(L)->rootupval = NULL; |
| 63 | G(L)->rootudata = NULL; | ||
| 64 | G(L)->tmudata = NULL; | ||
| 64 | G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); | 65 | G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); |
| 65 | luaD_init(L, so->stacksize); /* init stack */ | 66 | luaD_init(L, so->stacksize); /* init stack */ |
| 66 | /* create default event table with a dummy table, and then close the loop */ | 67 | /* create default event table with a dummy table, and then close the loop */ |
| @@ -118,6 +119,7 @@ static void close_state (lua_State *L, lua_State *OL) { | |||
| 118 | else if (G(L)) { /* last thread; close global state */ | 119 | else if (G(L)) { /* last thread; close global state */ |
| 119 | if (G(L)->rootudata) /* (avoid problems with incomplete states) */ | 120 | if (G(L)->rootudata) /* (avoid problems with incomplete states) */ |
| 120 | luaC_callallgcTM(L); /* call GC tag methods for all udata */ | 121 | luaC_callallgcTM(L); /* call GC tag methods for all udata */ |
| 122 | lua_assert(G(L)->tmudata == NULL); | ||
| 121 | luaC_collect(L, 1); /* collect all elements */ | 123 | luaC_collect(L, 1); /* collect all elements */ |
| 122 | lua_assert(G(L)->rootproto == NULL); | 124 | lua_assert(G(L)->rootproto == NULL); |
| 123 | lua_assert(G(L)->rootudata == NULL); | 125 | lua_assert(G(L)->rootudata == NULL); |
| @@ -81,8 +81,9 @@ typedef struct global_State { | |||
| 81 | Proto *rootproto; /* list of all prototypes */ | 81 | Proto *rootproto; /* list of all prototypes */ |
| 82 | Closure *rootcl; /* list of all closures */ | 82 | Closure *rootcl; /* list of all closures */ |
| 83 | Table *roottable; /* list of all tables */ | 83 | Table *roottable; /* list of all tables */ |
| 84 | Udata *rootudata; /* list of all userdata */ | ||
| 85 | UpVal *rootupval; /* list of closed up values */ | 84 | UpVal *rootupval; /* list of closed up values */ |
| 85 | Udata *rootudata; /* list of all userdata */ | ||
| 86 | Udata *tmudata; /* list of userdata to be GC */ | ||
| 86 | TString *tmname[TM_N]; /* array with tag-method names */ | 87 | TString *tmname[TM_N]; /* array with tag-method names */ |
| 87 | } global_State; | 88 | } global_State; |
| 88 | 89 | ||
