aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc.c26
-rwxr-xr-xtestes/all.lua4
-rw-r--r--testes/gc.lua4
-rw-r--r--testes/gengc.lua83
4 files changed, 102 insertions, 15 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).
diff --git a/testes/all.lua b/testes/all.lua
index cfe21603..37796254 100755
--- a/testes/all.lua
+++ b/testes/all.lua
@@ -1,5 +1,5 @@
1#!../lua 1#!../lua
2-- $Id: all.lua,v 1.100 2018/03/09 14:23:48 roberto Exp $ 2-- $Id: all.lua $
3-- See Copyright Notice at the end of this file 3-- See Copyright Notice at the end of this file
4 4
5 5
@@ -162,7 +162,7 @@ olddofile('strings.lua')
162olddofile('literals.lua') 162olddofile('literals.lua')
163dofile('tpack.lua') 163dofile('tpack.lua')
164assert(dofile('attrib.lua') == 27) 164assert(dofile('attrib.lua') == 27)
165 165dofile('gengc.lua')
166assert(dofile('locals.lua') == 5) 166assert(dofile('locals.lua') == 5)
167dofile('constructs.lua') 167dofile('constructs.lua')
168dofile('code.lua', true) 168dofile('code.lua', true)
diff --git a/testes/gc.lua b/testes/gc.lua
index 9647cd54..05072efd 100644
--- a/testes/gc.lua
+++ b/testes/gc.lua
@@ -1,7 +1,7 @@
1-- $Id: gc.lua,v 1.82 2018/03/12 14:19:36 roberto Exp $ 1-- $Id: gc.lua $
2-- See Copyright Notice in file all.lua 2-- See Copyright Notice in file all.lua
3 3
4print('testing garbage collection') 4print('testing incremental garbage collection')
5 5
6local debug = require"debug" 6local debug = require"debug"
7 7
diff --git a/testes/gengc.lua b/testes/gengc.lua
new file mode 100644
index 00000000..36aed806
--- /dev/null
+++ b/testes/gengc.lua
@@ -0,0 +1,83 @@
1-- $Id: gengc.lua $
2-- See Copyright Notice in file all.lua
3
4print('testing generational garbage collection')
5
6local debug = require"debug"
7
8assert(collectgarbage("isrunning"))
9
10collectgarbage()
11
12local oldmode = collectgarbage("generational")
13
14
15-- ensure that table barrier evolves correctly
16do
17 local U = {}
18 -- full collection makes 'U' old
19 collectgarbage()
20 assert(not T or T.gcage(U) == "old")
21
22 -- U refers to a new table, so it becomes 'touched1'
23 U[1] = {x = {234}}
24 assert(not T or (T.gcage(U) == "touched1" and T.gcage(U[1]) == "new"))
25
26 -- both U and the table survive one more collection
27 collectgarbage("step", 0)
28 assert(not T or (T.gcage(U) == "touched2" and T.gcage(U[1]) == "survival"))
29
30 -- both U and the table survive yet another collection
31 -- now everything is old
32 collectgarbage("step", 0)
33 assert(not T or (T.gcage(U) == "old" and T.gcage(U[1]) == "old1"))
34
35 -- data was not corrupted
36 assert(U[1].x[1] == 234)
37end
38
39
40if T == nil then
41 (Message or print)('\n >>> testC not active: \z
42 skipping some generational tests <<<\n')
43 print 'OK'
44 return
45end
46
47
48-- ensure that userdata barrier evolves correctly
49do
50 local U = T.newuserdata(0, 1)
51 -- full collection makes 'U' old
52 collectgarbage()
53 assert(T.gcage(U) == "old")
54
55 -- U refers to a new table, so it becomes 'touched1'
56 debug.setuservalue(U, {x = {234}})
57 assert(T.gcage(U) == "touched1" and
58 T.gcage(debug.getuservalue(U)) == "new")
59
60 -- both U and the table survive one more collection
61 collectgarbage("step", 0)
62 assert(T.gcage(U) == "touched2" and
63 T.gcage(debug.getuservalue(U)) == "survival")
64
65 -- both U and the table survive yet another collection
66 -- now everything is old
67 collectgarbage("step", 0)
68 assert(T.gcage(U) == "old" and
69 T.gcage(debug.getuservalue(U)) == "old1")
70
71 -- data was not corrupted
72 assert(debug.getuservalue(U).x[1] == 234)
73end
74
75
76
77-- just to make sure
78assert(collectgarbage'isrunning')
79
80collectgarbage(oldmode)
81
82print('OK')
83