lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




On 2018-01-21 09:53 AM, Philipp Janda wrote:
Am 09.01.2018 um 00:26 schröbte Paige DePol:
Roberto Ierusalimschy <roberto@inf.puc-rio.br> wrote:

One thing I am curious about, Roberto, is the creation of tables to hold the vargs. Won't this add significant overhead for the table allocations vs just
leaving the vargs on the stack?

That was the motivation for stack varargs. But "significant" is quite
relative. Moreover, stack varargs add an overhead (a quite small one, but
it is not zero) to all functions, even those not varargs. We do not see
vararg functions in critical paths often. Several (most?) vararg functions
have to create tables (or pay the price of 'select') anyway.

More important, table is the bread-and-butter of Lua. If we start to
demonise them, we are left with little else.

-- Roberto

Very good point about tables, Roberto! I would guess that anyone looking
for performance probably wouldn't be using varargs on critical paths anyway.

Or resort to C for avoiding the extra memory allocation (or addressing other performance concerns).

One other thing I wanted to point out (which is related to the array discussion in another thread):

I find it unfortunate that Lua needs two different array implementations in its tiny standard library -- one convenient but limited one (sequences), and a more powerful but inconvenient one (vararg tables). Now it looks like both implementations will even end up in the Lua core. Since we apparently can't agree on a single implementation that will cover all needs, may I propose that the table library also work for vararg tables in addition to sequences? It seems strange that the inconvenient array type doesn't have any support functions in the standard library, and especially inserting or removing elements are things you might want to do to vararg tables.

Philipp


p.s.: If the concept of n fields of vararg tables ends up in the Lua core, the length operator could (raw-)inspect n as well. Maybe in time most Lua code would be able to handle both array types without extra effort. But that is a proposal for another time.



function push(_ARGS, extra)
  return (function(...)
    return _ARGS
  end)(extra, ...)
end

function pop(_ARGS, extra)
  return (function(x, ...)
    return _ARGS, x
  end)(...)
end

Since tables and varargs are now one and the same, and ... unpacks varargs at the bytecode level, this makes extremely fast push and pop functions (as long as you're ok with things like "t = push(t, extra)", which when using recursion is trivial).

If Lua had function folding (i.e. -O3) and a better bytecode, this could be made very efficient. Since Lua bytecode is already not sandbox-safe (there's no validation done on it, and it can and will cause UB (in the C way) if used incorrectly), there's no reason why we can't have a more efficient bytecode (besides the debug library, I guess... or do I?).

On that note, indeed, this shouldn't require bytecode manipulation: https://gist.github.com/corsix/6575486 you just need to be able to convince something to corrupt the for loop variables in just the right way:

$ lua5.2
Lua 5.2.4  Copyright (C) 1994-2015 Lua.org, PUC-Rio
> local x = print local first = true for i=1, 1, 0 do if first then debug.setlocal(1, 3, x) debug.setlocal(1, 4, x) first=false else print(i) break end end
2.1239131134934e-317
> local x = print local first = true for i=1, 1, 0 do if first then debug.setlocal(1, 3, x) debug.setlocal(1, 4, x) first=false else print(i) break end end
2.1239131134934e-317
> local x = print local first = true for i=1, 1, 0 do if first then debug.setlocal(1, 3, x) debug.setlocal(1, 4, x) first=false else print(i) break end end
2.1239131134934e-317
> local x = {} local first = true for i=1, 1, 0 do if first then debug.setlocal(1, 3, x) debug.setlocal(1, 4, x) first=false else print(i) break end end
1.1483223936599e-316
> local x = {} local first = true for i=1, 1, 0 do if first then debug.setlocal(1, 3, x) debug.setlocal(1, 4, x) first=false else print(i) break end end
1.1484615225457e-316
> local x = {} local first = true for i=1, 1, 0 do if first then debug.setlocal(1, 3, x) debug.setlocal(1, 4, x) first=false else print(i) break end end
1.1485982799165e-316
>

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.