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; | |
floitsch
2012/02/08 10:07:53
we don't care about the try-body. -> inCatchOrFina
ngeoffray
2012/02/08 10:17:17
As discussed, we do care about the try body, becau
| |
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. | |
floitsch
2012/02/08 10:07:53
only do this if the variable is mutated in the try
ngeoffray
2012/02/08 10:17:17
ditto
| |
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) { | |
floitsch
2012/02/08 10:07:53
move this code into visitCatch and visitFinally.
ngeoffray
2012/02/08 10:17:17
ditto
| |
319 // TODO(ngeoffray): implement finer grain state. | |
320 inTryCatchOrFinally = true; | |
321 node.visitChildren(this); | |
322 inTryCatchOrFinally = false; | |
323 } | |
310 } | 324 } |
OLD | NEW |