Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Side by Side Diff: lib/compiler/implementation/ssa/closure.dart

Issue 9969212: Reapplies (again) "Don't try to box immutable objects." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comment. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | samples/tests/samples/samples-leg.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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;
11 11
12 String toString() => "ClosureFieldElement($name)"; 12 String toString() => "ClosureFieldElement($name)";
13 } 13 }
14 14
15 class ClosureClassElement extends ClassElement { 15 class ClosureClassElement extends ClassElement {
16 ClosureClassElement(Compiler compiler, Element enclosingElement) 16 ClosureClassElement(Compiler compiler, Element enclosingElement)
17 : super(compiler.closureClass.name, enclosingElement) { 17 : super(compiler.closureClass.name, enclosingElement) {
18 isResolved = true; 18 isResolved = true;
19 compiler.closureClass.ensureResolved(compiler); 19 compiler.closureClass.ensureResolved(compiler);
20 supertype = compiler.closureClass.computeType(compiler); 20 supertype = compiler.closureClass.computeType(compiler);
21 } 21 }
22 } 22 }
23 23
24 class BoxElement extends Element {
25 BoxElement(SourceString name, Element enclosingElement)
26 : super(name, ElementKind.VARIABLE, enclosingElement);
27 }
28
29 class ThisElement extends Element {
30 ThisElement(Element enclosing)
31 : super(const SourceString('this'), ElementKind.PARAMETER, enclosing);
32
33 bool isAssignable() => false;
34 }
35
24 // The box-element for a scope, and the captured variables that need to be 36 // The box-element for a scope, and the captured variables that need to be
25 // stored in the box. 37 // stored in the box.
26 class ClosureScope { 38 class ClosureScope {
27 Element boxElement; 39 Element boxElement;
28 Map<Element, Element> capturedVariableMapping; 40 Map<Element, Element> capturedVariableMapping;
29 // If the scope is attached to a [For] contains the variables that are 41 // If the scope is attached to a [For] contains the variables that are
30 // declared in the initializer of the [For] and that need to be boxed. 42 // declared in the initializer of the [For] and that need to be boxed.
31 // Otherwise contains the empty List. 43 // Otherwise contains the empty List.
32 List<Element> boxedLoopVariables; 44 List<Element> boxedLoopVariables;
33 45
34 ClosureScope(this.boxElement, this.capturedVariableMapping) 46 ClosureScope(this.boxElement, this.capturedVariableMapping)
35 : boxedLoopVariables = const <Element>[]; 47 : boxedLoopVariables = const <Element>[];
36 48
37 bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty(); 49 bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty();
38 } 50 }
39 51
40 class ClosureData { 52 class ClosureData {
41 // The closure's element before any translation. Will be null for methods. 53 // The closure's element before any translation. Will be null for methods.
42 final FunctionElement closureElement; 54 final FunctionElement closureElement;
43 // The closureClassElement will be null for methods that are not local 55 // The closureClassElement will be null for methods that are not local
44 // closures. 56 // closures.
45 final ClassElement closureClassElement; 57 final ClassElement closureClassElement;
46 // The callElement will be null for methods that are not local closures. 58 // The callElement will be null for methods that are not local closures.
47 final FunctionElement callElement; 59 final FunctionElement callElement;
48 // The [thisElement] makes handling 'this' easier by treating it like any 60 // The [thisElement] makes handling 'this' easier by treating it like any
49 // other argument. It is only set for instance-members. 61 // other argument. It is only set for instance-members.
50 final Element thisElement; 62 final ThisElement thisElement;
51 63
52 // Maps free locals, arguments and function elements to their captured 64 // Maps free locals, arguments and function elements to their captured
53 // copies. 65 // copies.
54 final Map<Element, Element> freeVariableMapping; 66 final Map<Element, Element> freeVariableMapping;
55 // Maps closure-fields to their captured elements. This is somehow the inverse 67 // Maps closure-fields to their captured elements. This is somehow the inverse
56 // mapping of [freeVariableMapping], but whereas [freeVariableMapping] does 68 // mapping of [freeVariableMapping], but whereas [freeVariableMapping] does
57 // not deal with boxes, here we map instance-fields (which might represent 69 // not deal with boxes, here we map instance-fields (which might represent
58 // boxes) to their boxElement. 70 // boxes) to their boxElement.
59 final Map<Element, Element> capturedFieldMapping; 71 final Map<Element, Element> capturedFieldMapping;
60 72
(...skipping 14 matching lines...) Expand all
75 this.capturedFieldMapping = new Map<Element, Element>(), 87 this.capturedFieldMapping = new Map<Element, Element>(),
76 this.capturingScopes = new Map<Node, ClosureScope>(), 88 this.capturingScopes = new Map<Node, ClosureScope>(),
77 this.usedVariablesInTry = new Set<Element>(); 89 this.usedVariablesInTry = new Set<Element>();
78 90
79 bool isClosure() => closureElement !== null; 91 bool isClosure() => closureElement !== null;
80 } 92 }
81 93
82 class ClosureTranslator extends AbstractVisitor { 94 class ClosureTranslator extends AbstractVisitor {
83 final Compiler compiler; 95 final Compiler compiler;
84 final TreeElements elements; 96 final TreeElements elements;
85 int boxCounter = 0; 97 int closureFieldCounter = 0;
86 bool inTryCatchOrFinally = false; 98 bool inTryCatchOrFinally = false;
87 final Map<Node, ClosureData> closureDataCache; 99 final Map<Node, ClosureData> closureDataCache;
88 100
89 // Map of captured variables. Initially they will map to themselves. If 101 // Map of captured variables. Initially they will map to themselves. If
90 // a variable needs to be boxed then the scope declaring the variable 102 // a variable needs to be boxed then the scope declaring the variable
91 // will update this mapping. 103 // will update this mapping.
92 Map<Element, Element> capturedVariableMapping; 104 Map<Element, Element> capturedVariableMapping;
93 // List of encountered closures. 105 // List of encountered closures.
94 List<FunctionExpression> closures; 106 List<FunctionExpression> closures;
95 107
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 } else { 161 } else {
150 // A boxed element. 162 // A boxed element.
151 freeVariableMapping[fromElement] = updatedElement; 163 freeVariableMapping[fromElement] = updatedElement;
152 Element boxElement = updatedElement.enclosingElement; 164 Element boxElement = updatedElement.enclosingElement;
153 assert(boxElement.kind == ElementKind.VARIABLE); 165 assert(boxElement.kind == ElementKind.VARIABLE);
154 fieldCaptures.add(boxElement); 166 fieldCaptures.add(boxElement);
155 } 167 }
156 }); 168 });
157 ClassElement closureElement = data.closureClassElement; 169 ClassElement closureElement = data.closureClassElement;
158 assert(closureElement != null || fieldCaptures.isEmpty()); 170 assert(closureElement != null || fieldCaptures.isEmpty());
159 for (Element boxElement in fieldCaptures) { 171 for (Element capturedElement in fieldCaptures) {
160 Element fieldElement = 172 SourceString name;
161 new ClosureFieldElement(boxElement.name, closureElement); 173 if (capturedElement is BoxElement) {
174 // The name is already mangled.
175 name = capturedElement.name;
176 } else {
177 int id = closureFieldCounter++;
178 name = new SourceString("${capturedElement.name.slowToString()}_$id");
179 }
180 Element fieldElement = new ClosureFieldElement(name, closureElement);
162 closureElement.backendMembers = 181 closureElement.backendMembers =
163 closureElement.backendMembers.prepend(fieldElement); 182 closureElement.backendMembers.prepend(fieldElement);
164 data.capturedFieldMapping[fieldElement] = boxElement; 183 data.capturedFieldMapping[fieldElement] = capturedElement;
165 freeVariableMapping[boxElement] = fieldElement; 184 freeVariableMapping[capturedElement] = fieldElement;
166 } 185 }
167 } 186 }
168 } 187 }
169 188
170 void useLocal(Element element) { 189 void useLocal(Element element) {
171 // TODO(floitsch): replace this with a general solution. 190 // TODO(floitsch): replace this with a general solution.
172 Element functionElement = currentFunctionElement; 191 Element functionElement = currentFunctionElement;
173 if (functionElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { 192 if (functionElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
174 ConstructorBodyElement body = functionElement; 193 ConstructorBodyElement body = functionElement;
175 functionElement = body.constructor; 194 functionElement = body.constructor;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 } 252 }
234 253
235 // If variables that are declared in the [node] scope are captured and need 254 // If variables that are declared in the [node] scope are captured and need
236 // to be boxed create a box-element and update the [capturingScopes] in the 255 // to be boxed create a box-element and update the [capturingScopes] in the
237 // current [closureData]. 256 // current [closureData].
238 // The boxed variables are updated in the [capturedVariableMapping]. 257 // The boxed variables are updated in the [capturedVariableMapping].
239 void attachCapturedScopeVariables(Node node) { 258 void attachCapturedScopeVariables(Node node) {
240 Element box = null; 259 Element box = null;
241 Map<Element, Element> scopeMapping = new Map<Element, Element>(); 260 Map<Element, Element> scopeMapping = new Map<Element, Element>();
242 for (Element element in scopeVariables) { 261 for (Element element in scopeVariables) {
262 // No need to box non-assignable elements.
263 if (!element.isAssignable()) continue;
243 if (capturedVariableMapping.containsKey(element)) { 264 if (capturedVariableMapping.containsKey(element)) {
244 if (box == null) { 265 if (box == null) {
245 // TODO(floitsch): construct better box names. 266 // TODO(floitsch): construct better box names.
246 SourceString boxName = new SourceString("box${boxCounter++}"); 267 SourceString boxName =
247 box = new Element(boxName, 268 new SourceString("box_${closureFieldCounter++}");
248 ElementKind.VARIABLE, 269 box = new BoxElement(boxName, currentFunctionElement);
249 currentFunctionElement);
250 } 270 }
251 // TODO(floitsch): construct better boxed names. 271 // TODO(floitsch): construct better boxed names.
252 String elementName = element.name.slowToString(); 272 String elementName = element.name.slowToString();
253 // We are currently using the name in an HForeign which could replace 273 // We are currently using the name in an HForeign which could replace
254 // "$X" with something else. 274 // "$X" with something else.
255 String escaped = elementName.replaceAll("\$", "_"); 275 String escaped = elementName.replaceAll("\$", "_");
256 SourceString boxedName = new SourceString("${escaped}_${boxCounter++}"); 276 SourceString boxedName =
277 new SourceString("${escaped}_${closureFieldCounter++}");
257 Element boxed = new Element(boxedName, ElementKind.FIELD, box); 278 Element boxed = new Element(boxedName, ElementKind.FIELD, box);
258 scopeMapping[element] = boxed; 279 scopeMapping[element] = boxed;
259 capturedVariableMapping[element] = boxed; 280 capturedVariableMapping[element] = boxed;
260 } 281 }
261 } 282 }
262 if (!scopeMapping.isEmpty()) { 283 if (!scopeMapping.isEmpty()) {
263 ClosureScope scope = new ClosureScope(box, scopeMapping); 284 ClosureScope scope = new ClosureScope(box, scopeMapping);
264 closureData.capturingScopes[node] = scope; 285 closureData.capturingScopes[node] = scope;
265 } 286 }
266 } 287 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 // the body. 360 // the body.
340 if (element.isInstanceMember() || 361 if (element.isInstanceMember() ||
341 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { 362 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
342 // TODO(floitsch): currently all variables are considered to be 363 // TODO(floitsch): currently all variables are considered to be
343 // declared in the GENERATIVE_CONSTRUCTOR. Including the 'this'. 364 // declared in the GENERATIVE_CONSTRUCTOR. Including the 'this'.
344 Element thisEnclosingElement = element; 365 Element thisEnclosingElement = element;
345 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { 366 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
346 ConstructorBodyElement body = element; 367 ConstructorBodyElement body = element;
347 thisEnclosingElement = body.constructor; 368 thisEnclosingElement = body.constructor;
348 } 369 }
349 thisElement = new Element(const SourceString("this"), 370 thisElement = new ThisElement(thisEnclosingElement);
350 ElementKind.PARAMETER,
351 thisEnclosingElement);
352 } 371 }
353 closureData = new ClosureData(null, null, null, thisElement); 372 closureData = new ClosureData(null, null, null, thisElement);
354 } 373 }
355 scopeVariables = new List<Element>(); 374 scopeVariables = new List<Element>();
356 375
357 // TODO(floitsch): a named function is visible from inside itself. Add
358 // the element to the block.
359
360 // We have to declare the implicit 'this' parameter. 376 // We have to declare the implicit 'this' parameter.
361 if (!insideClosure && closureData.thisElement !== null) { 377 if (!insideClosure && closureData.thisElement !== null) {
362 declareLocal(closureData.thisElement); 378 declareLocal(closureData.thisElement);
363 } 379 }
364 // If we are inside a named closure we have to declare ourselve. For 380 // If we are inside a named closure we have to declare ourselve. For
365 // simplicity we declare the local even if the closure does not have a name 381 // simplicity we declare the local even if the closure does not have a name
366 // It will simply not be used. 382 // It will simply not be used.
367 if (insideClosure) { 383 if (insideClosure) {
368 declareLocal(element); 384 declareLocal(element);
369 } 385 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 declareLocal(elements[node]); 424 declareLocal(elements[node]);
409 } 425 }
410 426
411 visitTryStatement(TryStatement node) { 427 visitTryStatement(TryStatement node) {
412 // TODO(ngeoffray): implement finer grain state. 428 // TODO(ngeoffray): implement finer grain state.
413 inTryCatchOrFinally = true; 429 inTryCatchOrFinally = true;
414 node.visitChildren(this); 430 node.visitChildren(this);
415 inTryCatchOrFinally = false; 431 inTryCatchOrFinally = false;
416 } 432 }
417 } 433 }
OLDNEW
« no previous file with comments | « no previous file | samples/tests/samples/samples-leg.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698