| Index: pkg/compiler/lib/src/js_model/closure_visitors.dart
|
| diff --git a/pkg/compiler/lib/src/js_model/closure_visitors.dart b/pkg/compiler/lib/src/js_model/closure_visitors.dart
|
| index a089defc3827a327e0927a4b884b3a6f1f22cc4b..5f74b50957d729af556844586cd6cf04715acc5c 100644
|
| --- a/pkg/compiler/lib/src/js_model/closure_visitors.dart
|
| +++ b/pkg/compiler/lib/src/js_model/closure_visitors.dart
|
| @@ -13,6 +13,9 @@ import 'closure.dart';
|
| /// various points to build CapturedScope that can respond to queries
|
| /// about how a particular variable is being used at any point in the code.
|
| class CapturedScopeBuilder extends ir.Visitor {
|
| + final MemberEntity _currentMember;
|
| + Local _currentLocalFunction;
|
| +
|
| /// A map of each visited call node with the associated information about what
|
| /// variables are captured/used. Each ir.Node key corresponds to a scope that
|
| /// was encountered while visiting a closure (initially called through
|
| @@ -63,19 +66,22 @@ class CapturedScopeBuilder extends ir.Visitor {
|
| /// The current scope we are in.
|
| KernelScopeInfo _currentScopeInfo;
|
|
|
| + // TODO(johnniwinther): Remove the need for this.
|
| final KernelToElementMap _kernelToElementMap;
|
|
|
| - /// The original entity from which we start the tree-walk to find closure and
|
| - /// scope information.
|
| - final Entity _originalEntity;
|
| + final Entity _thisLocal;
|
|
|
| CapturedScopeBuilder(
|
| + this._currentMember,
|
| this._scopesCapturedInClosureMap,
|
| this._scopeInfoMap,
|
| - this._originalEntity,
|
| this._closuresToGenerate,
|
| this._localsMap,
|
| - this._kernelToElementMap);
|
| + this._kernelToElementMap)
|
| + : this._thisLocal =
|
| + _currentMember.isInstanceMember || _currentMember.isConstructor
|
| + ? new ThisLocal(_currentMember)
|
| + : null;
|
|
|
| /// Update the [CapturedScope] object corresponding to
|
| /// this node if any variables are captured.
|
| @@ -91,40 +97,22 @@ class CapturedScopeBuilder extends ir.Visitor {
|
| }
|
| }
|
| if (!capturedVariablesForScope.isEmpty) {
|
| - ThisLocal thisLocal = null;
|
| - if (node is ir.Member && node.isInstanceMember) {
|
| - if (node is ir.Procedure) {
|
| - thisLocal = new ThisLocal(_kernelToElementMap.getMethod(node));
|
| - } else if (node is ir.Field) {
|
| - thisLocal = new ThisLocal(_kernelToElementMap.getField(node));
|
| - }
|
| - } else if (node is ir.Constructor) {
|
| - thisLocal = new ThisLocal(_kernelToElementMap.getConstructor(node));
|
| - }
|
| -
|
| - assert(_scopeInfoMap[_nodeToEntity(node)] != null);
|
| - KernelScopeInfo from = _scopeInfoMap[_nodeToEntity(node)];
|
| + assert(_scopeInfoMap[_currentMember] != null);
|
| + assert(_currentLocalFunction != null);
|
| + KernelScopeInfo from = _scopeInfoMap[_currentMember];
|
| _scopesCapturedInClosureMap[node] = new KernelCapturedScope(
|
| capturedVariablesForScope,
|
| - _nodeToEntity(_executableContext),
|
| + _currentLocalFunction,
|
| from.localsUsedInTryOrSync,
|
| from.freeVariables,
|
| from.localsMap,
|
| - thisLocal);
|
| - }
|
| - }
|
| -
|
| - Entity _nodeToEntity(ir.Node node) {
|
| - if (node is ir.Member) {
|
| - return _kernelToElementMap.getMember(node);
|
| - } else {
|
| - return _kernelToElementMap.getLocalFunction(node);
|
| + _thisLocal);
|
| }
|
| }
|
|
|
| /// Perform book-keeping with the current set of local variables that have
|
| /// been seen thus far before entering this new scope.
|
| - void enterNewScope(ir.Node node, Function visitNewScope) {
|
| + void enterNewScope(ir.Node node, void visitNewScope()) {
|
| List<ir.VariableDeclaration> oldScopeVariables = _scopeVariables;
|
| _scopeVariables = <ir.VariableDeclaration>[];
|
| visitNewScope();
|
| @@ -235,17 +223,20 @@ class CapturedScopeBuilder extends ir.Visitor {
|
| bool oldIsInsideClosure = _isInsideClosure;
|
| ir.Node oldExecutableContext = _executableContext;
|
| KernelScopeInfo oldScopeInfo = _currentScopeInfo;
|
| + Local oldLocalFunction = _currentLocalFunction;
|
|
|
| // _outermostNode is only null the first time we enter the body of the
|
| // field, constructor, or method that is being analyzed.
|
| _isInsideClosure = _outermostNode != null;
|
| _executableContext = node;
|
| - _currentScopeInfo = new KernelScopeInfo(_nodeToThisLocal(node), _localsMap);
|
| +
|
| + _currentScopeInfo = new KernelScopeInfo(_thisLocal, _localsMap);
|
| if (_isInsideClosure) {
|
| _closuresToGenerate[node] = _currentScopeInfo;
|
| + _currentLocalFunction = _kernelToElementMap.getLocalFunction(node.parent);
|
| } else {
|
| _outermostNode = node;
|
| - _scopeInfoMap[_originalEntity] = _currentScopeInfo;
|
| + _scopeInfoMap[_currentMember] = _currentScopeInfo;
|
| }
|
|
|
| enterNewScope(node, () {
|
| @@ -259,6 +250,7 @@ class CapturedScopeBuilder extends ir.Visitor {
|
| _isInsideClosure = oldIsInsideClosure;
|
| _currentScopeInfo = oldScopeInfo;
|
| _executableContext = oldExecutableContext;
|
| + _currentLocalFunction = oldLocalFunction;
|
|
|
| // Mark all free variables as captured and expect to encounter them in the
|
| // outer function.
|
| @@ -293,32 +285,4 @@ class CapturedScopeBuilder extends ir.Visitor {
|
| void visitFunctionNode(ir.FunctionNode functionNode) {
|
| visitInvokable(functionNode);
|
| }
|
| -
|
| - /// If [node] is an instance member return the corresponding `this` reference.
|
| - /// If not, return null.
|
| - Entity _nodeToThisLocal(
|
| - ir.TreeNode
|
| - /*ir.Field|ir.FunctionNode|ir.Constructor|ir.Procedure*/ node) {
|
| - ir.Node nodeToConvert = node;
|
| - if (nodeToConvert is ir.Field) {
|
| - if (!nodeToConvert.isInstanceMember) return null;
|
| - return new ThisLocal(_kernelToElementMap.getField(nodeToConvert));
|
| - } else {
|
| - if (nodeToConvert is ir.FunctionNode) {
|
| - // Step up one node higher to find the corresponding entity for this
|
| - // node.
|
| - nodeToConvert = node.parent;
|
| - }
|
| - if (nodeToConvert is ir.Constructor ||
|
| - (nodeToConvert is ir.Procedure &&
|
| - nodeToConvert.kind == ir.ProcedureKind.Factory &&
|
| - nodeToConvert.isInstanceMember)) {
|
| - return new ThisLocal(_kernelToElementMap.getConstructor(nodeToConvert));
|
| - } else if (nodeToConvert is ir.Procedure &&
|
| - nodeToConvert.isInstanceMember) {
|
| - return new ThisLocal(_kernelToElementMap.getMethod(nodeToConvert));
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| }
|
|
|