diff --git a/_glua-tests/base.lua b/_glua-tests/base.lua index 2bc64a8b..f6ed976b 100644 --- a/_glua-tests/base.lua +++ b/_glua-tests/base.lua @@ -46,3 +46,14 @@ local ok, a, b = xpcall(function() return err .. "!", "b" end) assert(not ok and string.find(a, "error!!") and b == nil) + +-- collectgarbage options, as in Lua 5.1 (#546) +assert(collectgarbage() == 0) +assert(collectgarbage("collect") == 0) +local kb = collectgarbage("count") +assert(type(kb) == "number" and kb > 0) +assert(type(collectgarbage("step")) == "boolean") +assert(collectgarbage("stop") == 0 and collectgarbage("restart") == 0) +assert(collectgarbage("setpause", 150) == 200 and collectgarbage("setpause", 200) == 150) +assert(collectgarbage("setstepmul", 300) == 200 and collectgarbage("setstepmul", 200) == 300) +assert(not pcall(collectgarbage, "nope")) diff --git a/_state.go b/_state.go index 6e9febfb..4e0cb61f 100644 --- a/_state.go +++ b/_state.go @@ -543,6 +543,8 @@ func newGlobal() *Global { Global: newLTable(0, 64), builtinMts: make(map[int]LValue), tempFiles: make([]*os.File, 0, 10), + gcPause: 200, // Lua 5.1 defaults + gcStepMul: 200, } } diff --git a/baselib.go b/baselib.go index aa2c08a9..d62fb5e0 100644 --- a/baselib.go +++ b/baselib.go @@ -64,8 +64,33 @@ func baseAssert(L *LState) int { } func baseCollectGarbage(L *LState) int { - runtime.GC() - return 0 + switch opt := L.OptString(1, "collect"); opt { + case "collect": + runtime.GC() + L.Push(LNumber(0)) + case "count": + // Kbytes in use by the Go heap (the Lua state has no heap of its own). + var ms runtime.MemStats + runtime.ReadMemStats(&ms) + L.Push(LNumber(float64(ms.HeapAlloc) / 1024)) + case "step": + runtime.GC() + L.Push(LTrue) + case "stop", "restart": + // The Go collector cannot be stopped for one state. + L.Push(LNumber(0)) + case "setpause": + prev := L.G.gcPause + L.G.gcPause = L.OptInt(2, 0) + L.Push(LNumber(prev)) + case "setstepmul": + prev := L.G.gcStepMul + L.G.gcStepMul = L.OptInt(2, 0) + L.Push(LNumber(prev)) + default: + L.ArgError(1, "invalid option '"+opt+"'") + } + return 1 } func baseDoFile(L *LState) int { diff --git a/state.go b/state.go index 292f93b4..309d46a3 100644 --- a/state.go +++ b/state.go @@ -643,6 +643,8 @@ func newGlobal() *Global { Global: newLTable(0, 64), builtinMts: make(map[int]LValue), tempFiles: make([]*os.File, 0, 10), + gcPause: 200, // Lua 5.1 defaults + gcStepMul: 200, } } diff --git a/value.go b/value.go index 4156e9d5..5dbc90d7 100644 --- a/value.go +++ b/value.go @@ -174,6 +174,8 @@ type Global struct { builtinMts map[int]LValue tempFiles []*os.File gccount int32 + gcPause int // collectgarbage("setpause"): kept and returned, no effect on the Go collector + gcStepMul int // collectgarbage("setstepmul"): idem } type LState struct {