---
source: src/main.rs
expression: compiled
input_file: test-data/lua5.4-tests/gengc.lua
---
print('testing generational garbage collection');
local debug = require("debug")
assert(collectgarbage("isrunning"));
collectgarbage();
local oldmode = collectgarbage("generational")
{
local U = {}
collectgarbage();
assert(!T || T.gcage(U) == "old");
U[(1)] = {
x = {
234
}
}
assert(!T || (T.gcage(U) == "touched1" && T.gcage(U[(1)]) == "new"));
collectgarbage("step", 0);
assert(!T || (T.gcage(U) == "touched2" && T.gcage(U[(1)]) == "survival"));
collectgarbage("step", 0);
assert(!T || (T.gcage(U) == "old" && T.gcage(U[(1)]) == "old1"));
assert(U[(1)].x[(1)] == 234);
}
{
local fn foo() {
}
local old = {
10
}
collectgarbage();
assert(!T || T.gcage(old) == "old");
setmetatable(old, {});
assert(!T || T.gcage(getmetatable(old)) == "old0");
collectgarbage("step", 0);
assert(!T || T.gcage(getmetatable(old)) == "old1");
setmetatable(getmetatable(old), {
__gc = foo
});
collectgarbage("step", 0);
}
{
local A = {}
A[(1)] = false
local fn gcf(obj) {
A[(1)] = obj
assert(!T || T.gcage(obj) == "old1");
obj = nil
collectgarbage("step", 0);
print(getmetatable(A[(1)]).x);
}
collectgarbage();
local obj = {}
collectgarbage("step", 0);
assert(!T || T.gcage(obj) == "survival");
setmetatable(obj, {
__gc = gcf,
x = "+"
});
assert(!T || T.gcage(getmetatable(obj)) == "new");
obj = nil
collectgarbage("step", 0);
}
{
local old = {
10
}
collectgarbage();
local co = coroutine.create(fn () {
local x = nil
local f = fn () {
return x[(1)]
}
x = coroutine.yield(f)
coroutine.yield();
})
local _, f = coroutine.resume(co)
collectgarbage("step", 0);
old[(1)] = {
"hello"
}
coroutine.resume(co, {
123
});
co = nil
collectgarbage("step", 0);
assert(f() == 123 && old[(1)][(1)] == "hello");
collectgarbage("step", 0);
assert(f() == 123 && old[(1)][(1)] == "hello");
}
{
local t = setmetatable({}, {
__mode = "kv"
})
collectgarbage();
assert(!T || T.gcage(t) == "old");
t[(1)] = {
10
}
assert(!T || (T.gcage(t) == "touched1" && T.gccolor(t) == "gray"));
collectgarbage("step", 0);
assert(!T || (T.gcage(t) == "touched2" && T.gccolor(t) == "black"));
collectgarbage("step", 0);
assert(!T || T.gcage(t) == "old");
t[(1)] = {
10
}
collectgarbage("step", 0);
assert(t[(1)] == nil);
}
if T == nil {
(Message || print)('\n >>> testC not active: \z
skipping some generational tests <<<\n');
print('OK');
return
}
{
local U = T.newuserdata(0, 1)
collectgarbage();
assert(T.gcage(U) == "old");
debug.setuservalue(U, {
x = {
234
}
});
assert(T.gcage(U) == "touched1" && T.gcage(debug.getuservalue(U)) == "new");
collectgarbage("step", 0);
assert(T.gcage(U) == "touched2" && T.gcage(debug.getuservalue(U)) == "survival");
collectgarbage("step", 0);
assert(T.gcage(U) == "old" && T.gcage(debug.getuservalue(U)) == "old1");
assert(debug.getuservalue(U).x[(1)] == 234);
}
assert(collectgarbage('isrunning'));
assert(collectgarbage('isrunning'));
collectgarbage(oldmode);
print('OK');