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