aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-02-11 10:18:12 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-02-11 10:18:12 -0200
commitba3586cc90d1ab8d499437dd7c504798371b0e4f (patch)
tree416f99ec601d48a19a7233f6363a7329989a6fd6 /lgc.c
parent68df7c6279421a0a5710afc31e5cd3122e0d3391 (diff)
downloadlua-ba3586cc90d1ab8d499437dd7c504798371b0e4f.tar.gz
lua-ba3586cc90d1ab8d499437dd7c504798371b0e4f.tar.bz2
lua-ba3586cc90d1ab8d499437dd7c504798371b0e4f.zip
keep a single list of objects to be finalized (with local and non-local
objects), to ensure finalization order
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c47
1 files changed, 16 insertions, 31 deletions
diff --git a/lgc.c b/lgc.c
index 0ef4a679..a06af829 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.167 2013/12/13 15:17:00 roberto Exp roberto $ 2** $Id: lgc.c,v 2.168 2013/12/13 15:42:08 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*/
@@ -770,16 +770,16 @@ static GCObject *udata2finalize (global_State *g) {
770 lua_assert(tofinalize(o)); 770 lua_assert(tofinalize(o));
771 g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ 771 g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */
772 if (islocal(o)) { 772 if (islocal(o)) {
773 lua_assert(!testbit(gch(o)->marked, LOCALMARK));
774 gch(o)->next = g->localgc; /* return it to 'localgc' list */ 773 gch(o)->next = g->localgc; /* return it to 'localgc' list */
775 g->localgc = o; 774 g->localgc = o;
775 resetbit(gch(o)->marked, LOCALMARK);
776 } 776 }
777 else { /* return it to 'allgc' list */ 777 else { /* return it to 'allgc' list */
778 gch(o)->next = g->allgc; 778 gch(o)->next = g->allgc;
779 g->allgc = o; 779 g->allgc = o;
780 l_setbit(gch(o)->marked, LOCALMARK); 780 l_setbit(gch(o)->marked, LOCALMARK);
781 } 781 }
782 resetbit(gch(o)->marked, FINALIZEDBIT); /* object is back in 'allgc' */ 782 resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */
783 if (issweepphase(g)) 783 if (issweepphase(g))
784 makewhite(g, o); /* "sweep" object */ 784 makewhite(g, o); /* "sweep" object */
785 return o; 785 return o;
@@ -848,8 +848,9 @@ static GCObject **findlast (GCObject **p) {
848** move all unreachable objects (or 'all' objects) that need 848** move all unreachable objects (or 'all' objects) that need
849** finalization from list 'p' to list 'tobefnz' (to be finalized) 849** finalization from list 'p' to list 'tobefnz' (to be finalized)
850*/ 850*/
851static void separatetobefnz_aux (global_State *g, GCObject **p, int all) { 851static void separatetobefnz (global_State *g, int all) {
852 GCObject *curr; 852 GCObject *curr;
853 GCObject **p = &g->finobj;
853 GCObject **lastnext = findlast(&g->tobefnz); 854 GCObject **lastnext = findlast(&g->tobefnz);
854 while ((curr = *p) != NULL) { /* traverse all finalizable objects */ 855 while ((curr = *p) != NULL) { /* traverse all finalizable objects */
855 lua_assert(tofinalize(curr)); 856 lua_assert(tofinalize(curr));
@@ -865,15 +866,9 @@ static void separatetobefnz_aux (global_State *g, GCObject **p, int all) {
865} 866}
866 867
867 868
868static void separatetobefnz (global_State *g, int all) {
869 separatetobefnz_aux(g, &g->localfin, all);
870 separatetobefnz_aux(g, &g->finobj, all);
871}
872
873
874/* 869/*
875** if object 'o' has a finalizer, remove it from 'allgc' list (must 870** if object 'o' has a finalizer, remove it from 'allgc' list (must
876** search the list to find it) and link it in 'localfin' or 'finobj' list. 871** search the list to find it) and link it in 'finobj' list.
877*/ 872*/
878void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { 873void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
879 global_State *g = G(L); 874 global_State *g = G(L);
@@ -890,9 +885,8 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
890 p = (testbit(o->gch.marked, LOCALMARK)) ? &g->allgc : &g->localgc; 885 p = (testbit(o->gch.marked, LOCALMARK)) ? &g->allgc : &g->localgc;
891 for (; *p != o; p = &gch(*p)->next) { /* empty */ } 886 for (; *p != o; p = &gch(*p)->next) { /* empty */ }
892 *p = o->gch.next; /* remove 'o' from its list */ 887 *p = o->gch.next; /* remove 'o' from its list */
893 p = (testbit(o->gch.marked, LOCALMARK)) ? &g->finobj : &g->localfin; 888 o->gch.next = g->finobj; /* link it in "fin" list */
894 o->gch.next = *p; /* link it in a "fin" list */ 889 g->finobj = o;
895 *p = o;
896 l_setbit(o->gch.marked, FINALIZEDBIT); /* mark it as such */ 890 l_setbit(o->gch.marked, FINALIZEDBIT); /* mark it as such */
897 if (issweepphase(g)) 891 if (issweepphase(g))
898 makewhite(g, o); /* "sweep" object */ 892 makewhite(g, o); /* "sweep" object */
@@ -966,20 +960,15 @@ static void localsweep (lua_State *L, global_State *g) {
966} 960}
967 961
968 962
969static void separatelocal (global_State *g, int all) { 963static void separatelocal (global_State *g) {
970 GCObject **p = &g->localfin; 964 GCObject **p = &g->finobj;
971 GCObject **lastnext = findlast(&g->tobefnz); 965 GCObject **lastnext = findlast(&g->tobefnz);
972 while (*p != NULL) { 966 while (*p != NULL) {
973 GCObject *curr = *p; 967 GCObject *curr = *p;
974 if (!islocal(curr)) { /* is 'curr' no more local? */ 968 if (!islocal(curr)) /* is 'curr' no more local? */
975 *p = curr->gch.next; /* remove 'curr' from list */ 969 p = &curr->gch.next; /* go to next element */
976 curr->gch.next = g->finobj; /* link 'curr' in 'finobj' list */
977 g->finobj = curr;
978 /* mark it as out of local list */
979 l_setbit(curr->gch.marked, LOCALMARK);
980 }
981 else { /* still local */ 970 else { /* still local */
982 if (testbit(curr->gch.marked, LOCALMARK) && !all) { /* locally alive? */ 971 if (testbit(curr->gch.marked, LOCALMARK)) { /* locally alive? */
983 resetbit(curr->gch.marked, LOCALMARK); 972 resetbit(curr->gch.marked, LOCALMARK);
984 p = &curr->gch.next; /* go to next element */ 973 p = &curr->gch.next; /* go to next element */
985 } 974 }
@@ -999,7 +988,7 @@ static void luaC_localcollection (lua_State *L) {
999 lua_assert(g->gcstate == GCSpause); 988 lua_assert(g->gcstate == GCSpause);
1000 localmark(g); 989 localmark(g);
1001 localsweep(L, g); 990 localsweep(L, g);
1002 separatelocal(g, 0); 991 separatelocal(g);
1003 callallpendingfinalizers(L, 1); 992 callallpendingfinalizers(L, 1);
1004} 993}
1005 994
@@ -1050,13 +1039,12 @@ static int entersweep (lua_State *L) {
1050void luaC_freeallobjects (lua_State *L) { 1039void luaC_freeallobjects (lua_State *L) {
1051 global_State *g = G(L); 1040 global_State *g = G(L);
1052 separatetobefnz(g, 1); /* separate all objects with finalizers */ 1041 separatetobefnz(g, 1); /* separate all objects with finalizers */
1053 lua_assert(g->finobj == NULL && g->localfin == NULL); 1042 lua_assert(g->finobj == NULL);
1054 callallpendingfinalizers(L, 0); 1043 callallpendingfinalizers(L, 0);
1055 lua_assert(g->tobefnz == NULL); 1044 lua_assert(g->tobefnz == NULL);
1056 g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ 1045 g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */
1057 g->gckind = KGC_NORMAL; 1046 g->gckind = KGC_NORMAL;
1058 sweepwholelist(L, &g->localgc); 1047 sweepwholelist(L, &g->localgc);
1059 sweepwholelist(L, &g->localfin); /* finalizers can create objs. with fins. */
1060 sweepwholelist(L, &g->finobj); 1048 sweepwholelist(L, &g->finobj);
1061 sweepwholelist(L, &g->allgc); 1049 sweepwholelist(L, &g->allgc);
1062 sweepwholelist(L, &g->mainthread->next); 1050 sweepwholelist(L, &g->mainthread->next);
@@ -1155,12 +1143,9 @@ static lu_mem singlestep (lua_State *L) {
1155 return sweepstep(L, g, GCSswpthreads, &g->mainthread->next); 1143 return sweepstep(L, g, GCSswpthreads, &g->mainthread->next);
1156 } 1144 }
1157 case GCSswpthreads: { /* sweep threads */ 1145 case GCSswpthreads: { /* sweep threads */
1158 return sweepstep(L, g, GCSswplocalfin, &g->localfin);
1159 }
1160 case GCSswplocalfin: { /* sweep local objects with finalizers */
1161 return sweepstep(L, g, GCSswpfinobj, &g->finobj); 1146 return sweepstep(L, g, GCSswpfinobj, &g->finobj);
1162 } 1147 }
1163 case GCSswpfinobj: { /* sweep non-local objects with finalizers */ 1148 case GCSswpfinobj: { /* sweep objects with finalizers */
1164 return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); 1149 return sweepstep(L, g, GCSswptobefnz, &g->tobefnz);
1165 } 1150 }
1166 case GCSswptobefnz: { /* sweep objects to be finalized */ 1151 case GCSswptobefnz: { /* sweep objects to be finalized */