diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-04-11 15:41:09 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-04-11 15:41:09 -0300 |
commit | a3d36fe283c09d4e56474da98f22d13162cc9fec (patch) | |
tree | 1f6e2ed56d50dc14aa669fa5f31a63755abd4553 /lgc.c | |
parent | 9569ad6b0ddcde43eb893d2cfe5bcdb715c0ff20 (diff) | |
download | lua-a3d36fe283c09d4e56474da98f22d13162cc9fec.tar.gz lua-a3d36fe283c09d4e56474da98f22d13162cc9fec.tar.bz2 lua-a3d36fe283c09d4e56474da98f22d13162cc9fec.zip |
Upvalues collected like everything else (with mark-sweep) instead
of reference count (simpler and better for generational mode)
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 89 |
1 files changed, 32 insertions, 57 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.218 2017/04/06 13:08:56 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.219 2017/04/10 13:33:04 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 | */ |
@@ -179,25 +179,11 @@ void luaC_barrierback_ (lua_State *L, Table *t) { | |||
179 | } | 179 | } |
180 | 180 | ||
181 | 181 | ||
182 | /* | ||
183 | ** barrier for assignments to closed upvalues. Because upvalues are | ||
184 | ** shared among closures, it is impossible to know the color of all | ||
185 | ** closures pointing to it. So, we assume that the object being assigned | ||
186 | ** must be marked. | ||
187 | */ | ||
188 | void luaC_upvalbarrier_ (lua_State *L, GCObject *o) { | ||
189 | global_State *g = G(L); | ||
190 | if (keepinvariant(g) && !isold(o)) { | ||
191 | markobject(g, o); | ||
192 | setage(o, G_OLD0); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | |||
197 | void luaC_fix (lua_State *L, GCObject *o) { | 182 | void luaC_fix (lua_State *L, GCObject *o) { |
198 | global_State *g = G(L); | 183 | global_State *g = G(L); |
199 | lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ | 184 | lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ |
200 | white2gray(o); /* they will be gray forever */ | 185 | white2gray(o); /* they will be gray forever */ |
186 | setage(o, G_OLD); /* and old forever */ | ||
201 | g->allgc = o->next; /* remove object from 'allgc' list */ | 187 | g->allgc = o->next; /* remove object from 'allgc' list */ |
202 | o->next = g->fixedgc; /* link it to 'fixedgc' list */ | 188 | o->next = g->fixedgc; /* link it to 'fixedgc' list */ |
203 | g->fixedgc = o; | 189 | g->fixedgc = o; |
@@ -230,10 +216,11 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { | |||
230 | 216 | ||
231 | 217 | ||
232 | /* | 218 | /* |
233 | ** mark an object. Userdata, strings, and closed upvalues are visited | 219 | ** Mark an object. Userdata, strings, and closed upvalues are visited |
234 | ** and turned black here. Other objects are marked gray and added | 220 | ** and turned black here. Other objects are marked gray and added |
235 | ** to appropriate list to be visited (and turned black) later. (Open | 221 | ** to appropriate list to be visited (and turned black) later. (Open |
236 | ** upvalues are already linked in 'headuv' list.) | 222 | ** upvalues are already linked in 'headuv' list. They are kept gray |
223 | ** to avoid barriers, as their values will be revisited by the thread.) | ||
237 | */ | 224 | */ |
238 | static void reallymarkobject (global_State *g, GCObject *o) { | 225 | static void reallymarkobject (global_State *g, GCObject *o) { |
239 | reentry: | 226 | reentry: |
@@ -261,6 +248,14 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
261 | } | 248 | } |
262 | break; | 249 | break; |
263 | } | 250 | } |
251 | case LUA_TUPVAL: { | ||
252 | UpVal *uv = gco2upv(o); | ||
253 | g->GCmemtrav += sizeof(UpVal); | ||
254 | if (!upisopen(uv)) /* open upvalues are kept gray */ | ||
255 | gray2black(o); | ||
256 | markvalue(g, uv->v); /* mark its content */ | ||
257 | break; | ||
258 | } | ||
264 | case LUA_TLCL: { | 259 | case LUA_TLCL: { |
265 | linkgclist(gco2lcl(o), g->gray); | 260 | linkgclist(gco2lcl(o), g->gray); |
266 | break; | 261 | break; |
@@ -324,10 +319,8 @@ static void remarkupvals (global_State *g) { | |||
324 | *p = thread->twups; /* remove thread from the list */ | 319 | *p = thread->twups; /* remove thread from the list */ |
325 | thread->twups = thread; /* mark that it is out of list */ | 320 | thread->twups = thread; /* mark that it is out of list */ |
326 | for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { | 321 | for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { |
327 | if (uv->u.open.touched) { | 322 | if (!iswhite(uv)) /* upvalue already visited? */ |
328 | markvalue(g, uv->v); /* remark upvalue's value */ | 323 | markvalue(g, uv->v); /* mark its value */ |
329 | uv->u.open.touched = 0; | ||
330 | } | ||
331 | } | 324 | } |
332 | } | 325 | } |
333 | } | 326 | } |
@@ -516,22 +509,15 @@ static lu_mem traverseCclosure (global_State *g, CClosure *cl) { | |||
516 | } | 509 | } |
517 | 510 | ||
518 | /* | 511 | /* |
519 | ** open upvalues point to values in a thread, so those values should | 512 | ** Traverse a Lua closure, marking its prototype and its upvalues. |
520 | ** be marked when the thread is traversed except in the atomic phase | 513 | ** (Both can be NULL while closure is being created.) |
521 | ** (because then the value cannot be changed by the thread and the | ||
522 | ** thread may not be traversed again) | ||
523 | */ | 514 | */ |
524 | static lu_mem traverseLclosure (global_State *g, LClosure *cl) { | 515 | static lu_mem traverseLclosure (global_State *g, LClosure *cl) { |
525 | int i; | 516 | int i; |
526 | markobjectN(g, cl->p); /* mark its prototype */ | 517 | markobjectN(g, cl->p); /* mark its prototype */ |
527 | for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ | 518 | for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ |
528 | UpVal *uv = cl->upvals[i]; | 519 | UpVal *uv = cl->upvals[i]; |
529 | if (uv != NULL) { /* can be NULL while closure is being built */ | 520 | markobjectN(g, uv); /* mark upvalue */ |
530 | if (upisopen(uv) && g->gcstate != GCSatomic) | ||
531 | uv->u.open.touched = 1; /* can be marked in 'remarkupvals' */ | ||
532 | else | ||
533 | markvalue(g, uv->v); | ||
534 | } | ||
535 | } | 521 | } |
536 | return sizeLclosure(cl->nupvalues); | 522 | return sizeLclosure(cl->nupvalues); |
537 | } | 523 | } |
@@ -569,7 +555,6 @@ static lu_mem traversethread (global_State *g, lua_State *th) { | |||
569 | static void propagatemark (global_State *g) { | 555 | static void propagatemark (global_State *g) { |
570 | lu_mem size; | 556 | lu_mem size; |
571 | GCObject *o = g->gray; | 557 | GCObject *o = g->gray; |
572 | lua_assert(ongraylist(o)); | ||
573 | gray2black(o); | 558 | gray2black(o); |
574 | switch (o->tt) { | 559 | switch (o->tt) { |
575 | case LUA_TTABLE: { | 560 | case LUA_TTABLE: { |
@@ -683,26 +668,10 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) { | |||
683 | } | 668 | } |
684 | 669 | ||
685 | 670 | ||
686 | /* | 671 | static void freeupval (lua_State *L, UpVal *uv) { |
687 | ** Decrement the reference count of an upvalue. If it goes to zero and | 672 | if (upisopen(uv)) |
688 | ** upvalue is closed, delete it. | 673 | luaF_unlinkupval(uv); |
689 | */ | 674 | luaM_free(L, uv); |
690 | void luaC_upvdeccount (lua_State *L, UpVal *uv) { | ||
691 | lua_assert(uv->refcount > 0); | ||
692 | uv->refcount--; | ||
693 | if (uv->refcount == 0 && !upisopen(uv)) | ||
694 | luaM_free(L, uv); | ||
695 | } | ||
696 | |||
697 | |||
698 | static void freeLclosure (lua_State *L, LClosure *cl) { | ||
699 | int i; | ||
700 | for (i = 0; i < cl->nupvalues; i++) { | ||
701 | UpVal *uv = cl->upvals[i]; | ||
702 | if (uv) | ||
703 | luaC_upvdeccount(L, uv); | ||
704 | } | ||
705 | luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); | ||
706 | } | 675 | } |
707 | 676 | ||
708 | 677 | ||
@@ -711,8 +680,11 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
711 | case LUA_TPROTO: | 680 | case LUA_TPROTO: |
712 | luaF_freeproto(L, gco2p(o)); | 681 | luaF_freeproto(L, gco2p(o)); |
713 | break; | 682 | break; |
683 | case LUA_TUPVAL: | ||
684 | freeupval(L, gco2upv(o)); | ||
685 | break; | ||
714 | case LUA_TLCL: | 686 | case LUA_TLCL: |
715 | freeLclosure(L, gco2lcl(o)); | 687 | luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); |
716 | break; | 688 | break; |
717 | case LUA_TCCL: | 689 | case LUA_TCCL: |
718 | luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); | 690 | luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); |
@@ -1144,14 +1116,14 @@ static void correctgraylists (global_State *g) { | |||
1144 | 1116 | ||
1145 | 1117 | ||
1146 | /* | 1118 | /* |
1147 | ** Mark 'old1' objects when starting a new young collection. ('old1' | 1119 | ** Mark 'old1' objects when starting a new young collection. (Threads |
1148 | ** tables are always black, threads are always gray.) | 1120 | ** and open upvalues are always gray, and do not need to be marked. |
1121 | ** All other old objects are black.) | ||
1149 | */ | 1122 | */ |
1150 | static void markold (global_State *g, GCObject *from, GCObject *to) { | 1123 | static void markold (global_State *g, GCObject *from, GCObject *to) { |
1151 | GCObject *p; | 1124 | GCObject *p; |
1152 | for (p = from; p != to; p = p->next) { | 1125 | for (p = from; p != to; p = p->next) { |
1153 | if (getage(p) == G_OLD1) { | 1126 | if (getage(p) == G_OLD1) { |
1154 | lua_assert((p->tt == LUA_TTHREAD) ? isgray(p) : isblack(p)); | ||
1155 | if (isblack(p)) { | 1127 | if (isblack(p)) { |
1156 | black2gray(p); /* should be '2white', but gray works too */ | 1128 | black2gray(p); /* should be '2white', but gray works too */ |
1157 | reallymarkobject(g, p); | 1129 | reallymarkobject(g, p); |
@@ -1228,6 +1200,8 @@ static void entergen (lua_State *L, global_State *g) { | |||
1228 | 1200 | ||
1229 | sweep2old(L, &g->tobefnz); | 1201 | sweep2old(L, &g->tobefnz); |
1230 | 1202 | ||
1203 | setage(g->mainthread, G_OLD); | ||
1204 | |||
1231 | finishgencycle(L, g); | 1205 | finishgencycle(L, g); |
1232 | g->gckind = KGC_GEN; | 1206 | g->gckind = KGC_GEN; |
1233 | } | 1207 | } |
@@ -1282,6 +1256,7 @@ static void genstep (lua_State *L, global_State *g) { | |||
1282 | youngcollection(L, g); | 1256 | youngcollection(L, g); |
1283 | mem = gettotalbytes(g); | 1257 | mem = gettotalbytes(g); |
1284 | luaE_setdebt(g, -((mem / 100) * 20)); | 1258 | luaE_setdebt(g, -((mem / 100) * 20)); |
1259 | lua_checkmemory(L); | ||
1285 | } | 1260 | } |
1286 | 1261 | ||
1287 | 1262 | ||