diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 59 |
1 files changed, 42 insertions, 17 deletions
@@ -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 | */ | ||
964 | static 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 | */ | ||
974 | static 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 | */ |
1035 | static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, | 1052 | static 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 | */ |
1170 | static void youngcollection (lua_State *L, global_State *g) { | 1190 | static 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); |