On Mon, 2011-06-13 at 16:22 -0700, Brendan Miller wrote:
> In V8 if I have a closure such as in this example where I have a
> function f that returns an anonymous closure:
> 
> function f() {
>     var x = 0;
>     var y = 1;
>     return function() {
>         return x + y;
>     };
> }
> 
> In V8 does the returned closure keep two pointers (one to x, and one
> to y), or does it keep a single pointer back to the execution context
> of f? Or does it do something else altogether?

V8 stores all variables referenced from nested functions (x and y in
your case) on the heap.  That way an update to a closed-over variable
from one nested scope will be visible in another.  (Note that this is
only strictly necessary for variables which are ever mutated; variables
which are never set may simply be copied.)  So closing over a variable
does currently have a small cost, in that it must be accessed through a
double indirection: once to get the pointer to the context object, and
another to dereference the variable.

See scope.h and scope.cc for a fairly well-commented analysis code.  At
runtime the values are stored in an array in a "context" object; see
contexts.{h,cc}.

Note that Crankshaft can at times access the value of variables stored
in heap slots directly (in registers, for example). 

> Partially, I'm just curious, and partially I'm wondering about
> performance implications. If f defined way more variables, is each
> closure going to chew up more memory to keep track of all of those
> pointers?

The cost is only paid for variables referenced by nested functions.  The
cost also appears to be only once per scope, and not per-function; an
odd decision, and one that really falls more on the side of "objects are
closures" than "closures are objects" ;-)

http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html

> Also, from a GC perspective, I'm wondering in the case that something
> like this happens:
> function g() {
>     var x = 0
>     var y = 1;
>     return function() {
>         return x;
>     };
> }
> 
> // lets day h is a global that sticks arround forever.
> var h = g();
> 
> Will y never be garbage collected since its part of an execution
> context pointed to by the closure held in h?

Y was never allocated on the heap in this case.

Happy hacking,

Andy

-- 
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users

Reply via email to