On Jan 18, 2012, at 11:04 AM, Andy Wingo wrote:
> As you mentioned, we should probably discuss my block scope on a higher
> level than individual bugs.
> 
> I wasn't familiar with JSC internals before developing this patch
> series, so it has been an educational experience ;)  Therefore, if in
> the end we need to take another implementation strategy, I'm fine with
> that.  I just needed to dive in and get something done in order to get
> productive with the code base.

Hi Andy,

Great job getting this implemented, this is a really interesting set of 
patches.  I do think there is a fundamental problem in that the right way to 
implement const (and let) vars is through an activation object (as var and 
const are currently implemented), and that the 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.  
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 think there are probably three key reasons we should be basing a solution 
around activations:

1) Activations are faster.  They are lazily created (in situations where 
variables might potentially be captured, they often are not), and access from 
within the same function is performed directly through virtual registers.  Let 
is intended to be used in much the same way as var (let is the new var!), so 
will likely need similar optimization.  Without evidence to the contrary, 
design choices (e.g. eager vs lazy tear-off) are likely to be equally 
applicable to var as they are to let.
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.
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 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 hope this makes sense, what are your thoughts?

cheers,
G.

> What I have is a series of patches that implement "block scoping" for
> const in strict mode, in the ES6 sense of the phrase.

One quick thing to mention – it is the goal of the ECMA committee to introduce 
let syntax into all modes of the language, and we'll probably want to try to 
unify on a single set of const semantics, so block scoping is a mechanism for 
all modes of the language – not just strict mode!

> There is a similarity between ES6 block scope and the scoping of the
> function name, in named function expressions, and the exception
> identifier, in catch clauses.  It seems to me that whatever ES6 block
> scope implementation that JSC gets should also be available in
> non-strict mode in these two specific cases.

This would certainly be desirable, but is not the single most important factor 
in determining how this should be implemented – for the reasons given above it 
seems likely the most desirable way to implement this would be to share the 
same activation mechanism used by for vars.  That said, any mechanism capable 
of supporting var, let and const would likely also be capable of supporting the 
exception in catch & function expression name, so yes, we should be able to 
unify the implementation of these, too.

> * Refactor identifier resolution in BytecodeGenerator
>  https://bugs.webkit.org/show_bug.cgi?id=76285

>From a glance this looks like a good refactoring to me.
Geoff, you had started looking at this patch, probably you or Oliver knows this 
code best?

> * Interpose CodeNode between ScopeNode and ProgramNode et al
>  https://bugs.webkit.org/show_bug.cgi?id=74509

I'm not sure whether this refactoring will be necessary, if we unify handling 
of let/const with var.  The set of properties that remain on ScopeNode after 
this refactoring are m_varStack, m_functionStack, m_statements, and 
m_capturedVariables.  From memory I believe function declarations are block 
scoped in ES6, so m_functionStack will presumably be required for block scopes 
too, as presumably will m_statements.  If const & let will share the same 
activation object as vars, it makes sense for them to continue to be stored in 
the same list (const variables are currently being stored in m_varStack, we'd 
just need a new flag indicating let variables).  There is no reason for block 
scopes other than the outermost scope to use a different data structure, one 
would just expect to only see vars in the outermost scopes (in fact, I'm not 
sure if we need to distinguish between var & let in the AST, if the parser has 
enforced the name conflict constraints, hoisted vars to the outermost scope, 
and implicitly initialized to undefined then they might be indistinguishable 
from lat variables).  Any variable capture information may also be useful in 
nested scopes as well as at the outermost scope, and we would want to share the 
same capture analysis mechanism for all types of variables, so it seems like 
m_capturedVariables may be necessary too?

> * Avoid double-lookup when setting static-scoped vars in strict mode
>  https://bugs.webkit.org/show_bug.cgi?id=74628
> 
> * Allow JSStaticScope to bind more than one variable
>  https://bugs.webkit.org/show_bug.cgi?id=74633
> 
> * Optimize access to block-scoped local variables
>  https://bugs.webkit.org/show_bug.cgi?id=74708

If we are going to store let/const variables on an activation object, I'm 
afraid these patches may be adding unnecessary complexity.  When we use 
activation objects, access for var & const variables within the same function 
is already optimized.

> I guess I should mention that this patch will allocate all block-scoped
> variables in JSStaticScope objects on the heap.  This is not good.  In
> many cases, we will be able to allocate them in registers in the
> function instead, in the future.  However there is a bright side here,
> and that's that `var' access still goes through registers.  The lazy
> tear-off solution does have the disadvantage that it penalizes `var'
> access within blocks, or access to any block-scoped let/const in an
> outer scope.  (A block doesn't logically capture a variable; only a
> function or eval does.)

Could you go into more detail here – it's not clear to me why a lazy tear-off 
scheme would need penalize access to var access within blocks.  Variable access 
is fast from within the same function, and I see no need to impede access 
through virtual registers for accesses crossing nested block scopes.

> * Remove the `value' argument to op_push_new_scope
>  https://bugs.webkit.org/show_bug.cgi?id=74718
> 
> A refactor, assuming the use of static scope objects..
> 
> * Implement block-scoped const in strict mode --harmony
>  https://bugs.webkit.org/show_bug.cgi?id=74725
> 
> I removed the pieces in this patch that referenced runtime options, and
> indeed I removed the #if ENABLE(ES6) stuff as well; it was hindering the
> discussion, and in the end things should be able to work together, so I
> figured for the time being, it would be OK without the guards.



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

Reply via email to