| 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 "scanner/scannerlib.dart" show Token; | 10 import "scanner/scannerlib.dart" show Token; |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 ClosureClassMap cached = closureMappingCache[function]; | 516 ClosureClassMap cached = closureMappingCache[function]; |
| 517 if (!cached.parametersWithSentinel.containsKey(parameter)) { | 517 if (!cached.parametersWithSentinel.containsKey(parameter)) { |
| 518 SourceString parameterName = parameter.name; | 518 SourceString parameterName = parameter.name; |
| 519 String name = '${parameterName.slowToString()}_check'; | 519 String name = '${parameterName.slowToString()}_check'; |
| 520 Element newElement = new CheckVariableElement(new SourceString(name), | 520 Element newElement = new CheckVariableElement(new SourceString(name), |
| 521 parameter, | 521 parameter, |
| 522 enclosing); | 522 enclosing); |
| 523 useLocal(newElement); | 523 useLocal(newElement); |
| 524 cached.parametersWithSentinel[parameter] = newElement; | 524 cached.parametersWithSentinel[parameter] = newElement; |
| 525 } | 525 } |
| 526 } else if (node.isOperator) { |
| 527 String operatorString = node.selector.asOperator().source.stringValue; |
| 528 if (operatorString == 'is' || operatorString == 'as') { |
| 529 DartType type = elements.getType(node.arguments.head); |
| 530 analyzeType(type); |
| 531 } |
| 526 } | 532 } |
| 527 node.visitChildren(this); | 533 node.visitChildren(this); |
| 528 } | 534 } |
| 529 | 535 |
| 530 visitSendSet(SendSet node) { | 536 visitSendSet(SendSet node) { |
| 531 Element element = elements[node]; | 537 Element element = elements[node]; |
| 532 if (Elements.isLocal(element)) { | 538 if (Elements.isLocal(element)) { |
| 533 mutatedVariables.add(element); | 539 mutatedVariables.add(element); |
| 534 } | 540 } |
| 535 if (Elements.isLocal(element) && | 541 if (Elements.isLocal(element) && |
| 536 element.computeType(compiler).containsTypeVariables) { | 542 element.computeType(compiler).containsTypeVariables) { |
| 537 registerNeedsThis(); | 543 registerNeedsThis(); |
| 538 } | 544 } |
| 539 super.visitSendSet(node); | 545 super.visitSendSet(node); |
| 540 } | 546 } |
| 541 | 547 |
| 542 visitNewExpression(NewExpression node) { | 548 visitNewExpression(NewExpression node) { |
| 543 DartType type = elements.getType(node); | 549 DartType type = elements.getType(node); |
| 550 analyzeType(type); |
| 551 node.visitChildren(this); |
| 552 } |
| 544 | 553 |
| 545 bool hasTypeVariable(DartType type) { | 554 void analyzeTypeVariables(DartType type) { |
| 546 if (type is TypeVariableType) { | 555 type.forEachTypeVariable((TypeVariableType typeVariable) { |
| 547 return true; | 556 useLocal(typeVariable.element); |
| 548 } else if (type is InterfaceType) { | 557 }); |
| 549 InterfaceType ifcType = type; | 558 } |
| 550 for (DartType argument in ifcType.typeArguments) { | |
| 551 if (hasTypeVariable(argument)) { | |
| 552 return true; | |
| 553 } | |
| 554 } | |
| 555 } | |
| 556 return false; | |
| 557 } | |
| 558 | 559 |
| 559 void analyzeTypeVariables(DartType type) { | 560 void analyzeType(DartType type) { |
| 560 if (type is TypeVariableType) { | 561 if (type == null) return; |
| 561 useLocal(type.element); | |
| 562 } else if (type is InterfaceType) { | |
| 563 InterfaceType ifcType = type; | |
| 564 for (DartType argument in ifcType.typeArguments) { | |
| 565 analyzeTypeVariables(argument); | |
| 566 } | |
| 567 } | |
| 568 } | |
| 569 | |
| 570 if (outermostElement.isMember() && | 562 if (outermostElement.isMember() && |
| 571 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { | 563 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { |
| 572 if (outermostElement.isConstructor() || outermostElement.isField()) { | 564 if (outermostElement.isConstructor() || |
| 565 outermostElement.isField()) { |
| 573 analyzeTypeVariables(type); | 566 analyzeTypeVariables(type); |
| 574 } else if (outermostElement.isInstanceMember()) { | 567 } else if (outermostElement.isInstanceMember()) { |
| 575 if (hasTypeVariable(type)) { | 568 if (type.containsTypeVariables) { |
| 576 registerNeedsThis(); | 569 registerNeedsThis(); |
| 577 } | 570 } |
| 578 } | 571 } |
| 579 } | 572 } |
| 580 | |
| 581 node.visitChildren(this); | |
| 582 } | 573 } |
| 583 | 574 |
| 584 // If variables that are declared in the [node] scope are captured and need | 575 // If variables that are declared in the [node] scope are captured and need |
| 585 // to be boxed create a box-element and update the [capturingScopes] in the | 576 // to be boxed create a box-element and update the [capturingScopes] in the |
| 586 // current [closureData]. | 577 // current [closureData]. |
| 587 // The boxed variables are updated in the [capturedVariableMapping]. | 578 // The boxed variables are updated in the [capturedVariableMapping]. |
| 588 void attachCapturedScopeVariables(Node node) { | 579 void attachCapturedScopeVariables(Node node) { |
| 589 Element box = null; | 580 Element box = null; |
| 590 Map<Element, Element> scopeMapping = new Map<Element, Element>(); | 581 Map<Element, Element> scopeMapping = new Map<Element, Element>(); |
| 591 for (Element element in scopeVariables) { | 582 for (Element element in scopeVariables) { |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 cls.typeVariables.forEach((TypeVariableType typeVariable) { | 735 cls.typeVariables.forEach((TypeVariableType typeVariable) { |
| 745 declareLocal(typeVariable.element); | 736 declareLocal(typeVariable.element); |
| 746 }); | 737 }); |
| 747 } | 738 } |
| 748 | 739 |
| 749 // Compute the function type and check for type variables in return or | 740 // Compute the function type and check for type variables in return or |
| 750 // parameter types. | 741 // parameter types. |
| 751 if (element.computeType(compiler).containsTypeVariables) { | 742 if (element.computeType(compiler).containsTypeVariables) { |
| 752 registerNeedsThis(); | 743 registerNeedsThis(); |
| 753 } | 744 } |
| 745 // Ensure that closure that need runtime type information has access to |
| 746 // this of the enclosing class. |
| 747 if (closureData.thisElement != null && |
| 748 compiler.backend.methodNeedsRti(element)) { |
| 749 registerNeedsThis(); |
| 750 } |
| 754 | 751 |
| 755 visitChildren(); | 752 visitChildren(); |
| 756 }); | 753 }); |
| 757 | 754 |
| 758 | 755 |
| 759 ClosureClassMap savedClosureData = closureData; | 756 ClosureClassMap savedClosureData = closureData; |
| 760 bool savedInsideClosure = insideClosure; | 757 bool savedInsideClosure = insideClosure; |
| 761 | 758 |
| 762 // Restore old values. | 759 // Restore old values. |
| 763 insideClosure = oldInsideClosure; | 760 insideClosure = oldInsideClosure; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 802 } | 799 } |
| 803 | 800 |
| 804 visitTryStatement(TryStatement node) { | 801 visitTryStatement(TryStatement node) { |
| 805 // TODO(ngeoffray): implement finer grain state. | 802 // TODO(ngeoffray): implement finer grain state. |
| 806 bool oldInTryStatement = inTryStatement; | 803 bool oldInTryStatement = inTryStatement; |
| 807 inTryStatement = true; | 804 inTryStatement = true; |
| 808 node.visitChildren(this); | 805 node.visitChildren(this); |
| 809 inTryStatement = oldInTryStatement; | 806 inTryStatement = oldInTryStatement; |
| 810 } | 807 } |
| 811 } | 808 } |
| OLD | NEW |