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 "elements/elements.dart"; | 7 import "elements/elements.dart"; |
| 8 import "dart2jslib.dart"; | 8 import "dart2jslib.dart"; |
| 9 import "dart_types.dart"; | 9 import "dart_types.dart"; |
| 10 import "js_backend/js_backend.dart" show JavaScriptBackend; | 10 import "js_backend/js_backend.dart" show JavaScriptBackend; |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 265 | 265 |
| 266 /// Call method of a closure class. | 266 /// Call method of a closure class. |
| 267 class SynthesizedCallMethodElementX extends BaseFunctionElementX { | 267 class SynthesizedCallMethodElementX extends BaseFunctionElementX { |
| 268 final LocalFunctionElement expression; | 268 final LocalFunctionElement expression; |
| 269 | 269 |
| 270 SynthesizedCallMethodElementX(String name, | 270 SynthesizedCallMethodElementX(String name, |
| 271 LocalFunctionElementX other, | 271 LocalFunctionElementX other, |
| 272 ClosureClassElement enclosing) | 272 ClosureClassElement enclosing) |
| 273 : expression = other, | 273 : expression = other, |
| 274 super(name, other.kind, other.modifiers, enclosing, false) { | 274 super(name, other.kind, other.modifiers, enclosing, false) { |
| 275 asyncMarker = other.asyncMarker; | |
| 275 functionSignatureCache = other.functionSignature; | 276 functionSignatureCache = other.functionSignature; |
| 276 } | 277 } |
| 277 | 278 |
| 278 /// Use [closureClass] instead. | 279 /// Use [closureClass] instead. |
| 279 @deprecated | 280 @deprecated |
| 280 get enclosingElement => super.enclosingElement; | 281 get enclosingElement => super.enclosingElement; |
| 281 | 282 |
| 282 ClosureClassElement get closureClass => super.enclosingElement; | 283 ClosureClassElement get closureClass => super.enclosingElement; |
| 283 | 284 |
| 284 MemberElement get memberContext { | 285 MemberElement get memberContext { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 final Map<Local, CapturedVariable> freeVariableMap = | 341 final Map<Local, CapturedVariable> freeVariableMap = |
| 341 new Map<Local, CapturedVariable>(); | 342 new Map<Local, CapturedVariable>(); |
| 342 | 343 |
| 343 // Maps [Loop] and [FunctionExpression] nodes to their | 344 // Maps [Loop] and [FunctionExpression] nodes to their |
| 344 // [ClosureScope] which contains their box and the | 345 // [ClosureScope] which contains their box and the |
| 345 // captured variables that are stored in the box. | 346 // captured variables that are stored in the box. |
| 346 // This map will be empty if the method/closure of this [ClosureData] does not | 347 // This map will be empty if the method/closure of this [ClosureData] does not |
| 347 // contain any nested closure. | 348 // contain any nested closure. |
| 348 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); | 349 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); |
| 349 | 350 |
| 350 final Set<Local> usedVariablesInTry = new Set<Local>(); | 351 // Variables that are used in a try must be treated as boxed because the |
|
floitsch
2015/02/04 12:31:28
Make dartcomment.
Add new line before "Also param
sigurdm
2015/02/05 14:06:03
Done.
| |
| 352 // control flow can be non-linear. | |
| 353 // Also parameters to a `sync*` generator must be boxed, because of the way we | |
| 354 // rewrite sync* functions. See also comments in [useLocal]. | |
| 355 // TODO(johnniwinter): Add variables to this only if the variable is mutated. | |
| 356 final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>(); | |
| 351 | 357 |
| 352 ClosureClassMap(this.closureElement, | 358 ClosureClassMap(this.closureElement, |
| 353 this.closureClassElement, | 359 this.closureClassElement, |
| 354 this.callElement, | 360 this.callElement, |
| 355 this.thisLocal); | 361 this.thisLocal); |
| 356 | 362 |
| 357 void addFreeVariable(Local element) { | 363 void addFreeVariable(Local element) { |
| 358 assert(freeVariableMap[element] == null); | 364 assert(freeVariableMap[element] == null); |
| 359 freeVariableMap[element] = null; | 365 freeVariableMap[element] = null; |
| 360 } | 366 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 }); | 426 }); |
| 421 } | 427 } |
| 422 } | 428 } |
| 423 | 429 |
| 424 class ClosureTranslator extends Visitor { | 430 class ClosureTranslator extends Visitor { |
| 425 final Compiler compiler; | 431 final Compiler compiler; |
| 426 final TreeElements elements; | 432 final TreeElements elements; |
| 427 int closureFieldCounter = 0; | 433 int closureFieldCounter = 0; |
| 428 int boxedFieldCounter = 0; | 434 int boxedFieldCounter = 0; |
| 429 bool inTryStatement = false; | 435 bool inTryStatement = false; |
| 436 | |
| 430 final Map<Node, ClosureClassMap> closureMappingCache; | 437 final Map<Node, ClosureClassMap> closureMappingCache; |
| 431 | 438 |
| 432 // Map of captured variables. Initially they will map to `null`. If | 439 // Map of captured variables. Initially they will map to `null`. If |
| 433 // a variable needs to be boxed then the scope declaring the variable | 440 // a variable needs to be boxed then the scope declaring the variable |
| 434 // will update this to mapping to the capturing [BoxFieldElement]. | 441 // will update this to mapping to the capturing [BoxFieldElement]. |
| 435 Map<Local, BoxFieldElement> _capturedVariableMapping = | 442 Map<Local, BoxFieldElement> _capturedVariableMapping = |
| 436 new Map<Local, BoxFieldElement>(); | 443 new Map<Local, BoxFieldElement>(); |
| 437 | 444 |
| 438 // List of encountered closures. | 445 // List of encountered closures. |
| 439 List<Expression> closures = <Expression>[]; | 446 List<Expression> closures = <Expression>[]; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 581 } | 588 } |
| 582 | 589 |
| 583 if (insideClosure && !inCurrentContext(variable)) { | 590 if (insideClosure && !inCurrentContext(variable)) { |
| 584 closureData.addFreeVariable(variable); | 591 closureData.addFreeVariable(variable); |
| 585 } else if (inTryStatement) { | 592 } else if (inTryStatement) { |
| 586 // Don't mark the this-element or a self-reference. This would complicate | 593 // Don't mark the this-element or a self-reference. This would complicate |
| 587 // things in the builder. | 594 // things in the builder. |
| 588 // Note that nested (named) functions are immutable. | 595 // Note that nested (named) functions are immutable. |
| 589 if (variable != closureData.thisLocal && | 596 if (variable != closureData.thisLocal && |
| 590 variable != closureData.closureElement) { | 597 variable != closureData.closureElement) { |
| 591 // TODO(ngeoffray): only do this if the variable is mutated. | 598 closureData.variablesUsedInTryOrGenerator.add(variable); |
| 592 closureData.usedVariablesInTry.add(variable); | |
| 593 } | 599 } |
| 600 } else if (variable is LocalParameterElement && | |
| 601 variable.functionDeclaration.asyncMarker == AsyncMarker.SYNC_STAR) { | |
| 602 // Parameters in a sync* function are shared between each Iterator created | |
| 603 // by the Iterable returned by the function, therefore they must be boxed. | |
| 604 closureData.variablesUsedInTryOrGenerator.add(variable); | |
| 594 } | 605 } |
| 595 } | 606 } |
| 596 | 607 |
| 597 void useTypeVariableAsLocal(TypeVariableType typeVariable) { | 608 void useTypeVariableAsLocal(TypeVariableType typeVariable) { |
| 598 useLocal(new TypeVariableLocal(typeVariable, outermostElement)); | 609 useLocal(new TypeVariableLocal(typeVariable, outermostElement)); |
| 599 } | 610 } |
| 600 | 611 |
| 601 void declareLocal(LocalVariableElement element) { | 612 void declareLocal(LocalVariableElement element) { |
| 602 scopeVariables.add(element); | 613 scopeVariables.add(element); |
| 603 } | 614 } |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1027 | 1038 |
| 1028 String get name => typeVariable.name; | 1039 String get name => typeVariable.name; |
| 1029 | 1040 |
| 1030 int get hashCode => typeVariable.hashCode; | 1041 int get hashCode => typeVariable.hashCode; |
| 1031 | 1042 |
| 1032 bool operator ==(other) { | 1043 bool operator ==(other) { |
| 1033 if (other is! TypeVariableLocal) return false; | 1044 if (other is! TypeVariableLocal) return false; |
| 1034 return typeVariable == other.typeVariable; | 1045 return typeVariable == other.typeVariable; |
| 1035 } | 1046 } |
| 1036 } | 1047 } |
| OLD | NEW |