Roman Tsisyk
2014-09-16 12:00:00 UTC
Hi!
I found one interesting pattern often used by Lua developers:
local t = { some Lua table with 3 elements }
local v1, v2, v3 = unpack(t)
A trick with unpack() is very nice, but it breaks all JIT traces
because unpack() is not compiled.
For plain Lua tables the example above can be easily rewritten:
local v1, v2, v3 = t[1], t[2], t[3]
Now let's imagine if we have an iterator without random access instead
of a plain Lua table:
local v1, v2, v3 = obj:iterate_and_unpack_all_elements()
where iterate_and_unpack_all_elements() should be logically equivalent to:
local t = {}
for state, v in ipairs(obj) do
table.insert(t, v)
end
return unpack(t)
Is it possible to write JIT-friendly version of such function?
I experimented with unpack() itself:
1. Tail recursion to build multi-return stack - doesn't compile
local function unpack2_r(gen, init, state)
local v
state, v = gen(init, state)
if state == nil then
return
end
return v, unpack2_r(gen, init, state)
end
local function unpack2(t)
return unpack2_r(ipairs(t))
end
2. Specialized versions for particular sizes - do compile, but looks ugly
local function unpack3(t)
if #t == 1 then
return t[1]
else if #t == 2 then
return t[1], t[2]
else if #t == 3 then
return t[1], t[2], t[3]
else
return unpack(t) -- goodbye, JIT
end
end
Any ideas?
Thanks!
I found one interesting pattern often used by Lua developers:
local t = { some Lua table with 3 elements }
local v1, v2, v3 = unpack(t)
A trick with unpack() is very nice, but it breaks all JIT traces
because unpack() is not compiled.
For plain Lua tables the example above can be easily rewritten:
local v1, v2, v3 = t[1], t[2], t[3]
Now let's imagine if we have an iterator without random access instead
of a plain Lua table:
local v1, v2, v3 = obj:iterate_and_unpack_all_elements()
where iterate_and_unpack_all_elements() should be logically equivalent to:
local t = {}
for state, v in ipairs(obj) do
table.insert(t, v)
end
return unpack(t)
Is it possible to write JIT-friendly version of such function?
I experimented with unpack() itself:
1. Tail recursion to build multi-return stack - doesn't compile
local function unpack2_r(gen, init, state)
local v
state, v = gen(init, state)
if state == nil then
return
end
return v, unpack2_r(gen, init, state)
end
local function unpack2(t)
return unpack2_r(ipairs(t))
end
2. Specialized versions for particular sizes - do compile, but looks ugly
local function unpack3(t)
if #t == 1 then
return t[1]
else if #t == 2 then
return t[1], t[2]
else if #t == 3 then
return t[1], t[2], t[3]
else
return unpack(t) -- goodbye, JIT
end
end
Any ideas?
Thanks!
--
WBR,
Roman Tsisyk <roman-***@public.gmane.org>
http://tarantool.org/ - an efficient in-memory data store and a Lua
application server
http://try.tarantool.org/ - try your Lua code **online**
WBR,
Roman Tsisyk <roman-***@public.gmane.org>
http://tarantool.org/ - an efficient in-memory data store and a Lua
application server
http://try.tarantool.org/ - try your Lua code **online**