summaryrefslogtreecommitdiff
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
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
-rw-r--r--lgc.c47
-rw-r--r--lgc.h15
-rw-r--r--lstate.c4
-rw-r--r--lstate.h6
-rw-r--r--ltests.c25
5 files changed, 37 insertions, 60 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 */
diff --git a/lgc.h b/lgc.h
index 88bd556a..43cfb851 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 2.75 2013/09/11 14:47:08 roberto Exp roberto $ 2** $Id: lgc.h,v 2.76 2013/09/11 20:15:31 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*/
@@ -39,13 +39,12 @@
39#define GCSpropagate 0 39#define GCSpropagate 0
40#define GCSatomic 1 40#define GCSatomic 1
41#define GCSswplocalgc 2 41#define GCSswplocalgc 2
42#define GCSswpallgc 4 42#define GCSswpallgc 3
43#define GCSswpthreads 3 43#define GCSswpthreads 4
44#define GCSswplocalfin 5 44#define GCSswpfinobj 5
45#define GCSswpfinobj 6 45#define GCSswptobefnz 6
46#define GCSswptobefnz 7 46#define GCSswpend 7
47#define GCSswpend 8 47#define GCSpause 8
48#define GCSpause 9
49 48
50 49
51#define issweepphase(g) \ 50#define issweepphase(g) \
diff --git a/lstate.c b/lstate.c
index fafef92e..2f21f98e 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.115 2013/09/17 15:40:06 roberto Exp roberto $ 2** $Id: lstate.c,v 2.116 2013/11/08 17:34:22 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*/
@@ -320,7 +320,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
320 g->panic = NULL; 320 g->panic = NULL;
321 g->version = NULL; 321 g->version = NULL;
322 g->gcstate = GCSpause; 322 g->gcstate = GCSpause;
323 g->localgc = g->localfin = g->allgc = g->finobj = NULL; 323 g->localgc = g->allgc = g->finobj = NULL;
324 g->tobefnz = NULL; 324 g->tobefnz = NULL;
325 g->fixedgc = NULL; 325 g->fixedgc = NULL;
326 g->sweepgc = NULL; 326 g->sweepgc = NULL;
diff --git a/lstate.h b/lstate.h
index e32f8b4f..49b5d24e 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.96 2013/09/13 16:21:52 roberto Exp roberto $ 2** $Id: lstate.h,v 2.97 2013/09/17 15:40:06 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*/
@@ -23,9 +23,8 @@
23** 23**
24** mainthread->next: all threads; 24** mainthread->next: all threads;
25** localgc: all local objects not marked for finalization; 25** localgc: all local objects not marked for finalization;
26** localfin: all local objects marked for finalization;
27** allgc: all non local objects not marked for finalization; 26** allgc: all non local objects not marked for finalization;
28** finobj: all non local objects marked for finalization; 27** finobj: all objects marked for finalization;
29** tobefnz: all objects ready to be finalized; 28** tobefnz: all objects ready to be finalized;
30** fixedgc: all objects that are not to be collected (currently 29** fixedgc: all objects that are not to be collected (currently
31** only small strings, such as reserved words). 30** only small strings, such as reserved words).
@@ -119,7 +118,6 @@ typedef struct global_State {
119 lu_byte gcrunning; /* true if GC is running */ 118 lu_byte gcrunning; /* true if GC is running */
120 GCObject *allgc; /* list of all collectable objects */ 119 GCObject *allgc; /* list of all collectable objects */
121 GCObject *localgc; /* list of local objects */ 120 GCObject *localgc; /* list of local objects */
122 GCObject *localfin; /* list of local objects with finalizers */
123 GCObject **sweepgc; /* current position of sweep in list */ 121 GCObject **sweepgc; /* current position of sweep in list */
124 GCObject *finobj; /* list of collectable objects with finalizers */ 122 GCObject *finobj; /* list of collectable objects with finalizers */
125 GCObject *gray; /* list of gray objects */ 123 GCObject *gray; /* list of gray objects */
diff --git a/ltests.c b/ltests.c
index d062d167..6923cef5 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.161 2013/12/18 14:12:03 roberto Exp roberto $ 2** $Id: ltests.c,v 2.162 2013/12/30 20:47:58 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -338,7 +338,6 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) {
338 lua_assert(maybedead); 338 lua_assert(maybedead);
339 else { 339 else {
340 lua_assert(g->gcstate != GCSpause || iswhite(o)); 340 lua_assert(g->gcstate != GCSpause || iswhite(o));
341 lua_assert(!islocal(o) || !testbit(gch(o)->marked, LOCALMARK));
342 switch (gch(o)->tt) { 341 switch (gch(o)->tt) {
343 case LUA_TUSERDATA: { 342 case LUA_TUSERDATA: {
344 Table *mt = gco2u(o)->metatable; 343 Table *mt = gco2u(o)->metatable;
@@ -456,19 +455,12 @@ int lua_checkmemory (lua_State *L) {
456 lua_assert(testbit(o->gch.marked, NOLOCALBIT)); 455 lua_assert(testbit(o->gch.marked, NOLOCALBIT));
457 lua_assert(gch(o)->tt == LUA_TTHREAD); 456 lua_assert(gch(o)->tt == LUA_TTHREAD);
458 } 457 }
459 /* check 'localfin' list */
460 checkgray(g, g->localfin);
461 for (o = g->localfin; o != NULL; o = gch(o)->next) {
462 checkobject(g, o, 0);
463 lua_assert(tofinalize(o) && !testbit(o->gch.marked, LOCALMARK));
464 lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE);
465 }
466 /* check 'finobj' list */ 458 /* check 'finobj' list */
467 checkgray(g, g->finobj); 459 checkgray(g, g->finobj);
468 for (o = g->finobj; o != NULL; o = gch(o)->next) { 460 for (o = g->finobj; o != NULL; o = gch(o)->next) {
469 checkobject(g, o, 0); 461 checkobject(g, o, 0);
470 lua_assert(tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); 462 lua_assert(tofinalize(o));
471 lua_assert(testbit(o->gch.marked, NOLOCALBIT)); 463 lua_assert(!islocal(o) || !testbit(gch(o)->marked, LOCALMARK));
472 lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE); 464 lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE);
473 } 465 }
474 /* check 'tobefnz' list */ 466 /* check 'tobefnz' list */
@@ -655,10 +647,13 @@ static int gc_local (lua_State *L) {
655 647
656static int gc_state (lua_State *L) { 648static int gc_state (lua_State *L) {
657 static const char *statenames[] = {"propagate", "atomic", 649 static const char *statenames[] = {"propagate", "atomic",
658 "sweeplocalgc", "sweepallgc", "sweepthreads", "sweeplocalfin", 650 "sweeplocalgc", "sweepallgc", "sweepthreads", "sweepfinobj",
659 "sweepfinobj", "sweeptobefnz", "sweepend", "pause", ""}; 651 "sweeptobefnz", "sweepend", "pause", ""};
660 int option = luaL_checkoption(L, 1, "", statenames); 652 static const int states[] = {GCSpropagate, GCSatomic,
661 if (option == GCSpause + 1) { 653 GCSswplocalgc, GCSswpallgc, GCSswpthreads, GCSswpfinobj,
654 GCSswptobefnz, GCSswpend, GCSpause, -1};
655 int option = states[luaL_checkoption(L, 1, "", statenames)];
656 if (option == -1) {
662 lua_pushstring(L, statenames[G(L)->gcstate]); 657 lua_pushstring(L, statenames[G(L)->gcstate]);
663 return 1; 658 return 1;
664 } 659 }