aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-08-13 14:31:27 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-08-13 14:31:27 -0300
commitf7ce7e5faae69fcab0126d8bfd34b685f1dcb019 (patch)
tree1e2aa3f512d224c58f8cc639f93582d3659bae1a
parent65141832d29824ebfbf26e8af9e6e4b8549518d4 (diff)
downloadlua-f7ce7e5faae69fcab0126d8bfd34b685f1dcb019.tar.gz
lua-f7ce7e5faae69fcab0126d8bfd34b685f1dcb019.tar.bz2
lua-f7ce7e5faae69fcab0126d8bfd34b685f1dcb019.zip
TOUCHED2 objects are not always black
This commit fixes a bug introduced in commit 9cf3299fa. TOUCHED2 objects are always black while the mutator runs, but they can become temporarily gray inside a minor collection (e.g., if the object is a weak table).
-rw-r--r--lgc.c10
-rw-r--r--testes/gengc.lua17
2 files changed, 19 insertions, 8 deletions
diff --git a/lgc.c b/lgc.c
index 7d62fafb..28c31715 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1146,15 +1146,9 @@ static GCObject **correctgraylist (GCObject **p) {
1146 } 1146 }
1147 else { /* everything else is removed */ 1147 else { /* everything else is removed */
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 lua_assert(isblack(curr)); /* TOUCHED2 objects are always black */ 1151 gray2black(curr); /* make object black (to be removed) */
1152 }
1153 else {
1154 /* everything else in a gray list should be gray */
1155 lua_assert(isgray(curr));
1156 gray2black(curr); /* make object black (to be removed) */
1157 }
1158 goto remove; 1152 goto remove;
1159 } 1153 }
1160 remove: *p = *next; continue; 1154 remove: *p = *next; continue;
diff --git a/testes/gengc.lua b/testes/gengc.lua
index 93b5afd7..3d4f67f8 100644
--- a/testes/gengc.lua
+++ b/testes/gengc.lua
@@ -106,6 +106,23 @@ do -- another bug in 5.4.0
106end 106end
107 107
108 108
109do -- bug introduced in commit 9cf3299fa
110 local t = setmetatable({}, {__mode = "kv"}) -- all-weak table
111 collectgarbage() -- full collection
112 assert(not T or T.gcage(t) == "old")
113 t[1] = {10}
114 assert(not T or (T.gcage(t) == "touched1" and T.gccolor(t) == "gray"))
115 collectgarbage("step", 0) -- minor collection
116 assert(not T or (T.gcage(t) == "touched2" and T.gccolor(t) == "black"))
117 collectgarbage("step", 0) -- minor collection
118 assert(not T or T.gcage(t) == "old") -- t should be black, but it was gray
119 t[1] = {10} -- no barrier here, so t was still old
120 collectgarbage("step", 0) -- minor collection
121 -- t, being old, is ignored by the collection, so it is not cleared
122 assert(t[1] == nil) -- fails with the bug
123end
124
125
109if T == nil then 126if T == nil then
110 (Message or print)('\n >>> testC not active: \z 127 (Message or print)('\n >>> testC not active: \z
111 skipping some generational tests <<<\n') 128 skipping some generational tests <<<\n')