aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-07-29 17:05:47 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-07-29 17:05:47 -0300
commit0dc5deca1c0182a4a3db2fcfd7bc721f27fb352b (patch)
treeb7af445c2b08aa760b3315c6083c4bb30387f2ee /lgc.c
parentb4c353434f28f3e9d4c45e61d42b4fd07d76cad2 (diff)
downloadlua-0dc5deca1c0182a4a3db2fcfd7bc721f27fb352b.tar.gz
lua-0dc5deca1c0182a4a3db2fcfd7bc721f27fb352b.tar.bz2
lua-0dc5deca1c0182a4a3db2fcfd7bc721f27fb352b.zip
Optimization in 'markold'
OLD1 objects can be potentially anywhere in the 'allgc' list (up to 'reallyold'), but frequently they are all after 'old1' (natural evolution of survivals) or do not exist at all (when all objects die young). So, instead of 'markold' starts looking for them always from the start of 'allgc', the collector keeps an extra pointer, 'firstold1', that points to the first OLD1 object in the 'allgc' list, or is NULL if there are no OLD1 objects in that list.
Diffstat (limited to '')
-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);