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