diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-07-29 17:05:47 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-07-29 17:05:47 -0300 |
commit | 0dc5deca1c0182a4a3db2fcfd7bc721f27fb352b (patch) | |
tree | b7af445c2b08aa760b3315c6083c4bb30387f2ee /lgc.c | |
parent | b4c353434f28f3e9d4c45e61d42b4fd07d76cad2 (diff) | |
download | lua-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.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); |