diff options
| author | Roberto I <roberto@inf.puc-rio.br> | 2025-09-24 18:33:08 -0300 |
|---|---|---|
| committer | Roberto I <roberto@inf.puc-rio.br> | 2025-09-24 18:33:08 -0300 |
| commit | 25c54fe60e22d05cdfaa48c64372d354efa59547 (patch) | |
| tree | 3ccaeded5e4363db358f73b7c8fc6b9f414a2f2a /testes | |
| parent | 0cc3c9447cca9abae9738ee77c24d88801c3916c (diff) | |
| download | lua-25c54fe60e22d05cdfaa48c64372d354efa59547.tar.gz lua-25c54fe60e22d05cdfaa48c64372d354efa59547.tar.bz2 lua-25c54fe60e22d05cdfaa48c64372d354efa59547.zip | |
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.
Diffstat (limited to 'testes')
| -rw-r--r-- | testes/locals.lua | 6 | ||||
| -rw-r--r-- | testes/vararg.lua | 47 |
2 files changed, 43 insertions, 10 deletions
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 | |||
| 310 | local function foo (howtoclose, obj, n) | 310 | local function foo (howtoclose, obj, n) |
| 311 | local ca -- copy of 'a' visible inside its close metamethod | 311 | local ca -- copy of 'a' visible inside its close metamethod |
| 312 | do | 312 | do |
| 313 | local a <close> = func2close(function (...) | 313 | local a <close> = func2close(function (... | t) |
| 314 | local t = table.pack(...) | ||
| 315 | assert(select("#", ...) == n) | 314 | assert(select("#", ...) == n) |
| 316 | assert(t.n == n and t[1] == ca and (t.n < 2 or t[2] == obj)) | 315 | assert(t.n == n and t[1] == ca and (t.n < 2 or t[2] == obj)) |
| 317 | ca = 15 -- final value to be returned if howtoclose=="scope" | 316 | ca = 15 -- final value to be returned if howtoclose=="scope" |
| @@ -911,8 +910,7 @@ do | |||
| 911 | 910 | ||
| 912 | local extrares -- result from extra yield (if any) | 911 | local extrares -- result from extra yield (if any) |
| 913 | 912 | ||
| 914 | local function check (body, extra, ...) | 913 | local function check (body, extra, ...|t) |
| 915 | local t = table.pack(...) -- expected returns | ||
| 916 | local co = coroutine.wrap(body) | 914 | local co = coroutine.wrap(body) |
| 917 | if extra then | 915 | if extra then |
| 918 | extrares = co() -- runs until first (extra) yield | 916 | 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 @@ | |||
| 3 | 3 | ||
| 4 | print('testing vararg') | 4 | print('testing vararg') |
| 5 | 5 | ||
| 6 | local function f (a, ...=t) | 6 | local function f (a, ...|t) |
| 7 | local x = {n = select('#', ...), ...} | 7 | local x = {n = select('#', ...), ...} |
| 8 | assert(x.n == t.n) | 8 | assert(x.n == t.n) |
| 9 | for i = 1, x.n do | 9 | for i = 1, x.n do |
| @@ -20,7 +20,7 @@ local function c12 (...) | |||
| 20 | return res, 2 | 20 | return res, 2 |
| 21 | end | 21 | end |
| 22 | 22 | ||
| 23 | local function vararg (...=t) return t end | 23 | local function vararg (... | t) return t end |
| 24 | 24 | ||
| 25 | local call = function (f, args) return f(table.unpack(args, 1, args.n)) end | 25 | local call = function (f, args) return f(table.unpack(args, 1, args.n)) end |
| 26 | 26 | ||
| @@ -153,8 +153,8 @@ end | |||
| 153 | 153 | ||
| 154 | 154 | ||
| 155 | do -- vararg parameter used in nested functions | 155 | do -- vararg parameter used in nested functions |
| 156 | local function foo (... = tab1) | 156 | local function foo (... | tab1) |
| 157 | return function (... = tab2) | 157 | return function (... | tab2) |
| 158 | return {tab1, tab2} | 158 | return {tab1, tab2} |
| 159 | end | 159 | end |
| 160 | end | 160 | end |
| @@ -165,16 +165,51 @@ do -- vararg parameter used in nested functions | |||
| 165 | end | 165 | end |
| 166 | 166 | ||
| 167 | do -- vararg parameter is read-only | 167 | do -- vararg parameter is read-only |
| 168 | local st, msg = load("return function (... = t) t = 10 end") | 168 | local st, msg = load("return function (... | t) t = 10 end") |
| 169 | assert(string.find(msg, "const variable 't'")) | 169 | assert(string.find(msg, "const variable 't'")) |
| 170 | 170 | ||
| 171 | local st, msg = load[[ | 171 | local st, msg = load[[ |
| 172 | local function foo (... = extra) | 172 | local function foo (... | extra) |
| 173 | return function (...) extra = nil end | 173 | return function (...) extra = nil end |
| 174 | end | 174 | end |
| 175 | ]] | 175 | ]] |
| 176 | assert(string.find(msg, "const variable 'extra'")) | 176 | assert(string.find(msg, "const variable 'extra'")) |
| 177 | end | 177 | end |
| 178 | 178 | ||
| 179 | |||
| 180 | do -- _ENV as vararg parameter | ||
| 181 | local st, msg = load[[ | ||
| 182 | local function aux (... | _ENV) | ||
| 183 | global <const> a | ||
| 184 | a = 10 | ||
| 185 | end ]] | ||
| 186 | assert(string.find(msg, "const variable 'a'")) | ||
| 187 | end | ||
| 188 | |||
| 189 | |||
| 190 | do -- access to vararg parameter | ||
| 191 | local function notab (keys, t, ... | v) | ||
| 192 | for _, k in pairs(keys) do | ||
| 193 | assert(t[k] == v[k]) | ||
| 194 | end | ||
| 195 | assert(t.n == v.n) | ||
| 196 | end | ||
| 197 | |||
| 198 | local t = table.pack(10, 20, 30) | ||
| 199 | local keys = {-1, 0, 1, t.n, t.n + 1, 1.0, 1.1, "n", print, "k", "1"} | ||
| 200 | notab(keys, t, 10, 20, 30) -- ensure stack space | ||
| 201 | local m = collectgarbage"count" | ||
| 202 | notab(keys, t, 10, 20, 30) | ||
| 203 | -- 'notab' does not create any table/object | ||
| 204 | assert(m == collectgarbage"count") | ||
| 205 | |||
| 206 | -- writing to the vararg table | ||
| 207 | local function foo (... | t) | ||
| 208 | t[1] = t[1] + 10 | ||
| 209 | return t[1] | ||
| 210 | end | ||
| 211 | assert(foo(10, 30) == 20) | ||
| 212 | end | ||
| 213 | |||
| 179 | print('OK') | 214 | print('OK') |
| 180 | 215 | ||
