aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-07-13 15:43:02 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-07-13 15:43:02 -0300
commit2e297d6ab37c1bb255b6984b91dd92d9080e02c9 (patch)
treed9031b8d7fbd2670efb6f9a7d24a7a08f24de844 /lgc.c
parentfb18346dddcb0400d0396111c56a817a8d4bd8bd (diff)
downloadlua-2e297d6ab37c1bb255b6984b91dd92d9080e02c9.tar.gz
lua-2e297d6ab37c1bb255b6984b91dd92d9080e02c9.tar.bz2
lua-2e297d6ab37c1bb255b6984b91dd92d9080e02c9.zip
Fixed bug in generational collection of userdata
During generational collection, a userdatum must become gray and go to a gray list after being traversed (like tables), so that 'correctgraylist' can handle it to its next stage. This commit also added minimum tests for the generational collector, including one that would detect this bug.
Diffstat (limited to '')
-rw-r--r--lgc.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/lgc.c b/lgc.c
index fb02f015..c11a5280 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id$ 2** $Id: lgc.c $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -212,7 +212,7 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) {
212 lua_assert(g->gckind != KGC_GEN || (isold(o) && getage(o) != G_TOUCHED1)); 212 lua_assert(g->gckind != KGC_GEN || (isold(o) && getage(o) != G_TOUCHED1));
213 if (getage(o) != G_TOUCHED2) /* not already in gray list? */ 213 if (getage(o) != G_TOUCHED2) /* not already in gray list? */
214 linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */ 214 linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */
215 black2gray(o); /* make table gray (again) */ 215 black2gray(o); /* make object gray (again) */
216 setage(o, G_TOUCHED1); /* touched in current cycle */ 216 setage(o, G_TOUCHED1); /* touched in current cycle */
217} 217}
218 218
@@ -515,6 +515,19 @@ static lu_mem traversetable (global_State *g, Table *h) {
515} 515}
516 516
517 517
518static int traverseudata (global_State *g, Udata *u) {
519 int i;
520 markobjectN(g, u->metatable); /* mark its metatable */
521 for (i = 0; i < u->nuvalue; i++)
522 markvalue(g, &u->uv[i].uv);
523 if (g->gckind == KGC_GEN) {
524 linkgclist(u, g->grayagain); /* keep it in some gray list */
525 black2gray(u);
526 }
527 return 1 + u->nuvalue;
528}
529
530
518/* 531/*
519** Check the cache of a prototype, to keep invariants. If the 532** Check the cache of a prototype, to keep invariants. If the
520** cache is white, clear it. (A cache should not prevent the 533** cache is white, clear it. (A cache should not prevent the
@@ -613,15 +626,6 @@ static int traversethread (global_State *g, lua_State *th) {
613} 626}
614 627
615 628
616static int traverseudata (global_State *g, Udata *u) {
617 int i;
618 markobjectN(g, u->metatable); /* mark its metatable */
619 for (i = 0; i < u->nuvalue; i++)
620 markvalue(g, &u->uv[i].uv);
621 return 1 + u->nuvalue;
622}
623
624
625/* 629/*
626** traverse one gray object, turning it to black (except for threads, 630** traverse one gray object, turning it to black (except for threads,
627** which are always gray). 631** which are always gray).