Previous    Next


In languages (such as C) without nested functions, the run-time representation of a function value can be the address of the machine code for that function. This address can be passed as an argument, stored in a variable, and so on; when it is time to call the function, the address is loaded into a machine register, and the "call to address contained in register" instruction is used. In the Tree intermediate representation, this is easy to express. Suppose the function starts at label L123; we assign the address into a variable t57 using

MOVE(TEMP(t57) NAME(L123))

and then call the function with something like

CALL(TEMP(t57),... parameters ...).

But this will not work for nested functions; if we represent the h function by an address, in what outer frame can it access the variable n? Similarly, how does the g function access the variable f? The solution is to represent a function variable as a closure: a record that contains the machine-code pointer and a way to access the necessary nonlocal variables. This is very much like an object with a single method (the machine-code pointer) and several instance variables. The portion of the closure giving access to values of variables is often called the environment. Closures need not be based on objects; any other data structure that gives access to nonlocal variables will do. However, in this chapter we will use objects for simplicity.


The local variables for add must not be destroyed when add returns, because n is still needed for the execution of h. To solve this problem, we can create a heap-allocated object to hold each function's local variables; then we rely on the garbage collector to reclaim the object when all references (including inner-nested function values) have disappeared. A refinement of this technique is to save on the heap only those variables that escape (that are used by inner-nested functions). The stack frame will hold spilled registers, return address, and so on, and also a pointer to the escaping-variable record. The escaping-variable record holds (1) any local variables that an inner-nested procedure might need and (2) a pointer to the environment (escaping-variable record) provided by the enclosing function. This pointer from one closure to the closure of the statically enclosing function is called the static link; see Image 15.2.

Java Click To expand
Image 15.2: Closures for execution of twice(add(5)). SL=static link; RV=return value; EP=escaping-variables-pointer or environment-pointer.
JaVaScreenshot Previous    Next