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.
This commit is contained in:
Roberto I
2025-09-24 18:33:08 -03:00
parent 0cc3c9447c
commit 25c54fe60e
13 changed files with 186 additions and 63 deletions

View File

@@ -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 <const> 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')