From 25c54fe60e22d05cdfaa48c64372d354efa59547 Mon Sep 17 00:00:00 2001 From: Roberto I Date: Wed, 24 Sep 2025 18:33:08 -0300 Subject: Optimization for vararg tables A vararg table can be virtual. If the vararg table is used only as a base in indexing expressions, the code does not need to create an actual table for it. Instead, it compiles the indexing expressions into direct accesses to the internal vararg data. --- testes/locals.lua | 6 ++---- testes/vararg.lua | 47 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 10 deletions(-) (limited to 'testes') diff --git a/testes/locals.lua b/testes/locals.lua index 02f41980..5222802f 100644 --- a/testes/locals.lua +++ b/testes/locals.lua @@ -310,8 +310,7 @@ do -- testing presence of second argument local function foo (howtoclose, obj, n) local ca -- copy of 'a' visible inside its close metamethod do - local a = func2close(function (...) - local t = table.pack(...) + local a = func2close(function (... | t) assert(select("#", ...) == n) assert(t.n == n and t[1] == ca and (t.n < 2 or t[2] == obj)) ca = 15 -- final value to be returned if howtoclose=="scope" @@ -911,8 +910,7 @@ do local extrares -- result from extra yield (if any) - local function check (body, extra, ...) - local t = table.pack(...) -- expected returns + local function check (body, extra, ...|t) local co = coroutine.wrap(body) if extra then extrares = co() -- runs until first (extra) yield diff --git a/testes/vararg.lua b/testes/vararg.lua index 92f720cb..5711f78b 100644 --- a/testes/vararg.lua +++ b/testes/vararg.lua @@ -3,7 +3,7 @@ print('testing vararg') -local function f (a, ...=t) +local function f (a, ...|t) local x = {n = select('#', ...), ...} assert(x.n == t.n) for i = 1, x.n do @@ -20,7 +20,7 @@ local function c12 (...) return res, 2 end -local function vararg (...=t) return t end +local function vararg (... | t) return t end local call = function (f, args) return f(table.unpack(args, 1, args.n)) end @@ -153,8 +153,8 @@ end do -- vararg parameter used in nested functions - local function foo (... = tab1) - return function (... = tab2) + local function foo (... | tab1) + return function (... | tab2) return {tab1, tab2} end end @@ -165,16 +165,51 @@ do -- vararg parameter used in nested functions end do -- vararg parameter is read-only - local st, msg = load("return function (... = t) t = 10 end") + local st, msg = load("return function (... | t) t = 10 end") assert(string.find(msg, "const variable 't'")) local st, msg = load[[ - local function foo (... = extra) + local function foo (... | extra) return function (...) extra = nil end end ]] assert(string.find(msg, "const variable 'extra'")) end + +do -- _ENV as vararg parameter + local st, msg = load[[ + local function aux (... | _ENV) + global a + a = 10 + end ]] + assert(string.find(msg, "const variable 'a'")) +end + + +do -- access to vararg parameter + local function notab (keys, t, ... | v) + for _, k in pairs(keys) do + assert(t[k] == v[k]) + end + assert(t.n == v.n) + end + + local t = table.pack(10, 20, 30) + local keys = {-1, 0, 1, t.n, t.n + 1, 1.0, 1.1, "n", print, "k", "1"} + notab(keys, t, 10, 20, 30) -- ensure stack space + local m = collectgarbage"count" + notab(keys, t, 10, 20, 30) + -- 'notab' does not create any table/object + assert(m == collectgarbage"count") + + -- writing to the vararg table + local function foo (... | t) + t[1] = t[1] + 10 + return t[1] + end + assert(foo(10, 30) == 20) +end + print('OK') -- cgit v1.2.3-55-g6feb