| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 class ClosureFieldElement extends Element { | 5 class ClosureFieldElement extends Element { |
| 6 ClosureFieldElement(SourceString name, ClassElement enclosing) | 6 ClosureFieldElement(SourceString name, ClassElement enclosing) |
| 7 : super(name, ElementKind.FIELD, enclosing); | 7 : super(name, ElementKind.FIELD, enclosing); |
| 8 | 8 |
| 9 bool isInstanceMember() => true; | 9 bool isInstanceMember() => true; |
| 10 bool isAssignable() => false; | 10 bool isAssignable() => false; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 // boxes) to their boxElement. | 37 // boxes) to their boxElement. |
| 38 final Map<Element, Element> capturedFieldMapping; | 38 final Map<Element, Element> capturedFieldMapping; |
| 39 | 39 |
| 40 // Maps scopes ([Loop] and [FunctionExpression] nodes) to their | 40 // Maps scopes ([Loop] and [FunctionExpression] nodes) to their |
| 41 // [ClosureScope] which contains their box and the | 41 // [ClosureScope] which contains their box and the |
| 42 // captured variables that are stored in the box. | 42 // captured variables that are stored in the box. |
| 43 // This map will be empty if the method/closure of this [ClosureData] does not | 43 // This map will be empty if the method/closure of this [ClosureData] does not |
| 44 // contain any nested closure. | 44 // contain any nested closure. |
| 45 final Map<Node, ClosureScope> capturingScopes; | 45 final Map<Node, ClosureScope> capturingScopes; |
| 46 | 46 |
| 47 final Set<Element> usedVariablesInTry; |
| 48 |
| 47 ClosureData(this.globalizedClosureElement, this.callElement) | 49 ClosureData(this.globalizedClosureElement, this.callElement) |
| 48 : this.freeVariableMapping = new Map<Element, Element>(), | 50 : this.freeVariableMapping = new Map<Element, Element>(), |
| 49 this.capturedFieldMapping = new Map<Element, Element>(), | 51 this.capturedFieldMapping = new Map<Element, Element>(), |
| 50 this.capturingScopes = new Map<Node, ClosureScope>(); | 52 this.capturingScopes = new Map<Node, ClosureScope>(), |
| 53 this.usedVariablesInTry = new Set<Element>(); |
| 51 } | 54 } |
| 52 | 55 |
| 53 Map<Node, ClosureData> _closureDataCache; | 56 Map<Node, ClosureData> _closureDataCache; |
| 54 Map<Node, ClosureData> get closureDataCache() { | 57 Map<Node, ClosureData> get closureDataCache() { |
| 55 if (_closureDataCache === null) { | 58 if (_closureDataCache === null) { |
| 56 _closureDataCache = new HashMap<Node, ClosureData>(); | 59 _closureDataCache = new HashMap<Node, ClosureData>(); |
| 57 } | 60 } |
| 58 return _closureDataCache; | 61 return _closureDataCache; |
| 59 } | 62 } |
| 60 | 63 |
| 61 class ClosureTranslator extends AbstractVisitor { | 64 class ClosureTranslator extends AbstractVisitor { |
| 62 final Compiler compiler; | 65 final Compiler compiler; |
| 63 final TreeElements elements; | 66 final TreeElements elements; |
| 64 int boxCounter = 0; | 67 int boxCounter = 0; |
| 68 bool inTryCatchOrFinally = false; |
| 65 | 69 |
| 66 // Map of captured variables. Initially they will map to themselves. If | 70 // Map of captured variables. Initially they will map to themselves. If |
| 67 // a variable needs to be boxed then the scope declaring the variable | 71 // a variable needs to be boxed then the scope declaring the variable |
| 68 // will update this mapping. | 72 // will update this mapping. |
| 69 Map<Element, Element> capturedVariableMapping; | 73 Map<Element, Element> capturedVariableMapping; |
| 70 // List of encountered closures. | 74 // List of encountered closures. |
| 71 List<FunctionExpression> closures; | 75 List<FunctionExpression> closures; |
| 72 | 76 |
| 73 // The variables that have been declared in the current scope. | 77 // The variables that have been declared in the current scope. |
| 74 List<Element> scopeVariables; | 78 List<Element> scopeVariables; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 freeVariableMapping[boxElement] = fieldElement; | 144 freeVariableMapping[boxElement] = fieldElement; |
| 141 } | 145 } |
| 142 } | 146 } |
| 143 } | 147 } |
| 144 | 148 |
| 145 void useLocal(Element element) { | 149 void useLocal(Element element) { |
| 146 if (element.enclosingElement != currentFunctionElement) { | 150 if (element.enclosingElement != currentFunctionElement) { |
| 147 assert(closureData.freeVariableMapping[element] == null || | 151 assert(closureData.freeVariableMapping[element] == null || |
| 148 closureData.freeVariableMapping[element] == element); | 152 closureData.freeVariableMapping[element] == element); |
| 149 closureData.freeVariableMapping[element] = element; | 153 closureData.freeVariableMapping[element] = element; |
| 154 } else if (inTryCatchOrFinally) { |
| 155 // TODO(ngeoffray): only do this if the variable is mutated. |
| 156 closureData.usedVariablesInTry.add(element); |
| 150 } | 157 } |
| 151 } | 158 } |
| 152 | 159 |
| 153 void declareLocal(Element element) { | 160 void declareLocal(Element element) { |
| 154 scopeVariables.add(element); | 161 scopeVariables.add(element); |
| 155 } | 162 } |
| 156 | 163 |
| 157 visit(Node node) => node.accept(this); | 164 visit(Node node) => node.accept(this); |
| 158 | 165 |
| 159 visitNode(Node node) => node.visitChildren(this); | 166 visitNode(Node node) => node.visitChildren(this); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 useLocal(element); | 307 useLocal(element); |
| 301 } | 308 } |
| 302 | 309 |
| 303 // If we just visited a closure we declare it. This is not always correct | 310 // If we just visited a closure we declare it. This is not always correct |
| 304 // since some closures are used as expressions and don't introduce any | 311 // since some closures are used as expressions and don't introduce any |
| 305 // name. But in this case the added local is simply not used. | 312 // name. But in this case the added local is simply not used. |
| 306 if (savedInsideClosure) { | 313 if (savedInsideClosure) { |
| 307 declareLocal(elements[node]); | 314 declareLocal(elements[node]); |
| 308 } | 315 } |
| 309 } | 316 } |
| 317 |
| 318 visitTryStatement(TryStatement node) { |
| 319 // TODO(ngeoffray): implement finer grain state. |
| 320 inTryCatchOrFinally = true; |
| 321 node.visitChildren(this); |
| 322 inTryCatchOrFinally = false; |
| 323 } |
| 310 } | 324 } |
| OLD | NEW |