aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2013-08-27 15:53:35 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2013-08-27 15:53:35 -0300
commitaf35c7f398e8149b5f2481b63b399674e4ecdf7e (patch)
tree7d74f5c81bb0e2555cab4bce00a94a12a6d78604 /lgc.c
parent742b7377d38e43224ee5dda4bb83a42763c20af8 (diff)
downloadlua-af35c7f398e8149b5f2481b63b399674e4ecdf7e.tar.gz
lua-af35c7f398e8149b5f2481b63b399674e4ecdf7e.tar.bz2
lua-af35c7f398e8149b5f2481b63b399674e4ecdf7e.zip
upvalues collected by reference count
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c142
1 files changed, 58 insertions, 84 deletions
diff --git a/lgc.c b/lgc.c
index d87d5afe..f09af8e7 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.151 2013/08/23 13:34:54 roberto Exp roberto $ 2** $Id: lgc.c,v 2.152 2013/08/26 12:41:10 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*/
@@ -85,12 +85,9 @@
85 lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \ 85 lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \
86 marklocalvalue(g,o); } 86 marklocalvalue(g,o); }
87 87
88#define marklocalobject(g,t) { \
89 if ((t) && iswhite(obj2gco(t))) \
90 reallymarkobject(g, obj2gco(t)); }
91
92#define markobject(g,t) \ 88#define markobject(g,t) \
93 { lua_assert((t) == NULL || !islocal(obj2gco(t))); marklocalobject(g,t); } 89 { lua_assert((t) == NULL || !islocal(obj2gco(t))); \
90 if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); }
94 91
95static void reallymarkobject (global_State *g, GCObject *o); 92static void reallymarkobject (global_State *g, GCObject *o);
96 93
@@ -176,22 +173,18 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) {
176 173
177 174
178/* 175/*
179** check color (and invariants) for an upvalue that is being closed, 176** barrier for assignments to closed upvalues. Because upvalues are
180** i.e., moved into the 'allgc' list 177** shared among closures, it is impossible to know the color of all
178** closured pointing to it. So, we assume that the object being assigned
179** must be marked.
181*/ 180*/
182void luaC_checkupvalcolor (global_State *g, UpVal *uv) { 181LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
183 GCObject *o = obj2gco(uv); 182 global_State *g = G(L);
184 lua_assert(!isblack(o)); /* open upvalues are never black */ 183 GCObject *o = gcvalue(uv->v);
185 if (isgray(o)) { 184 lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */
186 if (keepinvariant(g)) { 185 nolocal(o);
187 gray2black(o); /* it is being visited now */ 186 if (keepinvariant(g))
188 markvalue(g, uv->v); 187 markobject(g, o);
189 }
190 else {
191 lua_assert(issweepphase(g));
192 makewhite(g, o);
193 }
194 }
195} 188}
196 189
197 190
@@ -257,14 +250,6 @@ static void reallymarkobject (global_State *g, GCObject *o) {
257 size = sizeudata(gco2u(o)); 250 size = sizeudata(gco2u(o));
258 break; 251 break;
259 } 252 }
260 case LUA_TUPVAL: {
261 UpVal *uv = gco2uv(o);
262 marklocalvalue(g, uv->v);
263 if (uv->v != &uv->value) /* open? */
264 return; /* open upvalues remain gray */
265 size = sizeof(UpVal);
266 break;
267 }
268 case LUA_TLCL: { 253 case LUA_TLCL: {
269 gco2lcl(o)->gclist = g->gray; 254 gco2lcl(o)->gclist = g->gray;
270 g->gray = o; 255 g->gray = o;
@@ -328,10 +313,12 @@ static void remarkupvals (global_State *g) {
328 for (; thread != NULL; thread = gch(thread)->next) { 313 for (; thread != NULL; thread = gch(thread)->next) {
329 lua_assert(!isblack(thread)); /* threads are never black */ 314 lua_assert(!isblack(thread)); /* threads are never black */
330 if (!isgray(thread)) { /* dead thread? */ 315 if (!isgray(thread)) { /* dead thread? */
331 GCObject *uv = gco2th(thread)->openupval; 316 UpVal *uv = gco2th(thread)->openupval;
332 for (; uv != NULL; uv = gch(uv)->next) { 317 for (; uv != NULL; uv = uv->u.op.next) {
333 if (isgray(uv)) /* marked? */ 318 if (uv->u.op.touched) {
334 marklocalvalue(g, gco2uv(uv)->v); /* remark upvalue's value */ 319 marklocalvalue(g, uv->v); /* remark upvalue's value */
320 uv->u.op.touched = 0;
321 }
335 } 322 }
336 } 323 }
337 } 324 }
@@ -493,8 +480,15 @@ static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
493static lu_mem traverseLclosure (global_State *g, LClosure *cl) { 480static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
494 int i; 481 int i;
495 markobject(g, cl->p); /* mark its prototype */ 482 markobject(g, cl->p); /* mark its prototype */
496 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ 483 for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */
497 marklocalobject(g, cl->upvals[i]); 484 UpVal *uv = cl->upvals[i];
485 if (uv != NULL) {
486 if (upisopen(uv))
487 uv->u.op.touched = 1; /* can be marked in 'remarkupvals' */
488 else
489 markvalue(g, uv->v);
490 }
491 }
498 return sizeLclosure(cl->nupvalues); 492 return sizeLclosure(cl->nupvalues);
499} 493}
500 494
@@ -511,10 +505,14 @@ static lu_mem traversestack (global_State *g, lua_State *th) {
511 for (; o < lim; o++) /* clear not-marked stack slice */ 505 for (; o < lim; o++) /* clear not-marked stack slice */
512 setnilvalue(o); 506 setnilvalue(o);
513 } 507 }
514 else { /* count call infos to compute size */ 508 else {
515 CallInfo *ci; 509 CallInfo *ci;
510 luaE_freeCI(th); /* free extra CallInfo slots */
516 for (ci = &th->base_ci; ci != th->ci; ci = ci->next) 511 for (ci = &th->base_ci; ci != th->ci; ci = ci->next)
517 n++; 512 n++; /* count call infos to compute size */
513 /* should not change the stack during an emergency gc cycle */
514 if (g->gckind != KGC_EMERGENCY)
515 luaD_shrinkstack(th);
518 } 516 }
519 return sizeof(lua_State) + sizeof(TValue) * th->stacksize + 517 return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
520 sizeof(CallInfo) * n; 518 sizeof(CallInfo) * n;
@@ -667,18 +665,36 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
667} 665}
668 666
669 667
668void luaC_upvdeccount (lua_State *L, UpVal *uv) {
669 lua_assert(uv->refcount > 0);
670 uv->refcount--;
671 if (uv->refcount == 0 && !upisopen(uv))
672 luaM_free(L, uv);
673}
674
675
676static void freeLclosure (lua_State *L, LClosure *cl) {
677 int i;
678 for (i = 0; i < cl->nupvalues; i++) {
679 UpVal *uv = cl->upvals[i];
680 if (uv)
681 luaC_upvdeccount(L, uv);
682 }
683 luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));
684}
685
686
670static void freeobj (lua_State *L, GCObject *o) { 687static void freeobj (lua_State *L, GCObject *o) {
671 switch (gch(o)->tt) { 688 switch (gch(o)->tt) {
672 case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; 689 case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
673 case LUA_TLCL: { 690 case LUA_TLCL: {
674 luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); 691 freeLclosure(L, gco2lcl(o));
675 break; 692 break;
676 } 693 }
677 case LUA_TCCL: { 694 case LUA_TCCL: {
678 luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); 695 luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues));
679 break; 696 break;
680 } 697 }
681 case LUA_TUPVAL: luaM_free(L, gco2uv(o)); break;
682 case LUA_TTABLE: luaH_free(L, gco2t(o)); break; 698 case LUA_TTABLE: luaH_free(L, gco2t(o)); break;
683 case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; 699 case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break;
684 case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; 700 case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
@@ -699,20 +715,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count);
699 715
700 716
701/* 717/*
702** sweep the (open) upvalues of a thread and resize its stack and
703** list of call-info structures.
704*/
705static void sweepthread (lua_State *L, lua_State *L1) {
706 if (L1->stack == NULL) return; /* stack not completely built yet */
707 sweepwholelist(L, &L1->openupval); /* sweep open upvalues */
708 luaE_freeCI(L1); /* free extra CallInfo slots */
709 /* should not change the stack during an emergency gc cycle */
710 if (G(L)->gckind != KGC_EMERGENCY)
711 luaD_shrinkstack(L1);
712}
713
714
715/*
716** sweep at most 'count' elements from a list of GCObjects erasing dead 718** sweep at most 'count' elements from a list of GCObjects erasing dead
717** objects, where a dead (not alive) object is one marked with the "old" 719** objects, where a dead (not alive) object is one marked with the "old"
718** (non current) white and not fixed; change all non-dead objects back 720** (non current) white and not fixed; change all non-dead objects back
@@ -730,10 +732,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
730 *p = gch(curr)->next; /* remove 'curr' from list */ 732 *p = gch(curr)->next; /* remove 'curr' from list */
731 freeobj(L, curr); /* erase 'curr' */ 733 freeobj(L, curr); /* erase 'curr' */
732 } 734 }
733 else { 735 else { /* update marks */
734 if (gch(curr)->tt == LUA_TTHREAD)
735 sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */
736 /* update marks */
737 gch(curr)->marked = cast_byte((marked & maskcolors) | white); 736 gch(curr)->marked = cast_byte((marked & maskcolors) | white);
738 p = &gch(curr)->next; /* go to next element */ 737 p = &gch(curr)->next; /* go to next element */
739 } 738 }
@@ -886,16 +885,6 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
886*/ 885*/
887 886
888 887
889static void localmarkclosure (LClosure *cl, int bit) {
890 int i;
891 for (i = 0; i < cl->nupvalues; i++) {
892 if (cl->upvals[i]) {
893 l_setbit(cl->upvals[i]->marked, bit);
894 }
895 }
896}
897
898
899/* 888/*
900** Traverse a thread, local marking all its collectable objects 889** Traverse a thread, local marking all its collectable objects
901*/ 890*/
@@ -904,16 +893,8 @@ static void localmarkthread (lua_State *l) {
904 if (o == NULL) 893 if (o == NULL)
905 return; /* stack not completely built yet */ 894 return; /* stack not completely built yet */
906 for (; o < l->top; o++) { /* mark live elements in the stack */ 895 for (; o < l->top; o++) { /* mark live elements in the stack */
907 if (iscollectable(o)) { 896 if (iscollectable(o))
908 GCObject *obj = gcvalue(o); 897 l_setbit(gcvalue(o)->gch.marked, LOCALBLACK);
909 if (obj->gch.tt == LUA_TLCL && /* is it a Lua closure? */
910 islocal(obj) && /* is it still local? */
911 !testbit(obj->gch.marked, LOCALBLACK)) { /* not visited yet? */
912 /* mark its upvalues as local black */
913 localmarkclosure(gco2lcl(obj), LOCALBLACK);
914 }
915 l_setbit(obj->gch.marked, LOCALBLACK);
916 }
917 } 898 }
918} 899}
919 900
@@ -937,10 +918,6 @@ static void localsweep (lua_State *L, global_State *g, GCObject **p) {
937 *p = curr->gch.next; /* remove 'curr' from list */ 918 *p = curr->gch.next; /* remove 'curr' from list */
938 curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */ 919 curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */
939 g->allgc = curr; 920 g->allgc = curr;
940 if (curr->gch.tt == LUA_TLCL) { /* is it a Lua closure? */
941 /* mark its upvalues as non local */
942 localmarkclosure(gco2lcl(curr), LOCALBIT);
943 }
944 } 921 }
945 else { /* still local */ 922 else { /* still local */
946 if (testbit(curr->gch.marked, LOCALBLACK)) { /* locally alive? */ 923 if (testbit(curr->gch.marked, LOCALBLACK)) { /* locally alive? */
@@ -965,7 +942,6 @@ static void luaC_localcollection (lua_State *L) {
965 lua_assert(g->gcstate == GCSpause); 942 lua_assert(g->gcstate == GCSpause);
966 localmark(g); 943 localmark(g);
967 localsweep(L, g, &g->localgc); 944 localsweep(L, g, &g->localgc);
968 localsweep(L, g, &g->localupv);
969} 945}
970 946
971/* }====================================================== */ 947/* }====================================================== */
@@ -1036,7 +1012,6 @@ void luaC_freeallobjects (lua_State *L) {
1036 g->gckind = KGC_NORMAL; 1012 g->gckind = KGC_NORMAL;
1037 sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ 1013 sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */
1038 sweepwholelist(L, &g->localgc); 1014 sweepwholelist(L, &g->localgc);
1039 sweepwholelist(L, &g->localupv);
1040 sweepwholelist(L, &g->allgc); 1015 sweepwholelist(L, &g->allgc);
1041 sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ 1016 sweepwholelist(L, &g->fixedgc); /* collect fixed objects */
1042 lua_assert(g->strt.nuse == 0); 1017 lua_assert(g->strt.nuse == 0);
@@ -1119,7 +1094,6 @@ static lu_mem singlestep (lua_State *L) {
1119 } 1094 }
1120 else { 1095 else {
1121 sweepwholelist(L, &g->localgc); 1096 sweepwholelist(L, &g->localgc);
1122 sweepwholelist(L, &g->localupv);
1123 g->gcstate = GCSsweep; 1097 g->gcstate = GCSsweep;
1124 return GCLOCALPAUSE / 4; /* some magic for now */ 1098 return GCLOCALPAUSE / 4; /* some magic for now */
1125 } 1099 }