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
