Chromium Code Reviews| 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 library closureToClassMapper; | 5 library closureToClassMapper; |
| 6 | 6 |
| 7 import 'common/names.dart' show Identifiers; | 7 import 'common/names.dart' show Identifiers; |
| 8 import 'common/resolution.dart' show ParsingContext, Resolution; | 8 import 'common/resolution.dart' show ParsingContext, Resolution; |
| 9 import 'common/tasks.dart' show CompilerTask; | 9 import 'common/tasks.dart' show CompilerTask; |
| 10 import 'common.dart'; | 10 import 'common.dart'; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 failedAt(element, "No ClosureClassMap computed for ${element}.")); | 126 failedAt(element, "No ClosureClassMap computed for ${element}.")); |
| 127 return _closureMappingCache[element]; | 127 return _closureMappingCache[element]; |
| 128 }); | 128 }); |
| 129 }); | 129 }); |
| 130 } | 130 } |
| 131 } | 131 } |
| 132 | 132 |
| 133 /// Common interface for [BoxFieldElement] and [ClosureFieldElement] as | 133 /// Common interface for [BoxFieldElement] and [ClosureFieldElement] as |
| 134 /// non-elements. | 134 /// non-elements. |
| 135 // TODO(johnniwinther): Remove `implements Element`. | 135 // TODO(johnniwinther): Remove `implements Element`. |
| 136 abstract class CapturedVariable implements Element {} | 136 abstract class CapturedVariable implements Element {} |
|
Siggi Cherem (dart-lang)
2017/06/06 03:07:36
I wonder if we should simply delete this type now.
Emily Fortuna
2017/06/06 17:46:19
oh good point! removed!
| |
| 137 | 137 |
| 138 // TODO(ahe): These classes continuously cause problems. We need to | 138 // TODO(ahe): These classes continuously cause problems. We need to |
| 139 // find a more general solution. | 139 // find a more general solution. |
| 140 class ClosureFieldElement extends ElementX | 140 class ClosureFieldElement extends ElementX |
| 141 implements FieldElement, CapturedVariable, PrivatelyNamedJSEntity { | 141 implements FieldElement, CapturedVariable, PrivatelyNamedJSEntity { |
| 142 /// The [BoxLocal] or [LocalElement] being accessed through the field. | 142 /// The [BoxLocal] or [LocalElement] being accessed through the field. |
| 143 final Local local; | 143 final Local local; |
| 144 | 144 |
| 145 ClosureFieldElement(String name, this.local, ClosureClassElement enclosing) | 145 ClosureFieldElement(String name, this.local, ClosureClassElement enclosing) |
| 146 : super(name, ElementKind.FIELD, enclosing); | 146 : super(name, ElementKind.FIELD, enclosing); |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 415 | 415 |
| 416 // The box-element for a scope, and the captured variables that need to be | 416 // The box-element for a scope, and the captured variables that need to be |
| 417 // stored in the box. | 417 // stored in the box. |
| 418 class ClosureScope { | 418 class ClosureScope { |
| 419 final BoxLocal boxElement; | 419 final BoxLocal boxElement; |
| 420 final Map<Local, BoxFieldElement> capturedVariables; | 420 final Map<Local, BoxFieldElement> capturedVariables; |
| 421 | 421 |
| 422 // If the scope is attached to a [For] contains the variables that are | 422 // If the scope is attached to a [For] contains the variables that are |
| 423 // declared in the initializer of the [For] and that need to be boxed. | 423 // declared in the initializer of the [For] and that need to be boxed. |
| 424 // Otherwise contains the empty List. | 424 // Otherwise contains the empty List. |
| 425 List<VariableElement> boxedLoopVariables = const <VariableElement>[]; | 425 List<Local> boxedLoopVariables = const <Local>[]; |
| 426 | 426 |
| 427 ClosureScope(this.boxElement, this.capturedVariables); | 427 ClosureScope(this.boxElement, this.capturedVariables); |
| 428 | 428 |
| 429 bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty; | 429 bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty; |
| 430 | 430 |
| 431 bool isCapturedVariable(VariableElement variable) { | 431 bool isCapturedVariable(VariableElement variable) { |
| 432 return capturedVariables.containsKey(variable); | 432 return capturedVariables.containsKey(variable); |
| 433 } | 433 } |
| 434 | 434 |
| 435 void forEachCapturedVariable( | 435 void forEachCapturedVariable( |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 /// | 475 /// |
| 476 /// The callElement will be null for methods that are not local closures. | 476 /// The callElement will be null for methods that are not local closures. |
| 477 final MethodElement callElement; | 477 final MethodElement callElement; |
| 478 | 478 |
| 479 /// The [thisElement] makes handling 'this' easier by treating it like any | 479 /// The [thisElement] makes handling 'this' easier by treating it like any |
| 480 /// other argument. It is only set for instance-members. | 480 /// other argument. It is only set for instance-members. |
| 481 final ThisLocal thisLocal; | 481 final ThisLocal thisLocal; |
| 482 | 482 |
| 483 /// Maps free locals, arguments, function elements, and box locals to | 483 /// Maps free locals, arguments, function elements, and box locals to |
| 484 /// their locations. | 484 /// their locations. |
| 485 final Map<Local, CapturedVariable> freeVariableMap = | 485 final Map<Local, FieldEntity> freeVariableMap = new Map<Local, FieldEntity>(); |
| 486 new Map<Local, CapturedVariable>(); | |
| 487 | 486 |
| 488 /// Maps [Loop] and [FunctionExpression] nodes to their [ClosureScope] which | 487 /// Maps [Loop] and [FunctionExpression] nodes to their [ClosureScope] which |
| 489 /// contains their box and the captured variables that are stored in the box. | 488 /// contains their box and the captured variables that are stored in the box. |
| 490 /// This map will be empty if the method/closure of this [ClosureData] does | 489 /// This map will be empty if the method/closure of this [ClosureData] does |
| 491 /// not contain any nested closure. | 490 /// not contain any nested closure. |
| 492 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); | 491 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); |
| 493 | 492 |
| 494 /// Variables that are used in a try must be treated as boxed because the | 493 /// Variables that are used in a try must be treated as boxed because the |
| 495 /// control flow can be non-linear. | 494 /// control flow can be non-linear. |
| 496 /// | 495 /// |
| 497 /// Also parameters to a `sync*` generator must be boxed, because of the way | 496 /// Also parameters to a `sync*` generator must be boxed, because of the way |
| 498 /// we rewrite sync* functions. See also comments in [useLocal]. | 497 /// we rewrite sync* functions. See also comments in [useLocal]. |
| 499 // TODO(johnniwinther): Add variables to this only if the variable is mutated. | 498 // TODO(johnniwinther): Add variables to this only if the variable is mutated. |
| 500 final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>(); | 499 final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>(); |
| 501 | 500 |
| 502 ClosureClassMap(this.closureElement, this.closureClassElement, | 501 ClosureClassMap(this.closureElement, this.closureClassElement, |
| 503 this.callElement, this.thisLocal); | 502 this.callElement, this.thisLocal); |
| 504 | 503 |
| 505 void addFreeVariable(Local element) { | 504 void addFreeVariable(Local element) { |
| 506 assert(freeVariableMap[element] == null); | 505 assert(freeVariableMap[element] == null); |
| 507 freeVariableMap[element] = null; | 506 freeVariableMap[element] = null; |
| 508 } | 507 } |
| 509 | 508 |
| 510 Iterable<Local> get freeVariables => freeVariableMap.keys; | 509 Iterable<Local> get freeVariables => freeVariableMap.keys; |
| 511 | 510 |
| 512 bool isFreeVariable(Local element) { | 511 bool isFreeVariable(Local element) { |
| 513 return freeVariableMap.containsKey(element); | 512 return freeVariableMap.containsKey(element); |
| 514 } | 513 } |
| 515 | 514 |
| 516 void forEachFreeVariable(f(Local variable, CapturedVariable field)) { | 515 void forEachFreeVariable(f(Local variable, FieldEntity field)) { |
| 517 freeVariableMap.forEach(f); | 516 freeVariableMap.forEach(f); |
| 518 } | 517 } |
| 519 | 518 |
| 520 Local getLocalVariableForClosureField(ClosureFieldElement field) { | 519 Local getLocalVariableForClosureField(ClosureFieldElement field) { |
| 521 return field.local; | 520 return field.local; |
| 522 } | 521 } |
| 523 | 522 |
| 524 bool get isClosure => closureElement != null; | 523 bool get isClosure => closureElement != null; |
| 525 | 524 |
| 526 bool capturingScopesBox(Local variable) { | 525 bool capturingScopesBox(Local variable) { |
| 527 return capturingScopes.values.any((scope) { | 526 return capturingScopes.values.any((scope) { |
| 528 return scope.boxedLoopVariables.contains(variable); | 527 return scope.boxedLoopVariables.contains(variable); |
| 529 }); | 528 }); |
| 530 } | 529 } |
| 531 | 530 |
| 532 bool isVariableBoxed(Local variable) { | 531 bool isVariableBoxed(Local variable) { |
| 533 CapturedVariable copy = freeVariableMap[variable]; | 532 FieldEntity copy = freeVariableMap[variable]; |
| 534 if (copy is BoxFieldElement) { | 533 if (copy is BoxFieldElement) { |
| 535 return true; | 534 return true; |
| 536 } | 535 } |
| 537 return capturingScopesBox(variable); | 536 return capturingScopesBox(variable); |
| 538 } | 537 } |
| 539 | 538 |
| 540 void forEachCapturedVariable(void f(Local variable, CapturedVariable field)) { | 539 void forEachCapturedVariable(void f(Local variable, FieldEntity field)) { |
| 541 freeVariableMap.forEach((variable, copy) { | 540 freeVariableMap.forEach((variable, copy) { |
| 542 if (variable is BoxLocal) return; | 541 if (variable is BoxLocal) return; |
| 543 f(variable, copy); | 542 f(variable, copy); |
| 544 }); | 543 }); |
| 545 capturingScopes.values.forEach((ClosureScope scope) { | 544 capturingScopes.values.forEach((ClosureScope scope) { |
| 546 scope.forEachCapturedVariable(f); | 545 scope.forEachCapturedVariable(f); |
| 547 }); | 546 }); |
| 548 } | 547 } |
| 549 | 548 |
| 550 void forEachBoxedVariable( | 549 void forEachBoxedVariable( |
| (...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1238 /// | 1237 /// |
| 1239 /// Move the below classes to a JS model eventually. | 1238 /// Move the below classes to a JS model eventually. |
| 1240 /// | 1239 /// |
| 1241 abstract class JSEntity implements Entity { | 1240 abstract class JSEntity implements Entity { |
| 1242 Entity get declaredEntity; | 1241 Entity get declaredEntity; |
| 1243 } | 1242 } |
| 1244 | 1243 |
| 1245 abstract class PrivatelyNamedJSEntity implements JSEntity { | 1244 abstract class PrivatelyNamedJSEntity implements JSEntity { |
| 1246 Entity get rootOfScope; | 1245 Entity get rootOfScope; |
| 1247 } | 1246 } |
| OLD | NEW |