| 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 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 ClosureClassMap cached = closureMappingCache[function]; | 522 ClosureClassMap cached = closureMappingCache[function]; |
| 523 if (!cached.parametersWithSentinel.containsKey(parameter)) { | 523 if (!cached.parametersWithSentinel.containsKey(parameter)) { |
| 524 SourceString parameterName = parameter.name; | 524 SourceString parameterName = parameter.name; |
| 525 String name = '${parameterName.slowToString()}_check'; | 525 String name = '${parameterName.slowToString()}_check'; |
| 526 Element newElement = new CheckVariableElement(new SourceString(name), | 526 Element newElement = new CheckVariableElement(new SourceString(name), |
| 527 parameter, | 527 parameter, |
| 528 enclosing); | 528 enclosing); |
| 529 useLocal(newElement); | 529 useLocal(newElement); |
| 530 cached.parametersWithSentinel[parameter] = newElement; | 530 cached.parametersWithSentinel[parameter] = newElement; |
| 531 } | 531 } |
| 532 } else if (node.isTypeTest) { | |
| 533 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); | |
| 534 analyzeType(type); | |
| 535 } else if (node.isTypeCast) { | |
| 536 DartType type = elements.getType(node.arguments.head); | |
| 537 analyzeType(type); | |
| 538 } | 532 } |
| 539 node.visitChildren(this); | 533 node.visitChildren(this); |
| 540 } | 534 } |
| 541 | 535 |
| 542 visitSendSet(SendSet node) { | 536 visitSendSet(SendSet node) { |
| 543 Element element = elements[node]; | 537 Element element = elements[node]; |
| 544 if (Elements.isLocal(element)) { | 538 if (Elements.isLocal(element)) { |
| 545 mutatedVariables.add(element); | 539 mutatedVariables.add(element); |
| 546 } | 540 } |
| 547 if (Elements.isLocal(element) && | 541 if (Elements.isLocal(element) && |
| 548 element.computeType(compiler).containsTypeVariables) { | 542 element.computeType(compiler).containsTypeVariables) { |
| 549 registerNeedsThis(); | 543 registerNeedsThis(); |
| 550 } | 544 } |
| 551 super.visitSendSet(node); | 545 super.visitSendSet(node); |
| 552 } | 546 } |
| 553 | 547 |
| 554 visitNewExpression(NewExpression node) { | 548 visitNewExpression(NewExpression node) { |
| 555 DartType type = elements.getType(node); | 549 DartType type = elements.getType(node); |
| 556 analyzeType(type); | |
| 557 node.visitChildren(this); | |
| 558 } | |
| 559 | 550 |
| 560 void analyzeTypeVariables(DartType type) { | 551 void analyzeTypeVariables(DartType type) { |
| 561 type.forEachTypeVariable((TypeVariableType typeVariable) { | 552 if (type is TypeVariableType) { |
| 562 useLocal(typeVariable.element); | 553 useLocal(type.element); |
| 563 // Field initializers are inlined and access the type variable as | 554 // Field initializers are inlined and access the type variable as |
| 564 // normal parameters. | 555 // normal parameters. |
| 565 if (!outermostElement.isField()) { | 556 if (!outermostElement.isField()) { |
| 566 registerNeedsThis(); | 557 registerNeedsThis(); |
| 558 } |
| 559 } else if (type is InterfaceType) { |
| 560 InterfaceType ifcType = type; |
| 561 for (DartType argument in ifcType.typeArguments) { |
| 562 analyzeTypeVariables(argument); |
| 563 } |
| 567 } | 564 } |
| 568 }); | 565 } |
| 569 } | |
| 570 | 566 |
| 571 void analyzeType(DartType type) { | |
| 572 // TODO(johnniwinther): Find out why this can be null. | |
| 573 if (type == null) return; | |
| 574 if (outermostElement.isMember() && | 567 if (outermostElement.isMember() && |
| 575 compiler.backend.classNeedsRti(outermostElement.getEnclosingClass())) { | 568 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { |
| 576 if (outermostElement.isConstructor() || | 569 if (outermostElement.isConstructor() || outermostElement.isField()) { |
| 577 outermostElement.isField()) { | |
| 578 analyzeTypeVariables(type); | 570 analyzeTypeVariables(type); |
| 579 } else if (outermostElement.isInstanceMember()) { | 571 } else if (outermostElement.isInstanceMember()) { |
| 580 if (type.containsTypeVariables) { | 572 if (type.containsTypeVariables) { |
| 581 registerNeedsThis(); | 573 registerNeedsThis(); |
| 582 } | 574 } |
| 583 } | 575 } |
| 584 } | 576 } |
| 577 |
| 578 node.visitChildren(this); |
| 585 } | 579 } |
| 586 | 580 |
| 587 // If variables that are declared in the [node] scope are captured and need | 581 // If variables that are declared in the [node] scope are captured and need |
| 588 // to be boxed create a box-element and update the [capturingScopes] in the | 582 // to be boxed create a box-element and update the [capturingScopes] in the |
| 589 // current [closureData]. | 583 // current [closureData]. |
| 590 // The boxed variables are updated in the [capturedVariableMapping]. | 584 // The boxed variables are updated in the [capturedVariableMapping]. |
| 591 void attachCapturedScopeVariables(Node node) { | 585 void attachCapturedScopeVariables(Node node) { |
| 592 Element box = null; | 586 Element box = null; |
| 593 Map<Element, Element> scopeMapping = new Map<Element, Element>(); | 587 Map<Element, Element> scopeMapping = new Map<Element, Element>(); |
| 594 for (Element element in scopeVariables) { | 588 for (Element element in scopeVariables) { |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 } | 727 } |
| 734 // If we are inside a named closure we have to declare ourselve. For | 728 // If we are inside a named closure we have to declare ourselve. For |
| 735 // simplicity we declare the local even if the closure does not have a | 729 // simplicity we declare the local even if the closure does not have a |
| 736 // name. | 730 // name. |
| 737 // It will simply not be used. | 731 // It will simply not be used. |
| 738 if (insideClosure) { | 732 if (insideClosure) { |
| 739 declareLocal(element); | 733 declareLocal(element); |
| 740 } | 734 } |
| 741 | 735 |
| 742 if (currentElement.isFactoryConstructor() && | 736 if (currentElement.isFactoryConstructor() && |
| 743 compiler.backend.classNeedsRti(currentElement.enclosingElement)) { | 737 compiler.backend.needsRti(currentElement.enclosingElement)) { |
| 744 // Declare the type parameters in the scope. Generative | 738 // Declare the type parameters in the scope. Generative |
| 745 // constructors just use 'this'. | 739 // constructors just use 'this'. |
| 746 ClassElement cls = currentElement.enclosingElement; | 740 ClassElement cls = currentElement.enclosingElement; |
| 747 cls.typeVariables.forEach((TypeVariableType typeVariable) { | 741 cls.typeVariables.forEach((TypeVariableType typeVariable) { |
| 748 declareLocal(typeVariable.element); | 742 declareLocal(typeVariable.element); |
| 749 }); | 743 }); |
| 750 } | 744 } |
| 751 | 745 |
| 752 DartType type = element.computeType(compiler); | |
| 753 // Compute the function type and check for type variables in return or | 746 // Compute the function type and check for type variables in return or |
| 754 // parameter types. | 747 // parameter types. |
| 755 if (type.containsTypeVariables) { | 748 if (element.computeType(compiler).containsTypeVariables) { |
| 756 registerNeedsThis(); | |
| 757 } | |
| 758 // Ensure that closure that need runtime type information has access to | |
| 759 // this of the enclosing class. | |
| 760 if (element is FunctionElement && | |
| 761 closureData.thisElement != null && | |
| 762 type.containsTypeVariables && | |
| 763 compiler.backend.methodNeedsRti(element)) { | |
| 764 registerNeedsThis(); | 749 registerNeedsThis(); |
| 765 } | 750 } |
| 766 | 751 |
| 767 visitChildren(); | 752 visitChildren(); |
| 768 }); | 753 }); |
| 769 | 754 |
| 770 | 755 |
| 771 ClosureClassMap savedClosureData = closureData; | 756 ClosureClassMap savedClosureData = closureData; |
| 772 bool savedInsideClosure = insideClosure; | 757 bool savedInsideClosure = insideClosure; |
| 773 | 758 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 814 } | 799 } |
| 815 | 800 |
| 816 visitTryStatement(TryStatement node) { | 801 visitTryStatement(TryStatement node) { |
| 817 // TODO(ngeoffray): implement finer grain state. | 802 // TODO(ngeoffray): implement finer grain state. |
| 818 bool oldInTryStatement = inTryStatement; | 803 bool oldInTryStatement = inTryStatement; |
| 819 inTryStatement = true; | 804 inTryStatement = true; |
| 820 node.visitChildren(this); | 805 node.visitChildren(this); |
| 821 inTryStatement = oldInTryStatement; | 806 inTryStatement = oldInTryStatement; |
| 822 } | 807 } |
| 823 } | 808 } |
| OLD | NEW |