lua-users home
lua-l archive

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


Benoit Germain <bnt.germain@gmail.com> wrote:
>
> From what I've seen of the implementation (which is little), when a
> function is vararg, the call frame info has an array somewhere that is
> dynamically allocated and populated from values gotten from the VM
> stack when it is called. Then, when '...' is referenced in the
> function body, OP_VARARG copies some or all elements from this array
> into the call frame's stack.

Not quite. All the arguments for the call are on the stack, immediately
below the function's call frame. OP_VARARG copies the extra arguments from
their original location to the top of the stack. The key line is

        int n = cast_int(base - ci->func) - cl->p->numparams - 1;

which calculates the number of extra arguments. "base" is the call frame's
base pointer. "ci->func" is the position in the stack of the closure that
was called. "cl->p->numparams" is the number of named parameters to the
closure. So the stack layout is

  :         : parent function's frame
  +---------+
  | closure | ci->func
  +---------+
  |  arg 1  |
  +---------+
  |  arg 2  |
  +---------+
  :   ...   :
  +---------+
  |  arg z  |
  +---------+
  | local 1 | base
  +---------+
  :         : this function's frame

Hence (base - func) is the number of actual parameters plus one.

Actually that is a bit of a simplification. When calling a function with a
fixed number of arguments, "base" points to the first argument immediately
above ci->func, since the corresponding parameter is the first local
variable.

  :         : parent function's frame
  +---------+
  | closure | ci->func
  +---------+
  |  arg 1  | base
  +---------+
  :         :
  +---------+
  |  arg n  | last named arg
  +---------+
  | local 1 |
  +---------+
  :         :

When calling a vararg function, the named arguments get copied
above the variable arguments, so that the variable arguments can be
ignored for most purposes when dealing with the frame layout. So it
actually looks like this:

  :         : parent function's frame
  +---------+
  | closure | ci->func
  +---------+
  |  arg 1  |
  +---------+
  :   ...   :
  +---------+
  |  arg z  | last vararg
  +---------+
  |  arg 1  | base
  +---------+
  :         :
  +---------+
  |  arg n  | copy of last named arg
  +---------+
  | local 1 |
  +---------+
  :         :

The effect is almost exactly the same as rewriting the code

   function (a,b,c,...)
     -- etc
   end

into the code

   function (...)
     local a,b,c = ...
     -- etc
   end

So the additional cost in calling a vararg function is copying the
named arguments an extra time - there isn't any additional memory
management cost since it all happens on the stack.

I think that it might be nice if tuples in Lua were just sequences of
values on the stack. The problem dealing with variable size tuples is that
Lua relies a lot on static knowledge of the stack layout - which is why
the named arguments get copied when you call a vararg function.

Tony.
-- 
f.anthony.n.finch  <dot@dotat.at>  http://dotat.at/
Rockall, Malin, Hebrides: South 5 to 7, occasionally gale 8 at first in
Rockall and Malin, veering west or northwest 4 or 5, then backing southwest 5
or 6 later. Rough or very rough. Occasional rain. Moderate or good,
occasionally poor.