5

Related question: Scala closures compared to Java innerclasses -> final VS var

I wonder when do Scala makes the variables captured into a closure live on the heap instead of the stack. I'm reading the Scala book of Martin Odersky but for now i didn't find this information. Can someone explain what's behind the hood?

Community
  • 1
  • 1
Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419

2 Answers2

10

An anonymous function (and actually, any function) in scala is actually an object (an instance of Function*). When it is instantiated, the capture of vals is done by copying the vals into internal fields of the function object. In the function body (that is, in the function object's apply method) the access to the captured vals is done by accessing these fields.

The capture of vars is similar, except that the compiler has to add a level of indirection: the var value is accessed through some hidden mutable holder (simply an object with a mutable field pointing to the current value of the var) and this is this holder that is copied into the function object. When writing into the var (either by local code or by the function object), it is the holder's field which is written. This mechanism ensures that the local code and function's code manipulate the same data, and both see each other's modifications.

So the answer is that a captured vals and a captured var both always live on the heap (whether directly as a field of the function object, or as a field of some wrapper object)

Régis Jean-Gilles
  • 32,541
  • 5
  • 83
  • 97
  • I can't see any of these fields if I run `javap -p Test$$anonfun$1.class` (an anonymous function in an object `Test`) - any idea why not? – Luigi Plinge Oct 11 '12 at 07:28
  • Add the -private option to see private fields – Régis Jean-Gilles Oct 11 '12 at 07:44
  • -p and -private are the same. I've posted an example here: http://pastebin.com/AkaR6zjM which shows no private fields. – Luigi Plinge Oct 11 '12 at 07:55
  • My answer was about closing over locally scoped vals and vars, or in other words I concerned myself only of functions defined in another method/function, such as by example when calling foreaach and accessing the local scope in the body). This is certainly this case that @Sebastien Lorber was talking about, given the mention of stack vs heap. In your example, wrap the 3 lines of code inside a "test" method and check again. – Régis Jean-Gilles Oct 11 '12 at 08:36
  • So you mean that capturing vars in Scala is a bit like using a final ValueHolder in a Java innerclass, on which we make mutations? – Sebastien Lorber Oct 11 '12 at 10:35
  • Precisely. With the important difference that in scala this is an internal implementation detail, you don't have to do it by hand and pollute your code. – Régis Jean-Gilles Oct 11 '12 at 11:56
0

I don't know the insides of the compiler, but here is how it can be done. For each local variable, the compiler maintains a flag initialized to false. Whenever the variable is used, the compiler checks whether it is being used inside a class or closure that doesn't contain the variable's declaration; if so the flag is set to true. At the end of the variable's scope, if the flag is still false, the variable can live on the stack. Otherwise it must live on the heap.

Theodore Norvell
  • 15,366
  • 6
  • 31
  • 45