diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-02-11 18:03:35 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-02-11 18:03:35 -0200 |
| commit | 678d2fb2ace2dbdf91fdac2752e1f4dfe73651df (patch) | |
| tree | cf4ab13aee46788c66623009932f118c882d501c | |
| parent | af39352632864b1961a554a560bee2c758666b2a (diff) | |
| download | lua-678d2fb2ace2dbdf91fdac2752e1f4dfe73651df.tar.gz lua-678d2fb2ace2dbdf91fdac2752e1f4dfe73651df.tar.bz2 lua-678d2fb2ace2dbdf91fdac2752e1f4dfe73651df.zip | |
all collected userdata must go to the end of the list of finalizers
| -rw-r--r-- | lgc.c | 40 | ||||
| -rw-r--r-- | lstate.h | 4 |
2 files changed, 26 insertions, 18 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.22 2005/01/18 17:18:09 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.23 2005/02/10 13:25:02 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 | */ |
| @@ -114,21 +114,23 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
| 114 | 114 | ||
| 115 | 115 | ||
| 116 | static void marktmu (global_State *g) { | 116 | static void marktmu (global_State *g) { |
| 117 | GCObject *u; | 117 | GCObject *u = g->tmudata; |
| 118 | for (u = g->tmudata; u; u = u->gch.next) { | 118 | if (u) { |
| 119 | makewhite(g, u); /* may be marked, if left from previous GC */ | 119 | do { |
| 120 | reallymarkobject(g, u); | 120 | u = u->gch.next; |
| 121 | makewhite(g, u); /* may be marked, if left from previous GC */ | ||
| 122 | reallymarkobject(g, u); | ||
| 123 | } while (u != g->tmudata); | ||
| 121 | } | 124 | } |
| 122 | } | 125 | } |
| 123 | 126 | ||
| 124 | 127 | ||
| 125 | /* move `dead' udata that need finalization to list `tmudata' */ | 128 | /* move `dead' udata that need finalization to list `tmudata' */ |
| 126 | size_t luaC_separateudata (lua_State *L, int all) { | 129 | size_t luaC_separateudata (lua_State *L, int all) { |
| 130 | global_State *g = G(L); | ||
| 127 | size_t deadmem = 0; | 131 | size_t deadmem = 0; |
| 128 | GCObject **p = &G(L)->mainthread->next; | 132 | GCObject **p = &g->mainthread->next; |
| 129 | GCObject *curr; | 133 | GCObject *curr; |
| 130 | GCObject *collected = NULL; /* to collect udata with gc event */ | ||
| 131 | GCObject **lastcollected = &collected; | ||
| 132 | while ((curr = *p) != NULL) { | 134 | while ((curr = *p) != NULL) { |
| 133 | if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) | 135 | if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) |
| 134 | p = &curr->gch.next; /* don't bother with them */ | 136 | p = &curr->gch.next; /* don't bother with them */ |
| @@ -140,14 +142,16 @@ size_t luaC_separateudata (lua_State *L, int all) { | |||
| 140 | deadmem += sizeudata(gco2u(curr)); | 142 | deadmem += sizeudata(gco2u(curr)); |
| 141 | markfinalized(gco2u(curr)); | 143 | markfinalized(gco2u(curr)); |
| 142 | *p = curr->gch.next; | 144 | *p = curr->gch.next; |
| 143 | curr->gch.next = NULL; /* link `curr' at the end of `collected' list */ | 145 | /* link `curr' at the end of `tmudata' list */ |
| 144 | *lastcollected = curr; | 146 | if (g->tmudata == NULL) /* list is empty? */ |
| 145 | lastcollected = &curr->gch.next; | 147 | g->tmudata = curr->gch.next = curr; /* creates a circular list */ |
| 148 | else { | ||
| 149 | curr->gch.next = g->tmudata->gch.next; | ||
| 150 | g->tmudata->gch.next = curr; | ||
| 151 | g->tmudata = curr; | ||
| 152 | } | ||
| 146 | } | 153 | } |
| 147 | } | 154 | } |
| 148 | /* insert collected udata with gc event into `tmudata' list */ | ||
| 149 | *lastcollected = G(L)->tmudata; | ||
| 150 | G(L)->tmudata = collected; | ||
| 151 | return deadmem; | 155 | return deadmem; |
| 152 | } | 156 | } |
| 153 | 157 | ||
| @@ -443,10 +447,14 @@ static void checkSizes (lua_State *L) { | |||
| 443 | 447 | ||
| 444 | static void GCTM (lua_State *L) { | 448 | static void GCTM (lua_State *L) { |
| 445 | global_State *g = G(L); | 449 | global_State *g = G(L); |
| 446 | GCObject *o = g->tmudata; | 450 | GCObject *o = g->tmudata->gch.next; /* get first element */ |
| 447 | Udata *udata = rawgco2u(o); | 451 | Udata *udata = rawgco2u(o); |
| 448 | const TValue *tm; | 452 | const TValue *tm; |
| 449 | g->tmudata = udata->uv.next; /* remove udata from `tmudata' */ | 453 | /* remove udata from `tmudata' */ |
| 454 | if (o == g->tmudata) /* last element? */ | ||
| 455 | g->tmudata = NULL; | ||
| 456 | else | ||
| 457 | g->tmudata->gch.next = udata->uv.next; | ||
| 450 | udata->uv.next = g->mainthread->next; /* return it to `root' list */ | 458 | udata->uv.next = g->mainthread->next; /* return it to `root' list */ |
| 451 | g->mainthread->next = o; | 459 | g->mainthread->next = o; |
| 452 | makewhite(g, o); | 460 | makewhite(g, o); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 2.12 2005/01/14 14:19:42 roberto Exp $ | 2 | ** $Id: lstate.h,v 2.13 2005/01/18 17:18:09 roberto Exp roberto $ |
| 3 | ** Global State | 3 | ** Global State |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -77,7 +77,7 @@ typedef struct global_State { | |||
| 77 | GCObject *gray; /* list of gray objects */ | 77 | GCObject *gray; /* list of gray objects */ |
| 78 | GCObject *grayagain; /* list of objects to be traversed atomically */ | 78 | GCObject *grayagain; /* list of objects to be traversed atomically */ |
| 79 | GCObject *weak; /* list of weak tables (to be cleared) */ | 79 | GCObject *weak; /* list of weak tables (to be cleared) */ |
| 80 | GCObject *tmudata; /* list of userdata to be GC */ | 80 | GCObject *tmudata; /* last element of list of userdata to be GC */ |
| 81 | Mbuffer buff; /* temporary buffer for string concatentation */ | 81 | Mbuffer buff; /* temporary buffer for string concatentation */ |
| 82 | lu_mem GCthreshold; | 82 | lu_mem GCthreshold; |
| 83 | lu_mem totalbytes; /* number of bytes currently allocated */ | 83 | lu_mem totalbytes; /* number of bytes currently allocated */ |
