aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-08-13 15:23:21 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-08-13 15:23:21 -0300
commitf849885a4b49f2d766e6befc67475c05240023eb (patch)
treeab680958b8cac3cef61c63d5c54c448db7f100ae
parentf7ce7e5faae69fcab0126d8bfd34b685f1dcb019 (diff)
downloadlua-f849885a4b49f2d766e6befc67475c05240023eb.tar.gz
lua-f849885a4b49f2d766e6befc67475c05240023eb.tar.bz2
lua-f849885a4b49f2d766e6befc67475c05240023eb.zip
Small changes in macros that change GC colors
- Macro 'gray2black' was renamed 'nw2black' (Non-White to black), as it was already being used on objects that could be already black. - Macros 'white2gray' and 'black2gray' were unified in 'set2gray'; no reason to have two macros when one will do and, again, 'black2gray' was already being used on objects that could be already gray. Moreover, macros 'maskcolors' and 'maskgcbits' were negated to have ones in the described bits, instead of zeros. (This naming seems more intuitive.)
-rw-r--r--lfunc.c2
-rw-r--r--lgc.c54
-rw-r--r--lgc.h23
3 files changed, 40 insertions, 39 deletions
diff --git a/lfunc.c b/lfunc.c
index f8c3c446..88d45328 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -235,7 +235,7 @@ int luaF_close (lua_State *L, StkId level, int status) {
235 setobj(L, slot, uv->v); /* move value to upvalue slot */ 235 setobj(L, slot, uv->v); /* move value to upvalue slot */
236 uv->v = slot; /* now current value lives here */ 236 uv->v = slot; /* now current value lives here */
237 if (!iswhite(uv)) { /* neither white nor dead? */ 237 if (!iswhite(uv)) { /* neither white nor dead? */
238 gray2black(uv); /* closed upvalues cannot be gray */ 238 nw2black(uv); /* closed upvalues cannot be gray */
239 luaC_barrier(L, uv, slot); 239 luaC_barrier(L, uv, slot);
240 } 240 }
241 } 241 }
diff --git a/lgc.c b/lgc.c
index 28c31715..be125dd7 100644
--- a/lgc.c
+++ b/lgc.c
@@ -60,19 +60,19 @@
60#define PAUSEADJ 100 60#define PAUSEADJ 100
61 61
62 62
63/* mask to erase all color bits */ 63/* mask with all color bits */
64#define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) 64#define maskcolors (bitmask(BLACKBIT) | WHITEBITS)
65 65
66/* mask to erase all GC bits */ 66/* mask with all GC bits */
67#define maskgcbits (maskcolors & ~AGEBITS) 67#define maskgcbits (maskcolors | AGEBITS)
68 68
69 69
70/* macro to erase all color bits then set only the current white bit */ 70/* macro to erase all color bits then set only the current white bit */
71#define makewhite(g,x) \ 71#define makewhite(g,x) \
72 (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) 72 (x->marked = cast_byte((x->marked & ~maskcolors) | luaC_white(g)))
73 73
74#define white2gray(x) resetbits(x->marked, WHITEBITS) 74/* make an object gray (neither white nor black) */
75#define black2gray(x) resetbit(x->marked, BLACKBIT) 75#define set2gray(x) resetbits(x->marked, maskcolors)
76 76
77 77
78#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) 78#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
@@ -221,7 +221,7 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) {
221 lua_assert((g->gckind == KGC_GEN) == (isold(o) && getage(o) != G_TOUCHED1)); 221 lua_assert((g->gckind == KGC_GEN) == (isold(o) && getage(o) != G_TOUCHED1));
222 if (getage(o) != G_TOUCHED2) /* not already in gray list? */ 222 if (getage(o) != G_TOUCHED2) /* not already in gray list? */
223 linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */ 223 linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */
224 black2gray(o); /* make object gray (again) */ 224 set2gray(o); /* make object gray (again) */
225 if (isold(o)) /* generational mode? */ 225 if (isold(o)) /* generational mode? */
226 setage(o, G_TOUCHED1); /* touched in current cycle */ 226 setage(o, G_TOUCHED1); /* touched in current cycle */
227} 227}
@@ -230,7 +230,7 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) {
230void luaC_fix (lua_State *L, GCObject *o) { 230void luaC_fix (lua_State *L, GCObject *o) {
231 global_State *g = G(L); 231 global_State *g = G(L);
232 lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ 232 lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */
233 white2gray(o); /* they will be gray forever */ 233 set2gray(o); /* they will be gray forever */
234 setage(o, G_OLD); /* and old forever */ 234 setage(o, G_OLD); /* and old forever */
235 g->allgc = o->next; /* remove object from 'allgc' list */ 235 g->allgc = o->next; /* remove object from 'allgc' list */
236 o->next = g->fixedgc; /* link it to 'fixedgc' list */ 236 o->next = g->fixedgc; /* link it to 'fixedgc' list */
@@ -272,17 +272,17 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
272** the thread or by 'remarkupvals'.) 272** the thread or by 'remarkupvals'.)
273*/ 273*/
274static void reallymarkobject (global_State *g, GCObject *o) { 274static void reallymarkobject (global_State *g, GCObject *o) {
275 white2gray(o); 275 set2gray(o);
276 switch (o->tt) { 276 switch (o->tt) {
277 case LUA_VSHRSTR: 277 case LUA_VSHRSTR:
278 case LUA_VLNGSTR: { 278 case LUA_VLNGSTR: {
279 gray2black(o); /* nothing to visit */ 279 nw2black(o); /* nothing to visit */
280 break; 280 break;
281 } 281 }
282 case LUA_VUPVAL: { 282 case LUA_VUPVAL: {
283 UpVal *uv = gco2upv(o); 283 UpVal *uv = gco2upv(o);
284 if (!upisopen(uv)) /* open upvalues are kept gray */ 284 if (!upisopen(uv)) /* open upvalues are kept gray */
285 gray2black(o); /* closed upvalues are visited here */ 285 nw2black(o); /* closed upvalues are visited here */
286 markvalue(g, uv->v); /* mark its content */ 286 markvalue(g, uv->v); /* mark its content */
287 break; 287 break;
288 } 288 }
@@ -290,7 +290,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
290 Udata *u = gco2u(o); 290 Udata *u = gco2u(o);
291 if (u->nuvalue == 0) { /* no user values? */ 291 if (u->nuvalue == 0) { /* no user values? */
292 markobjectN(g, u->metatable); /* mark its metatable */ 292 markobjectN(g, u->metatable); /* mark its metatable */
293 gray2black(o); /* nothing else to mark */ 293 nw2black(o); /* nothing else to mark */
294 break; 294 break;
295 } 295 }
296 /* else... */ 296 /* else... */
@@ -412,7 +412,7 @@ static void genlink_ (global_State *g, GCObject *o, GCObject **pnext) {
412 if (getage(o) == G_TOUCHED1) { /* touched in this cycle? */ 412 if (getage(o) == G_TOUCHED1) { /* touched in this cycle? */
413 *pnext = g->grayagain; /* link it back in 'grayagain' */ 413 *pnext = g->grayagain; /* link it back in 'grayagain' */
414 g->grayagain = o; 414 g->grayagain = o;
415 black2gray(o); 415 set2gray(o);
416 } /* everything else do not need to be linked back */ 416 } /* everything else do not need to be linked back */
417 else if (getage(o) == G_TOUCHED2) 417 else if (getage(o) == G_TOUCHED2)
418 changeage(o, G_TOUCHED2, G_OLD); /* advance age */ 418 changeage(o, G_TOUCHED2, G_OLD); /* advance age */
@@ -497,7 +497,7 @@ static int traverseephemeron (global_State *g, Table *h, int inv) {
497 else if (hasclears) /* table has white keys? */ 497 else if (hasclears) /* table has white keys? */
498 linkgclist(h, g->allweak); /* may have to clean white keys */ 498 linkgclist(h, g->allweak); /* may have to clean white keys */
499 else { 499 else {
500 gray2black(h); /* 'genlink' expects black objects */ 500 nw2black(h); /* 'genlink' expects black objects */
501 genlink(g, h); /* check whether collector still needs to see it */ 501 genlink(g, h); /* check whether collector still needs to see it */
502 } 502 }
503 return marked; 503 return marked;
@@ -531,7 +531,7 @@ static lu_mem traversetable (global_State *g, Table *h) {
531 (cast_void(weakkey = strchr(svalue(mode), 'k')), 531 (cast_void(weakkey = strchr(svalue(mode), 'k')),
532 cast_void(weakvalue = strchr(svalue(mode), 'v')), 532 cast_void(weakvalue = strchr(svalue(mode), 'v')),
533 (weakkey || weakvalue))) { /* is really weak? */ 533 (weakkey || weakvalue))) { /* is really weak? */
534 black2gray(h); /* turn it back to gray, as it probably goes to a list */ 534 set2gray(h); /* turn it back to gray, as it probably goes to a list */
535 if (!weakkey) /* strong keys? */ 535 if (!weakkey) /* strong keys? */
536 traverseweakvalue(g, h); 536 traverseweakvalue(g, h);
537 else if (!weakvalue) /* strong values? */ 537 else if (!weakvalue) /* strong values? */
@@ -614,7 +614,7 @@ static int traversethread (global_State *g, lua_State *th) {
614 StkId o = th->stack; 614 StkId o = th->stack;
615 if (isold(th) || g->gcstate == GCSpropagate) { 615 if (isold(th) || g->gcstate == GCSpropagate) {
616 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ 616 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
617 black2gray(th); 617 set2gray(th);
618 } 618 }
619 if (o == NULL) 619 if (o == NULL)
620 return 1; /* stack not completely built yet */ 620 return 1; /* stack not completely built yet */
@@ -646,7 +646,7 @@ static int traversethread (global_State *g, lua_State *th) {
646*/ 646*/
647static lu_mem propagatemark (global_State *g) { 647static lu_mem propagatemark (global_State *g) {
648 GCObject *o = g->gray; 648 GCObject *o = g->gray;
649 gray2black(o); 649 nw2black(o);
650 g->gray = *getgclist(o); /* remove from 'gray' list */ 650 g->gray = *getgclist(o); /* remove from 'gray' list */
651 switch (o->tt) { 651 switch (o->tt) {
652 case LUA_VTABLE: return traversetable(g, gco2t(o)); 652 case LUA_VTABLE: return traversetable(g, gco2t(o));
@@ -812,7 +812,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
812 freeobj(L, curr); /* erase 'curr' */ 812 freeobj(L, curr); /* erase 'curr' */
813 } 813 }
814 else { /* change mark to 'white' */ 814 else { /* change mark to 'white' */
815 curr->marked = cast_byte((marked & maskgcbits) | white); 815 curr->marked = cast_byte((marked & ~maskgcbits) | white);
816 p = &curr->next; /* go to next element */ 816 p = &curr->next; /* go to next element */
817 } 817 }
818 } 818 }
@@ -1048,12 +1048,12 @@ static void sweep2old (lua_State *L, GCObject **p) {
1048 if (curr->tt == LUA_VTHREAD) { /* threads must be watched */ 1048 if (curr->tt == LUA_VTHREAD) { /* threads must be watched */
1049 lua_State *th = gco2th(curr); 1049 lua_State *th = gco2th(curr);
1050 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ 1050 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
1051 black2gray(th); /* OK if already gray */ 1051 set2gray(th);
1052 } 1052 }
1053 else if (curr->tt == LUA_VUPVAL && upisopen(gco2upv(curr))) 1053 else if (curr->tt == LUA_VUPVAL && upisopen(gco2upv(curr)))
1054 black2gray(curr); /* open upvalues are always gray */ 1054 set2gray(curr); /* open upvalues are always gray */
1055 else /* everything else is black */ 1055 else /* everything else is black */
1056 gray2black(curr); /* OK if already black */ 1056 nw2black(curr);
1057 p = &curr->next; /* go to next element */ 1057 p = &curr->next; /* go to next element */
1058 } 1058 }
1059 } 1059 }
@@ -1092,7 +1092,7 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1092 } 1092 }
1093 else { /* correct mark and age */ 1093 else { /* correct mark and age */
1094 if (getage(curr) == G_NEW) { /* new objects go back to white */ 1094 if (getage(curr) == G_NEW) { /* new objects go back to white */
1095 int marked = curr->marked & maskgcbits; /* erase GC bits */ 1095 int marked = curr->marked & ~maskgcbits; /* erase GC bits */
1096 curr->marked = cast_byte(marked | G_SURVIVAL | white); 1096 curr->marked = cast_byte(marked | G_SURVIVAL | white);
1097 } 1097 }
1098 else { /* all other objects will be old, and so keep their color */ 1098 else { /* all other objects will be old, and so keep their color */
@@ -1115,7 +1115,7 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1115static void whitelist (global_State *g, GCObject *p) { 1115static void whitelist (global_State *g, GCObject *p) {
1116 int white = luaC_white(g); 1116 int white = luaC_white(g);
1117 for (; p != NULL; p = p->next) 1117 for (; p != NULL; p = p->next)
1118 p->marked = cast_byte((p->marked & maskgcbits) | white); 1118 p->marked = cast_byte((p->marked & ~maskgcbits) | white);
1119} 1119}
1120 1120
1121 1121
@@ -1136,7 +1136,7 @@ static GCObject **correctgraylist (GCObject **p) {
1136 goto remove; /* remove all white objects */ 1136 goto remove; /* remove all white objects */
1137 else if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ 1137 else if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */
1138 lua_assert(isgray(curr)); 1138 lua_assert(isgray(curr));
1139 gray2black(curr); /* make it black, for next barrier */ 1139 nw2black(curr); /* make it black, for next barrier */
1140 changeage(curr, G_TOUCHED1, G_TOUCHED2); 1140 changeage(curr, G_TOUCHED1, G_TOUCHED2);
1141 goto remain; /* keep it in the list and go to next element */ 1141 goto remain; /* keep it in the list and go to next element */
1142 } 1142 }
@@ -1148,7 +1148,7 @@ static GCObject **correctgraylist (GCObject **p) {
1148 lua_assert(isold(curr)); /* young objects should be white here */ 1148 lua_assert(isold(curr)); /* young objects should be white here */
1149 if (getage(curr) == G_TOUCHED2) /* advance from TOUCHED2... */ 1149 if (getage(curr) == G_TOUCHED2) /* advance from TOUCHED2... */
1150 changeage(curr, G_TOUCHED2, G_OLD); /* ... to OLD */ 1150 changeage(curr, G_TOUCHED2, G_OLD); /* ... to OLD */
1151 gray2black(curr); /* make object black (to be removed) */ 1151 nw2black(curr); /* make object black (to be removed) */
1152 goto remove; 1152 goto remove;
1153 } 1153 }
1154 remove: *p = *next; continue; 1154 remove: *p = *next; continue;
@@ -1184,7 +1184,7 @@ static void markold (global_State *g, GCObject *from, GCObject *to) {
1184 lua_assert(!iswhite(p)); 1184 lua_assert(!iswhite(p));
1185 changeage(p, G_OLD1, G_OLD); /* now they are old */ 1185 changeage(p, G_OLD1, G_OLD); /* now they are old */
1186 if (isblack(p)) { 1186 if (isblack(p)) {
1187 black2gray(p); /* should be '2white', but gray works too */ 1187 set2gray(p); /* should be '2white', but gray works too */
1188 reallymarkobject(g, p); 1188 reallymarkobject(g, p);
1189 } 1189 }
1190 } 1190 }
diff --git a/lgc.h b/lgc.h
index 0508cd1d..073e2a40 100644
--- a/lgc.h
+++ b/lgc.h
@@ -12,16 +12,16 @@
12#include "lstate.h" 12#include "lstate.h"
13 13
14/* 14/*
15** Collectable objects may have one of three colors: white, which 15** Collectable objects may have one of three colors: white, which means
16** means the object is not marked; gray, which means the 16** the object is not marked; gray, which means the object is marked, but
17** object is marked, but its references may be not marked; and 17** its references may be not marked; and black, which means that the
18** black, which means that the object and all its references are marked. 18** object and all its references are marked. The main invariant of the
19** The main invariant of the garbage collector, while marking objects, 19** garbage collector, while marking objects, is that a black object can
20** is that a black object can never point to a white one. Moreover, 20** never point to a white one. Moreover, any gray object must be in a
21** any gray object must be in a "gray list" (gray, grayagain, weak, 21** "gray list" (gray, grayagain, weak, allweak, ephemeron) so that it
22** allweak, ephemeron) so that it can be visited again before finishing 22** can be visited again before finishing the collection cycle. (Open
23** the collection cycle. These lists have no meaning when the invariant 23** upvalues are an exception to this rule.) These lists have no meaning
24** is not being enforced (e.g., sweep phase). 24** when the invariant is not being enforced (e.g., sweep phase).
25*/ 25*/
26 26
27 27
@@ -96,7 +96,8 @@
96#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) 96#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked)
97 97
98#define changewhite(x) ((x)->marked ^= WHITEBITS) 98#define changewhite(x) ((x)->marked ^= WHITEBITS)
99#define gray2black(x) l_setbit((x)->marked, BLACKBIT) 99#define nw2black(x) \
100 check_exp(!iswhite(x), l_setbit((x)->marked, BLACKBIT))
100 101
101#define luaC_white(g) cast_byte((g)->currentwhite & WHITEBITS) 102#define luaC_white(g) cast_byte((g)->currentwhite & WHITEBITS)
102 103