lua

A copy of the Lua development repository
Log | Files | Refs | README

commit f7ce7e5faae69fcab0126d8bfd34b685f1dcb019
parent 65141832d29824ebfbf26e8af9e6e4b8549518d4
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Thu, 13 Aug 2020 14:31:00 -0300

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).

Diffstat:
Mlgc.c | 10++--------
Mtestes/gengc.lua | 17+++++++++++++++++
2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/lgc.c b/lgc.c @@ -1146,15 +1146,9 @@ static GCObject **correctgraylist (GCObject **p) { } else { /* everything else is removed */ lua_assert(isold(curr)); /* young objects should be white here */ - if (getage(curr) == G_TOUCHED2) { /* advance from TOUCHED2... */ + if (getage(curr) == G_TOUCHED2) /* advance from TOUCHED2... */ changeage(curr, G_TOUCHED2, G_OLD); /* ... to OLD */ - lua_assert(isblack(curr)); /* TOUCHED2 objects are always black */ - } - else { - /* everything else in a gray list should be gray */ - lua_assert(isgray(curr)); - gray2black(curr); /* make object black (to be removed) */ - } + gray2black(curr); /* make object black (to be removed) */ goto remove; } remove: *p = *next; continue; diff --git a/testes/gengc.lua b/testes/gengc.lua @@ -106,6 +106,23 @@ do -- another bug in 5.4.0 end +do -- bug introduced in commit 9cf3299fa + local t = setmetatable({}, {__mode = "kv"}) -- all-weak table + collectgarbage() -- full collection + assert(not T or T.gcage(t) == "old") + t[1] = {10} + assert(not T or (T.gcage(t) == "touched1" and T.gccolor(t) == "gray")) + collectgarbage("step", 0) -- minor collection + assert(not T or (T.gcage(t) == "touched2" and T.gccolor(t) == "black")) + collectgarbage("step", 0) -- minor collection + assert(not T or T.gcage(t) == "old") -- t should be black, but it was gray + t[1] = {10} -- no barrier here, so t was still old + collectgarbage("step", 0) -- minor collection + -- t, being old, is ignored by the collection, so it is not cleared + assert(t[1] == nil) -- fails with the bug +end + + if T == nil then (Message or print)('\n >>> testC not active: \z skipping some generational tests <<<\n')