| 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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 } | 123 } |
| 124 } | 124 } |
| 125 assert(_closureMappingCache[element] != null, | 125 assert(_closureMappingCache[element] != null, |
| 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 | |
| 134 /// non-elements. | |
| 135 // TODO(johnniwinther): Remove `implements Element`. | |
| 136 abstract class CapturedVariable implements Element {} | |
| 137 | |
| 138 // TODO(ahe): These classes continuously cause problems. We need to | 133 // TODO(ahe): These classes continuously cause problems. We need to |
| 139 // find a more general solution. | 134 // find a more general solution. |
| 140 class ClosureFieldElement extends ElementX | 135 class ClosureFieldElement extends ElementX |
| 141 implements FieldElement, CapturedVariable, PrivatelyNamedJSEntity { | 136 implements FieldElement, PrivatelyNamedJSEntity { |
| 142 /// The [BoxLocal] or [LocalElement] being accessed through the field. | 137 /// The [BoxLocal] or [LocalElement] being accessed through the field. |
| 143 final Local local; | 138 final Local local; |
| 144 | 139 |
| 145 ClosureFieldElement(String name, this.local, ClosureClassElement enclosing) | 140 ClosureFieldElement(String name, this.local, ClosureClassElement enclosing) |
| 146 : super(name, ElementKind.FIELD, enclosing); | 141 : super(name, ElementKind.FIELD, enclosing); |
| 147 | 142 |
| 148 /// Use [closureClass] instead. | 143 /// Use [closureClass] instead. |
| 149 @deprecated | 144 @deprecated |
| 150 get enclosingElement => super.enclosingElement; | 145 get enclosingElement => super.enclosingElement; |
| 151 | 146 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 | 283 |
| 289 @override | 284 @override |
| 290 MemberElement get memberContext => executableContext.memberContext; | 285 MemberElement get memberContext => executableContext.memberContext; |
| 291 | 286 |
| 292 String toString() => 'BoxLocal($name)'; | 287 String toString() => 'BoxLocal($name)'; |
| 293 } | 288 } |
| 294 | 289 |
| 295 // TODO(ngeoffray, ahe): These classes continuously cause problems. We need to | 290 // TODO(ngeoffray, ahe): These classes continuously cause problems. We need to |
| 296 // find a more general solution. | 291 // find a more general solution. |
| 297 class BoxFieldElement extends ElementX | 292 class BoxFieldElement extends ElementX |
| 298 implements | 293 implements TypedElement, FieldElement, PrivatelyNamedJSEntity { |
| 299 TypedElement, | |
| 300 CapturedVariable, | |
| 301 FieldElement, | |
| 302 PrivatelyNamedJSEntity { | |
| 303 final BoxLocal box; | 294 final BoxLocal box; |
| 304 | 295 |
| 305 BoxFieldElement(String name, this.variableElement, BoxLocal box) | 296 BoxFieldElement(String name, this.variableElement, BoxLocal box) |
| 306 : this.box = box, | 297 : this.box = box, |
| 307 super(name, ElementKind.FIELD, box.executableContext); | 298 super(name, ElementKind.FIELD, box.executableContext); |
| 308 | 299 |
| 309 ResolutionDartType computeType(Resolution resolution) => type; | 300 ResolutionDartType computeType(Resolution resolution) => type; |
| 310 | 301 |
| 311 ResolutionDartType get type => variableElement.type; | 302 ResolutionDartType get type => variableElement.type; |
| 312 | 303 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 | 406 |
| 416 // The box-element for a scope, and the captured variables that need to be | 407 // The box-element for a scope, and the captured variables that need to be |
| 417 // stored in the box. | 408 // stored in the box. |
| 418 class ClosureScope { | 409 class ClosureScope { |
| 419 final BoxLocal boxElement; | 410 final BoxLocal boxElement; |
| 420 final Map<Local, BoxFieldElement> capturedVariables; | 411 final Map<Local, BoxFieldElement> capturedVariables; |
| 421 | 412 |
| 422 // If the scope is attached to a [For] contains the variables that are | 413 // 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. | 414 // declared in the initializer of the [For] and that need to be boxed. |
| 424 // Otherwise contains the empty List. | 415 // Otherwise contains the empty List. |
| 425 List<VariableElement> boxedLoopVariables = const <VariableElement>[]; | 416 List<Local> boxedLoopVariables = const <Local>[]; |
| 426 | 417 |
| 427 ClosureScope(this.boxElement, this.capturedVariables); | 418 ClosureScope(this.boxElement, this.capturedVariables); |
| 428 | 419 |
| 429 bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty; | 420 bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty; |
| 430 | 421 |
| 431 bool isCapturedVariable(VariableElement variable) { | 422 bool isCapturedVariable(VariableElement variable) { |
| 432 return capturedVariables.containsKey(variable); | 423 return capturedVariables.containsKey(variable); |
| 433 } | 424 } |
| 434 | 425 |
| 435 void forEachCapturedVariable( | 426 void forEachCapturedVariable( |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 /// | 466 /// |
| 476 /// The callElement will be null for methods that are not local closures. | 467 /// The callElement will be null for methods that are not local closures. |
| 477 final MethodElement callElement; | 468 final MethodElement callElement; |
| 478 | 469 |
| 479 /// The [thisElement] makes handling 'this' easier by treating it like any | 470 /// The [thisElement] makes handling 'this' easier by treating it like any |
| 480 /// other argument. It is only set for instance-members. | 471 /// other argument. It is only set for instance-members. |
| 481 final ThisLocal thisLocal; | 472 final ThisLocal thisLocal; |
| 482 | 473 |
| 483 /// Maps free locals, arguments, function elements, and box locals to | 474 /// Maps free locals, arguments, function elements, and box locals to |
| 484 /// their locations. | 475 /// their locations. |
| 485 final Map<Local, CapturedVariable> freeVariableMap = | 476 final Map<Local, FieldEntity> freeVariableMap = new Map<Local, FieldEntity>(); |
| 486 new Map<Local, CapturedVariable>(); | |
| 487 | 477 |
| 488 /// Maps [Loop] and [FunctionExpression] nodes to their [ClosureScope] which | 478 /// Maps [Loop] and [FunctionExpression] nodes to their [ClosureScope] which |
| 489 /// contains their box and the captured variables that are stored in the box. | 479 /// 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 | 480 /// This map will be empty if the method/closure of this [ClosureData] does |
| 491 /// not contain any nested closure. | 481 /// not contain any nested closure. |
| 492 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); | 482 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); |
| 493 | 483 |
| 494 /// Variables that are used in a try must be treated as boxed because the | 484 /// Variables that are used in a try must be treated as boxed because the |
| 495 /// control flow can be non-linear. | 485 /// control flow can be non-linear. |
| 496 /// | 486 /// |
| 497 /// Also parameters to a `sync*` generator must be boxed, because of the way | 487 /// Also parameters to a `sync*` generator must be boxed, because of the way |
| 498 /// we rewrite sync* functions. See also comments in [useLocal]. | 488 /// we rewrite sync* functions. See also comments in [useLocal]. |
| 499 // TODO(johnniwinther): Add variables to this only if the variable is mutated. | 489 // TODO(johnniwinther): Add variables to this only if the variable is mutated. |
| 500 final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>(); | 490 final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>(); |
| 501 | 491 |
| 502 ClosureClassMap(this.closureElement, this.closureClassElement, | 492 ClosureClassMap(this.closureElement, this.closureClassElement, |
| 503 this.callElement, this.thisLocal); | 493 this.callElement, this.thisLocal); |
| 504 | 494 |
| 505 void addFreeVariable(Local element) { | 495 void addFreeVariable(Local element) { |
| 506 assert(freeVariableMap[element] == null); | 496 assert(freeVariableMap[element] == null); |
| 507 freeVariableMap[element] = null; | 497 freeVariableMap[element] = null; |
| 508 } | 498 } |
| 509 | 499 |
| 510 Iterable<Local> get freeVariables => freeVariableMap.keys; | 500 Iterable<Local> get freeVariables => freeVariableMap.keys; |
| 511 | 501 |
| 512 bool isFreeVariable(Local element) { | 502 bool isFreeVariable(Local element) { |
| 513 return freeVariableMap.containsKey(element); | 503 return freeVariableMap.containsKey(element); |
| 514 } | 504 } |
| 515 | 505 |
| 516 void forEachFreeVariable(f(Local variable, CapturedVariable field)) { | 506 void forEachFreeVariable(f(Local variable, FieldEntity field)) { |
| 517 freeVariableMap.forEach(f); | 507 freeVariableMap.forEach(f); |
| 518 } | 508 } |
| 519 | 509 |
| 520 Local getLocalVariableForClosureField(ClosureFieldElement field) { | 510 Local getLocalVariableForClosureField(ClosureFieldElement field) { |
| 521 return field.local; | 511 return field.local; |
| 522 } | 512 } |
| 523 | 513 |
| 524 bool get isClosure => closureElement != null; | 514 bool get isClosure => closureElement != null; |
| 525 | 515 |
| 526 bool capturingScopesBox(Local variable) { | 516 bool capturingScopesBox(Local variable) { |
| 527 return capturingScopes.values.any((scope) { | 517 return capturingScopes.values.any((scope) { |
| 528 return scope.boxedLoopVariables.contains(variable); | 518 return scope.boxedLoopVariables.contains(variable); |
| 529 }); | 519 }); |
| 530 } | 520 } |
| 531 | 521 |
| 532 bool isVariableBoxed(Local variable) { | 522 bool isVariableBoxed(Local variable) { |
| 533 CapturedVariable copy = freeVariableMap[variable]; | 523 FieldEntity copy = freeVariableMap[variable]; |
| 534 if (copy is BoxFieldElement) { | 524 if (copy is BoxFieldElement) { |
| 535 return true; | 525 return true; |
| 536 } | 526 } |
| 537 return capturingScopesBox(variable); | 527 return capturingScopesBox(variable); |
| 538 } | 528 } |
| 539 | 529 |
| 540 void forEachCapturedVariable(void f(Local variable, CapturedVariable field)) { | 530 void forEachCapturedVariable(void f(Local variable, FieldEntity field)) { |
| 541 freeVariableMap.forEach((variable, copy) { | 531 freeVariableMap.forEach((variable, copy) { |
| 542 if (variable is BoxLocal) return; | 532 if (variable is BoxLocal) return; |
| 543 f(variable, copy); | 533 f(variable, copy); |
| 544 }); | 534 }); |
| 545 capturingScopes.values.forEach((ClosureScope scope) { | 535 capturingScopes.values.forEach((ClosureScope scope) { |
| 546 scope.forEachCapturedVariable(f); | 536 scope.forEachCapturedVariable(f); |
| 547 }); | 537 }); |
| 548 } | 538 } |
| 549 | 539 |
| 550 void forEachBoxedVariable( | 540 void forEachBoxedVariable( |
| (...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1238 /// | 1228 /// |
| 1239 /// Move the below classes to a JS model eventually. | 1229 /// Move the below classes to a JS model eventually. |
| 1240 /// | 1230 /// |
| 1241 abstract class JSEntity implements Entity { | 1231 abstract class JSEntity implements Entity { |
| 1242 Entity get declaredEntity; | 1232 Entity get declaredEntity; |
| 1243 } | 1233 } |
| 1244 | 1234 |
| 1245 abstract class PrivatelyNamedJSEntity implements JSEntity { | 1235 abstract class PrivatelyNamedJSEntity implements JSEntity { |
| 1246 Entity get rootOfScope; | 1236 Entity get rootOfScope; |
| 1247 } | 1237 } |
| OLD | NEW |