Skip to content

UpValues

Dibyendu Majumdar edited this page Aug 10, 2020 · 5 revisions

The following description is obtained from Closures in Lua.

The UpVal structure mediates the connection between a closure and a variable. An upvalue may be two states: open or closed. When the upvalue is created, it is open, and its pointer points to the corresponding variable in the Lua stack. That is, an open upvalue is one that's v is pointing to the stack. When the upvalue is closed, the value is moved from the stack to the UpVal structure itself (value) and the pointer v is corrected to point internally.

At any point a variable can have at most one upvalue pointing to it, and all closures that reference the upvalue access this shared upvalue. Lua keeps a linked list of open upvalues of a stack. This list is ordered by the level of the corresponding variables on the stack. When Lua needs an upvalue for a local variable it traverse this linked list. If it finds an upvalue for the variable it reuses it thus ensuring that closures share the same upvalue.

Because the list is ordered and there is at most one upvalue for each variable the maximum number of elements to be traversed when looking for a variable in this list can be known at compile time. This maximum is the number of variables that escape to inner closures and that are declared between the closure and the external variable. For instance

   function foo()
     local a, b, c, d
     local f1 = function() return d + b end
     local f2 = function() return f() + a end

When Lua instantiates f2 it will traverse exactly three upvalues before realizing that a has no upvalue yet: f1, d, and b in that order.

When a variable goes out of scope, its corresponding upvalue (if there is one) must be closed. The list of open upvalues is also used for this task. When compiling a block that contains variables that escape, a "close" operation must be emitted (in Ravi there is no explicit close op, the JMP instruction takes care of it) to close all upvalues up to this level, at the end of the block.

Implementation

The instructioon op_close is emitted to close up-values in following scenarios:

  • block scope ended
  • there was a goto or break statement

We only emit op_close if the block has variables that escaped. See commit issue #31.

Links

Clone this wiki locally