aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c59
1 files changed, 42 insertions, 17 deletions
diff --git a/lgc.c b/lgc.c
index 347b6778..9973c9db 100644
--- a/lgc.c
+++ b/lgc.c
@@ -859,6 +859,8 @@ static GCObject *udata2finalize (global_State *g) {
859 resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ 859 resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */
860 if (issweepphase(g)) 860 if (issweepphase(g))
861 makewhite(g, o); /* "sweep" object */ 861 makewhite(g, o); /* "sweep" object */
862 else if (getage(o) == G_OLD1)
863 g->firstold1 = o; /* it is the first OLD1 object in the list */
862 return o; 864 return o;
863} 865}
864 866
@@ -957,6 +959,27 @@ static void separatetobefnz (global_State *g, int all) {
957 959
958 960
959/* 961/*
962** If pointer 'p' points to 'o', move it to the next element.
963*/
964static void checkpointer (GCObject **p, GCObject *o) {
965 if (o == *p)
966 *p = o->next;
967}
968
969
970/*
971** Correct pointers to objects inside 'allgc' list when
972** object 'o' is being removed from the list.
973*/
974static void correctpointers (global_State *g, GCObject *o) {
975 checkpointer(&g->survival, o);
976 checkpointer(&g->old1, o);
977 checkpointer(&g->reallyold, o);
978 checkpointer(&g->firstold1, o);
979}
980
981
982/*
960** if object 'o' has a finalizer, remove it from 'allgc' list (must 983** if object 'o' has a finalizer, remove it from 'allgc' list (must
961** search the list to find it) and link it in 'finobj' list. 984** search the list to find it) and link it in 'finobj' list.
962*/ 985*/
@@ -972,14 +995,8 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
972 if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ 995 if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */
973 g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ 996 g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */
974 } 997 }
975 else { /* correct pointers into 'allgc' list, if needed */ 998 else
976 if (o == g->survival) 999 correctpointers(g, o);
977 g->survival = o->next;
978 if (o == g->old1)
979 g->old1 = o->next;
980 if (o == g->reallyold)
981 g->reallyold = o->next;
982 }
983 /* search for pointer pointing to 'o' */ 1000 /* search for pointer pointing to 'o' */
984 for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } 1001 for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ }
985 *p = o->next; /* remove 'o' from 'allgc' list */ 1002 *p = o->next; /* remove 'o' from 'allgc' list */
@@ -1033,7 +1050,7 @@ static void sweep2old (lua_State *L, GCObject **p) {
1033** will also remove objects turned white here from any gray list. 1050** will also remove objects turned white here from any gray list.
1034*/ 1051*/
1035static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, 1052static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1036 GCObject *limit) { 1053 GCObject *limit, GCObject **pfirstold1) {
1037 static const lu_byte nextage[] = { 1054 static const lu_byte nextage[] = {
1038 G_SURVIVAL, /* from G_NEW */ 1055 G_SURVIVAL, /* from G_NEW */
1039 G_OLD1, /* from G_SURVIVAL */ 1056 G_OLD1, /* from G_SURVIVAL */
@@ -1056,8 +1073,11 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1056 int marked = curr->marked & maskgcbits; /* erase GC bits */ 1073 int marked = curr->marked & maskgcbits; /* erase GC bits */
1057 curr->marked = cast_byte(marked | G_SURVIVAL | white); 1074 curr->marked = cast_byte(marked | G_SURVIVAL | white);
1058 } 1075 }
1059 else /* all other objects will be old, and so keep their color */ 1076 else { /* all other objects will be old, and so keep their color */
1060 setage(curr, nextage[getage(curr)]); 1077 setage(curr, nextage[getage(curr)]);
1078 if (getage(curr) == G_OLD1 && *pfirstold1 == NULL)
1079 *pfirstold1 = curr; /* first OLD1 object in the list */
1080 }
1061 p = &curr->next; /* go to next element */ 1081 p = &curr->next; /* go to next element */
1062 } 1082 }
1063 } 1083 }
@@ -1169,30 +1189,34 @@ static void finishgencycle (lua_State *L, global_State *g) {
1169*/ 1189*/
1170static void youngcollection (lua_State *L, global_State *g) { 1190static void youngcollection (lua_State *L, global_State *g) {
1171 GCObject **psurvival; /* to point to first non-dead survival object */ 1191 GCObject **psurvival; /* to point to first non-dead survival object */
1192 GCObject *dummy; /* dummy out parameter to 'sweepgen' */
1172 lua_assert(g->gcstate == GCSpropagate); 1193 lua_assert(g->gcstate == GCSpropagate);
1173 markold(g, g->allgc, g->reallyold); 1194 if (g->firstold1) { /* are there OLD1 objects? */
1195 markold(g, g->firstold1, g->reallyold); /* mark them */
1196 g->firstold1 = NULL; /* no more OLD1 objects (for now) */
1197 }
1174 markold(g, g->finobj, g->finobjrold); 1198 markold(g, g->finobj, g->finobjrold);
1175 atomic(L); 1199 atomic(L);
1176 1200
1177 /* sweep nursery and get a pointer to its last live element */ 1201 /* sweep nursery and get a pointer to its last live element */
1178 g->gcstate = GCSswpallgc; 1202 g->gcstate = GCSswpallgc;
1179 psurvival = sweepgen(L, g, &g->allgc, g->survival); 1203 psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1);
1180 /* sweep 'survival' */ 1204 /* sweep 'survival' */
1181 sweepgen(L, g, psurvival, g->old1); 1205 sweepgen(L, g, psurvival, g->old1, &g->firstold1);
1182 g->reallyold = g->old1; 1206 g->reallyold = g->old1;
1183 g->old1 = *psurvival; /* 'survival' survivals are old now */ 1207 g->old1 = *psurvival; /* 'survival' survivals are old now */
1184 g->survival = g->allgc; /* all news are survivals */ 1208 g->survival = g->allgc; /* all news are survivals */
1185 1209
1186 /* repeat for 'finobj' lists */ 1210 /* repeat for 'finobj' lists */
1187 psurvival = sweepgen(L, g, &g->finobj, g->finobjsur); 1211 dummy = NULL; /* no 'firstold1' optimization for 'finobj' lists */
1212 psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy);
1188 /* sweep 'survival' */ 1213 /* sweep 'survival' */
1189 sweepgen(L, g, psurvival, g->finobjold1); 1214 sweepgen(L, g, psurvival, g->finobjold1, &dummy);
1190 g->finobjrold = g->finobjold1; 1215 g->finobjrold = g->finobjold1;
1191 g->finobjold1 = *psurvival; /* 'survival' survivals are old now */ 1216 g->finobjold1 = *psurvival; /* 'survival' survivals are old now */
1192 g->finobjsur = g->finobj; /* all news are survivals */ 1217 g->finobjsur = g->finobj; /* all news are survivals */
1193 1218
1194 sweepgen(L, g, &g->tobefnz, NULL); 1219 sweepgen(L, g, &g->tobefnz, NULL, &dummy);
1195
1196 finishgencycle(L, g); 1220 finishgencycle(L, g);
1197} 1221}
1198 1222
@@ -1203,6 +1227,7 @@ static void atomic2gen (lua_State *L, global_State *g) {
1203 sweep2old(L, &g->allgc); 1227 sweep2old(L, &g->allgc);
1204 /* everything alive now is old */ 1228 /* everything alive now is old */
1205 g->reallyold = g->old1 = g->survival = g->allgc; 1229 g->reallyold = g->old1 = g->survival = g->allgc;
1230 g->firstold1 = NULL; /* there are no OLD1 objects anywhere */
1206 1231
1207 /* repeat for 'finobj' lists */ 1232 /* repeat for 'finobj' lists */
1208 sweep2old(L, &g->finobj); 1233 sweep2old(L, &g->finobj);