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 |