Heya Gavin,

Thanks for the feedback, and sorry for the delay here.

On Thu, 2012-01-19 at 01:19 -0800, Gavin Barraclough wrote:
> rather than moving in the direction of trying to optimize
> JSStaticScope objects we should instead to generalizing activations to
> allow them to nest within the same function scope.

The thing that we need to ensure, whatever we do, is that access to all
visible block-scoped and var-scoped bindings can happen in registers.

For example:

function (x) {
  let y = frob(x);
  {
     let z = qux(y);
     return x + z;
  }
}

In this case, all variable accesses -- the two fetches of x, and the put
and fetch of y and z -- all of them need to happen as register accesses.

For me, it's hard to separate the "activation" concept from a function
call -- where you also store return addresses, you have a register for
the arguments, etc.  Is that really a concept that is worth importing
here?  To me, block scope implies a local extension of the register
file: a binding construct, rather than a control-flow construct.

Of course the aspect of activations that does apply directly would be
that they can have symbol tables, and thus are useful for nested
functions with eval().  You might be right that this is the important
aspect.

** Getting to the ideal compilation

My current patches push on static scope objects, but they do resolve the
bindings at compile-time.  They also allow access to var-bound locals
via registers, not by traversing the scope chain.  There are a couple of
easy optimizations that one could do to improve this: a block scope with
no captured lexicals could be allocated as registers, and doesn't need a
symbol table.  A block scope with one captured lexical and two
uncaptured lexicals doesn't need to store the uncaptured lexicals in its
symbol table if no nested function uses eval().

There are ways that these strategies could apply to lazy tear-off as
well.  The common denominator here is that we need a compile-time
representation of the block-scoped locals, and that we need to make a
decision at compile-time as to their allocation policy (e.g. in a
register, lazily torn off, in a scope object, etc).  The scope
information in the compiled program doesn't need to correspond to the
scopes in the source program: uncaptured identifiers (where we count
nested eval() as a capturing construct) don't need to appear in the
symbol table, for example.

Also note that "is there a nested eval()" or "is this identifier
captured" is a block-local property, so some of the analysis that
happens now on ScopeNode needs to happen for blocks as well.  OTOH a
block doesn't store var declarations, so it does seem sensible to me to
separate those concerns.

>  Hopefully the work you have done so far can provide a foundation for
> such an implementation – hopefully much of the parser and
> byte-compiler changes should be are similar.

I hope so, but we'll see I guess :)

> I think there are probably three key reasons we should be basing a
> solution around activations:

> 1) Activations are faster.

For captured variables, yes, but only assuming that you get register
access to identifiers bound in outer blocks.  Do you?

> 2) Let, const and var may appear in the same block scope, and it would
> not make sense to add two separate objects onto the scope chain, one
> for each of the two types of declarations.

Not sure what you mean here.  Var bindings are hoisted to the function
level; let and const bindings are hoisted to the block level.  You would
get a function activation, and then the block activations, as many as
there are nested blocks -- minus one, it seems, given the current "one
scope, function parameters are var-bound" discussion.

> 3) Many optimizations will be equally applicable to all types of
> variables (e.g. capture analysis), and we should not need this work to
> be duplicated to operate over separate sets of data structures used to
> represent the different variable types.

I'm not sure how this point applies.  Are you referring to the capture
analysis in the parser or something deeper in the JIT?

> I think the right route forwards is to rework these changes to be
> oriented around an activation rather than a static scope object.
> Landing these changes as is doesn't seem like the best move, since
> they will only be introduce unnecessary complexity if our intention is
> to switch to an activation based solution.

I'm fine with doing it like that.  However, I wonder: the current set of
patches don't appear to add much complexity, and they use existing
concepts.  We could get a working implementation quickly with them, and
refactor to use activations over time, helped by unit tests.

But, as you like ;-)

I'm interested in your feedback on what you think the ultimate compiled
form of the examples I had at the start of the mail should be.  Then
once we agree I can make it happen :)  Let me know!

Cheers,

Andy
_______________________________________________
squirrelfish-dev mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/squirrelfish-dev

Reply via email to