aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-04-11 15:41:09 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-04-11 15:41:09 -0300
commita3d36fe283c09d4e56474da98f22d13162cc9fec (patch)
tree1f6e2ed56d50dc14aa669fa5f31a63755abd4553 /lgc.c
parent9569ad6b0ddcde43eb893d2cfe5bcdb715c0ff20 (diff)
downloadlua-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.c89
1 files changed, 32 insertions, 57 deletions
diff --git a/lgc.c b/lgc.c
index 68a7622f..f4223588 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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*/
188void 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
197void luaC_fix (lua_State *L, GCObject *o) { 182void 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*/
238static void reallymarkobject (global_State *g, GCObject *o) { 225static 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*/
524static lu_mem traverseLclosure (global_State *g, LClosure *cl) { 515static 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) {
569static void propagatemark (global_State *g) { 555static 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/* 671static 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);
690void 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
698static 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*/
1150static void markold (global_State *g, GCObject *from, GCObject *to) { 1123static 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));
1259lua_checkmemory(L);
1285} 1260}
1286 1261
1287 1262