---
source: src/main.rs
expression: compiled
input_file: test-data/lua5.1-tests/gc.lua
---
print('testing garbage collection');
collectgarbage();
_G[("while")] = 234
limit = 5000
contCreate = 0
print('tables');
while contCreate <= limit {
local a = {}
a = nil
contCreate = contCreate + 1
}
a = "a"
contCreate = 0
print('strings');
while contCreate <= limit {
a = contCreate .. "b"
a = string.gsub(a, '(%d%d*)', string.upper)
a = "a"
contCreate = contCreate + 1
}
contCreate = 0
a = {}
print('functions');
method a::test() {
while contCreate <= limit {
loadstring(string.format("function temp(a) return 'a%d' end", contCreate))();
assert(temp() == string.format('a%d', contCreate));
contCreate = contCreate + 1
}
}
a::test();
{
local f = fn () {
}
}
print("functions with errors");
prog = `
do
a = 10;
function foo(x,y)
a = sin(a+0.456-0.23e-12);
return function (z) return sin(%x+z) end
end
local x = function (w) a=a+w; end
end
`
{
local step = 1
if rawget(_G, "_soft") {
step = 13
}
for i = 1, string.len(prog), step {
for j = i, string.len(prog), step {
pcall(loadstring(string.sub(prog, i, j)));
}
}
}
print('long strings');
x = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
assert(string.len(x) == 80);
s = ''
n = 0
k = 300
while n < k {
s = s .. x
n = n + 1
j = tostring(n)
}
assert(string.len(s) == k * 80);
s = string.sub(s, 1, 20000)
s, i = string.gsub(s, '(%d%d%d%d)', math.sin)
assert(i == 20000 / 4);
s = nil
x = nil
assert(_G[("while")] == 234);
local bytes = gcinfo()
while 1 {
local nbytes = gcinfo()
if nbytes < bytes {
break
}
bytes = nbytes
a = {}
}
local fn dosteps(siz) {
collectgarbage();
collectgarbage("stop");
local a = {}
for i = 1, 100 {
a[(i)] = {
{}
}
local b = {}
}
local x = gcinfo()
local i = 0
loop {
i = i + 1
} until collectgarbage("step", siz)
assert(gcinfo() < x);
return i
}
assert(dosteps(0) > 10);
assert(dosteps(6) < dosteps(2));
assert(dosteps(10000) == 1);
assert(collectgarbage("step", 1000000) == true);
assert(collectgarbage("step", 1000000));
{
local x = gcinfo()
collectgarbage();
collectgarbage("stop");
loop {
local a = {}
} until gcinfo() > 1000
collectgarbage("restart");
loop {
local a = {}
} until gcinfo() < 1000
}
lim = 15
a = {}
for i = 1, lim {
a[({})] = i
}
b = {}
for k, v with pairs(a) {
b[(k)] = v
}
for n with pairs(b) {
a[(n)] = nil
assert(type(n) == 'table' && next(n) == nil);
collectgarbage();
}
b = nil
collectgarbage();
for n with pairs(a) {
error('cannot be here');
}
for i = 1, lim {
a[(i)] = i
}
for i = 1, lim {
assert(a[(i)] == i);
}
print('weak tables');
a = {}
setmetatable(a, {
__mode = 'k'
});
for i = 1, lim {
a[({})] = i
}
for i = 1, lim {
local t = {}
a[(t)] = t
}
for i = 1, lim {
a[(i)] = i
}
for i = 1, lim {
local s = string.rep('@', i)
a[(s)] = s .. '#'
}
collectgarbage();
local i = 0
for k, v with pairs(a) {
assert(k == v || k .. '#' == v);
i = i + 1
}
assert(i == 3 * lim);
a = {}
setmetatable(a, {
__mode = 'v'
});
a[(1)] = string.rep('b', 21)
collectgarbage();
assert(a[(1)]);
a[(1)] = nil
for i = 1, lim {
a[(i)] = {}
}
for i = 1, lim {
a[(i .. 'x')] = {}
}
for i = 1, lim {
local t = {}
a[(t)] = t
}
for i = 1, lim {
a[(i + lim)] = i .. 'x'
}
collectgarbage();
local i = 0
for k, v with pairs(a) {
assert(k == v || k - lim .. 'x' == v);
i = i + 1
}
assert(i == 2 * lim);
a = {}
setmetatable(a, {
__mode = 'vk'
});
local x, y, z = {}, {}, {}
a[(1)], a[(2)], a[(3)] = x, y, z
a[(string.rep('$', 11))] = string.rep('$', 11)
for i = 4, lim {
a[(i)] = {}
}
for i = 1, lim {
a[({})] = i
}
for i = 1, lim {
local t = {}
a[(t)] = t
}
collectgarbage();
assert(next(a) != nil);
local i = 0
for k, v with pairs(a) {
assert((k == 1 && v == x) || (k == 2 && v == y) || (k == 3 && v == z) || k == v);
i = i + 1
}
assert(i == 4);
x, y, z = nil
collectgarbage();
assert(next(a) == string.rep('$', 11));
collectgarbage("stop");
local u = newproxy(true)
local s = 0
local a = {
u = 0
}
setmetatable(a, {
__mode = 'vk'
});
for i = 1, 10 {
a[(newproxy(u))] = i
}
for k with pairs(a) {
assert(getmetatable(k) == getmetatable(u));
}
local a1 = {}
for k, v with pairs(a) {
a1[(k)] = v
}
for k, v with pairs(a1) {
a[(v)] = k
}
for i = 1, 10 {
assert(a[(i)]);
}
getmetatable(u).a = a1
getmetatable(u).u = u
{
local u = u
getmetatable(u).__gc = fn (o) {
assert(a[(o)] == 10 - s);
assert(a[(10 - s)] == nil);
assert(getmetatable(o) == getmetatable(u));
assert(getmetatable(o).a[(o)] == 10 - s);
s = s + 1
}
}
a1, u = nil
assert(next(a) != nil);
collectgarbage();
assert(s == 11);
collectgarbage();
assert(next(a) == nil);
local u = newproxy(true)
setmetatable(getmetatable(u), {
__mode = "v"
});
getmetatable(u).__gc = fn (o) {
os.exit(1);
}
collectgarbage();
local u = newproxy(true)
local m = getmetatable(u)
m.x = {
{
0
} = 1,
0 = {
1
}
}
setmetatable(m.x, {
__mode = "kv"
});
m.__gc = fn (o) {
assert(next(getmetatable(o).x) == nil);
m = 10
}
u, m = nil
collectgarbage();
assert(m == 10);
u = newproxy(true)
getmetatable(u).__gc = fn () {
error("!!!");
}
u = nil
assert(!pcall(collectgarbage));
if !rawget(_G, "_soft") {
print("deep structures");
local a = {}
for i = 1, 200000 {
a = {
next = a
}
}
collectgarbage();
}
local thread_id = 0
local threads = {}
global fn fn(thread) {
local x = {}
threads[(thread_id)] = fn () {
thread = x
}
coroutine.yield();
}
while thread_id < 1000 {
local thread = coroutine.create(fn)
coroutine.resume(thread, thread);
thread_id = thread_id + 1
}
{
local newproxy, assert, type, print, getmetatable = newproxy, assert, type, print, getmetatable
local u = newproxy(true)
local tt = getmetatable(u)
___Glob = {
u
}
tt.__gc = fn (o) {
assert(getmetatable(o) == tt);
local a = 'xuxu' .. (10 + 3) .. 'joao', {}
___Glob = o
newproxy(o);
print(">>> closing state " .. "<<<\n");
}
}
{
local u = newproxy(true)
getmetatable(u).__gc = fn (o) {
return o + 1
}
table.insert(___Glob, u);
for i = 1, 10 {
table.insert(___Glob, newproxy(u));
}
}
print('OK');