diff options
-rw-r--r-- | lgc.c | 26 | ||||
-rwxr-xr-x | testes/all.lua | 4 | ||||
-rw-r--r-- | testes/gc.lua | 4 | ||||
-rw-r--r-- | testes/gengc.lua | 83 |
4 files changed, 102 insertions, 15 deletions
@@ -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 | ||
518 | static 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 | ||
616 | static 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') | |||
162 | olddofile('literals.lua') | 162 | olddofile('literals.lua') |
163 | dofile('tpack.lua') | 163 | dofile('tpack.lua') |
164 | assert(dofile('attrib.lua') == 27) | 164 | assert(dofile('attrib.lua') == 27) |
165 | 165 | dofile('gengc.lua') | |
166 | assert(dofile('locals.lua') == 5) | 166 | assert(dofile('locals.lua') == 5) |
167 | dofile('constructs.lua') | 167 | dofile('constructs.lua') |
168 | dofile('code.lua', true) | 168 | dofile('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 | ||
4 | print('testing garbage collection') | 4 | print('testing incremental garbage collection') |
5 | 5 | ||
6 | local debug = require"debug" | 6 | local 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 | |||
4 | print('testing generational garbage collection') | ||
5 | |||
6 | local debug = require"debug" | ||
7 | |||
8 | assert(collectgarbage("isrunning")) | ||
9 | |||
10 | collectgarbage() | ||
11 | |||
12 | local oldmode = collectgarbage("generational") | ||
13 | |||
14 | |||
15 | -- ensure that table barrier evolves correctly | ||
16 | do | ||
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) | ||
37 | end | ||
38 | |||
39 | |||
40 | if T == nil then | ||
41 | (Message or print)('\n >>> testC not active: \z | ||
42 | skipping some generational tests <<<\n') | ||
43 | print 'OK' | ||
44 | return | ||
45 | end | ||
46 | |||
47 | |||
48 | -- ensure that userdata barrier evolves correctly | ||
49 | do | ||
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) | ||
73 | end | ||
74 | |||
75 | |||
76 | |||
77 | -- just to make sure | ||
78 | assert(collectgarbage'isrunning') | ||
79 | |||
80 | collectgarbage(oldmode) | ||
81 | |||
82 | print('OK') | ||
83 | |||