| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 // IrNodes are kept in a separate library to have precise control over their | 5 // IrNodes are kept in a separate library to have precise control over their |
| 6 // dependencies on other parts of the system. | 6 // dependencies on other parts of the system. |
| 7 library dart2js.ir_nodes; | 7 library dart2js.ir_nodes; |
| 8 | 8 |
| 9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
| 10 import '../constants/values.dart' as values show ConstantValue; | 10 import '../constants/values.dart' as values show ConstantValue; |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 bool get isReturnContinuation => body == null; | 542 bool get isReturnContinuation => body == null; |
| 543 | 543 |
| 544 Continuation(this.parameters); | 544 Continuation(this.parameters); |
| 545 | 545 |
| 546 Continuation.retrn() : parameters = <Parameter>[new Parameter(null)]; | 546 Continuation.retrn() : parameters = <Parameter>[new Parameter(null)]; |
| 547 | 547 |
| 548 accept(Visitor visitor) => visitor.visitContinuation(this); | 548 accept(Visitor visitor) => visitor.visitContinuation(this); |
| 549 } | 549 } |
| 550 | 550 |
| 551 abstract class ExecutableDefinition implements Node { | 551 abstract class ExecutableDefinition implements Node { |
| 552 Expression get body; | 552 RunnableBody get body; |
| 553 | 553 |
| 554 applyPass(Pass pass); | 554 applyPass(Pass pass); |
| 555 } | 555 } |
| 556 | 556 |
| 557 // This is basically a function definition with an empty parameter list and a | 557 // This is basically a function definition with an empty parameter list and a |
| 558 // field element instead of a function element and no const declarations, and | 558 // field element instead of a function element and no const declarations, and |
| 559 // never a getter or setter, though that's less important. | 559 // never a getter or setter, though that's less important. |
| 560 class FieldDefinition extends Node | 560 class FieldDefinition extends Node implements ExecutableDefinition { |
| 561 implements InteriorNode, ExecutableDefinition { | |
| 562 final FieldElement element; | 561 final FieldElement element; |
| 563 final Continuation returnContinuation; | 562 RunnableBody body; |
| 564 Expression body; | |
| 565 | 563 |
| 566 FieldDefinition(this.element, this.returnContinuation, this.body); | 564 FieldDefinition(this.element, this.body); |
| 567 | 565 |
| 568 FieldDefinition.withoutInitializer(this.element) | 566 FieldDefinition.withoutInitializer(this.element) |
| 569 : this.returnContinuation = null; | 567 : this.body = null; |
| 570 | 568 |
| 571 accept(Visitor visitor) => visitor.visitFieldDefinition(this); | 569 accept(Visitor visitor) => visitor.visitFieldDefinition(this); |
| 572 applyPass(Pass pass) => pass.rewriteFieldDefinition(this); | 570 applyPass(Pass pass) => pass.rewriteFieldDefinition(this); |
| 573 | 571 |
| 574 /// `true` if this field has no initializer. | 572 /// `true` if this field has no initializer. |
| 575 /// | 573 /// |
| 576 /// If `true` [body] and [returnContinuation] are `null`. | 574 /// If `true` [body] and [returnContinuation] are `null`. |
| 577 /// | 575 /// |
| 578 /// This is different from a initializer that is `null`. Consider this class: | 576 /// This is different from a initializer that is `null`. Consider this class: |
| 579 /// | 577 /// |
| (...skipping 15 matching lines...) Expand all Loading... |
| 595 class ClosureVariable extends Definition { | 593 class ClosureVariable extends Definition { |
| 596 /// Body of code that declares this closure variable. | 594 /// Body of code that declares this closure variable. |
| 597 ExecutableElement host; | 595 ExecutableElement host; |
| 598 Entity hint; | 596 Entity hint; |
| 599 | 597 |
| 600 ClosureVariable(this.host, this.hint); | 598 ClosureVariable(this.host, this.hint); |
| 601 | 599 |
| 602 accept(Visitor v) => v.visitClosureVariable(this); | 600 accept(Visitor v) => v.visitClosureVariable(this); |
| 603 } | 601 } |
| 604 | 602 |
| 603 class RunnableBody implements InteriorNode { |
| 604 Expression body; |
| 605 final Continuation returnContinuation; |
| 606 Node parent; |
| 607 RunnableBody(this.body, this.returnContinuation); |
| 608 accept(Visitor visitor) => visitor.visitRunnableBody(this); |
| 609 } |
| 610 |
| 605 /// A function definition, consisting of parameters and a body. The parameters | 611 /// A function definition, consisting of parameters and a body. The parameters |
| 606 /// include a distinguished continuation parameter. | 612 /// include a distinguished continuation parameter. |
| 607 class FunctionDefinition extends Node | 613 class FunctionDefinition extends Node |
| 608 implements InteriorNode, ExecutableDefinition { | 614 implements ExecutableDefinition { |
| 609 final FunctionElement element; | 615 final FunctionElement element; |
| 610 final Continuation returnContinuation; | |
| 611 /// Mixed list of [Parameter]s and [ClosureVariable]s. | 616 /// Mixed list of [Parameter]s and [ClosureVariable]s. |
| 612 final List<Definition> parameters; | 617 final List<Definition> parameters; |
| 613 Expression body; | 618 final RunnableBody body; |
| 614 final List<ConstDeclaration> localConstants; | 619 final List<ConstDeclaration> localConstants; |
| 615 | 620 |
| 616 /// Values for optional parameters. | 621 /// Values for optional parameters. |
| 617 final List<ConstantExpression> defaultParameterValues; | 622 final List<ConstantExpression> defaultParameterValues; |
| 618 | 623 |
| 619 /// Closure variables declared by this function. | 624 /// Closure variables declared by this function. |
| 620 final List<ClosureVariable> closureVariables; | 625 final List<ClosureVariable> closureVariables; |
| 621 | 626 |
| 622 FunctionDefinition(this.element, this.returnContinuation, | 627 FunctionDefinition(this.element, |
| 623 this.parameters, this.body, this.localConstants, | 628 this.parameters, |
| 624 this.defaultParameterValues, this.closureVariables); | 629 this.body, |
| 630 this.localConstants, |
| 631 this.defaultParameterValues, |
| 632 this.closureVariables); |
| 625 | 633 |
| 626 FunctionDefinition.abstract(this.element, | 634 FunctionDefinition.abstract(this.element, |
| 627 this.parameters, | 635 this.parameters, |
| 628 this.defaultParameterValues) | 636 this.defaultParameterValues) |
| 629 : this.returnContinuation = null, | 637 : body = null, |
| 630 this.localConstants = const <ConstDeclaration>[], | 638 localConstants = const <ConstDeclaration>[], |
| 631 this.closureVariables = const <ClosureVariable>[]; | 639 closureVariables = const <ClosureVariable>[]; |
| 632 | 640 |
| 633 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); | 641 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); |
| 634 applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); | 642 applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); |
| 635 | 643 |
| 636 /// Returns `true` if this function is abstract or external. | 644 /// Returns `true` if this function is abstract or external. |
| 637 /// | 645 /// |
| 638 /// If `true`, [body] and [returnContinuation] are `null` and [localConstants] | 646 /// If `true`, [body] and [returnContinuation] are `null` and [localConstants] |
| 639 /// is empty. | 647 /// is empty. |
| 640 bool get isAbstract => body == null; | 648 bool get isAbstract => body == null; |
| 641 } | 649 } |
| 642 | 650 |
| 651 abstract class Initializer extends Node {} |
| 652 |
| 653 class FieldInitializer implements Initializer { |
| 654 final FieldElement element; |
| 655 final RunnableBody body; |
| 656 Node parent; |
| 657 |
| 658 FieldInitializer(this.element, this.body); |
| 659 accept(Visitor visitor) => visitor.visitFieldInitializer(this); |
| 660 } |
| 661 |
| 662 class SuperInitializer implements Initializer { |
| 663 final ConstructorElement target; |
| 664 final List<RunnableBody> arguments; |
| 665 final Selector selector; |
| 666 Node parent; |
| 667 SuperInitializer(this.target, this.arguments, this.selector); |
| 668 accept(Visitor visitor) => visitor.visitSuperInitializer(this); |
| 669 } |
| 670 |
| 671 class ConstructorDefinition extends FunctionDefinition { |
| 672 final List<Initializer> initializers; |
| 673 |
| 674 ConstructorDefinition(ConstructorElement element, |
| 675 List<Definition> parameters, |
| 676 RunnableBody body, |
| 677 this.initializers, |
| 678 List<ConstDeclaration> localConstants, |
| 679 List<ConstantExpression> defaultParameterValues, |
| 680 List<ClosureVariable> closureVariables) |
| 681 : super(element, parameters, body, localConstants, |
| 682 defaultParameterValues, closureVariables); |
| 683 |
| 684 // 'Abstract' here means "has no body" and is used to represent external |
| 685 // constructors. |
| 686 ConstructorDefinition.abstract( |
| 687 ConstructorElement element, |
| 688 List<Parameter> parameters, |
| 689 List<ConstantExpression> defaultParameterValues) |
| 690 : initializers = null, |
| 691 super.abstract(element, parameters, defaultParameterValues); |
| 692 |
| 693 accept(Visitor visitor) => visitor.visitConstructorDefinition(this); |
| 694 applyPass(Pass pass) => pass.rewriteConstructorDefinition(this); |
| 695 } |
| 696 |
| 643 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { | 697 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |
| 644 return definitions.map((e) => new Reference<Primitive>(e)).toList(); | 698 return definitions.map((e) => new Reference<Primitive>(e)).toList(); |
| 645 } | 699 } |
| 646 | 700 |
| 647 abstract class Visitor<T> { | 701 abstract class Visitor<T> { |
| 648 const Visitor(); | 702 const Visitor(); |
| 649 | 703 |
| 650 T visit(Node node) => node.accept(this); | 704 T visit(Node node) => node.accept(this); |
| 651 // Abstract classes. | 705 // Abstract classes. |
| 652 T visitNode(Node node) => null; | 706 T visitNode(Node node) => null; |
| 653 T visitExpression(Expression node) => visitNode(node); | 707 T visitExpression(Expression node) => visitNode(node); |
| 654 T visitDefinition(Definition node) => visitNode(node); | 708 T visitDefinition(Definition node) => visitNode(node); |
| 655 T visitPrimitive(Primitive node) => visitDefinition(node); | 709 T visitPrimitive(Primitive node) => visitDefinition(node); |
| 656 T visitCondition(Condition node) => visitNode(node); | 710 T visitCondition(Condition node) => visitNode(node); |
| 711 T visitRunnableBody(RunnableBody node) => visitNode(node); |
| 657 | 712 |
| 658 // Concrete classes. | 713 // Concrete classes. |
| 659 T visitFieldDefinition(FieldDefinition node) => visitNode(node); | 714 T visitFieldDefinition(FieldDefinition node) => visitNode(node); |
| 660 T visitFunctionDefinition(FunctionDefinition node) => visitNode(node); | 715 T visitFunctionDefinition(FunctionDefinition node) => visitNode(node); |
| 716 T visitConstructorDefinition(ConstructorDefinition node) { |
| 717 return visitFunctionDefinition(node); |
| 718 } |
| 719 |
| 720 // Initializers |
| 721 T visitInitializer(Initializer node) => visitNode(node); |
| 722 T visitFieldInitializer(FieldInitializer node) => visitInitializer(node); |
| 723 T visitSuperInitializer(SuperInitializer node) => visitInitializer(node); |
| 661 | 724 |
| 662 // Expressions. | 725 // Expressions. |
| 663 T visitLetPrim(LetPrim node) => visitExpression(node); | 726 T visitLetPrim(LetPrim node) => visitExpression(node); |
| 664 T visitLetCont(LetCont node) => visitExpression(node); | 727 T visitLetCont(LetCont node) => visitExpression(node); |
| 665 T visitInvokeStatic(InvokeStatic node) => visitExpression(node); | 728 T visitInvokeStatic(InvokeStatic node) => visitExpression(node); |
| 666 T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node); | 729 T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node); |
| 667 T visitInvokeMethod(InvokeMethod node) => visitExpression(node); | 730 T visitInvokeMethod(InvokeMethod node) => visitExpression(node); |
| 668 T visitInvokeSuperMethod(InvokeSuperMethod node) => visitExpression(node); | 731 T visitInvokeSuperMethod(InvokeSuperMethod node) => visitExpression(node); |
| 669 T visitInvokeConstructor(InvokeConstructor node) => visitExpression(node); | 732 T visitInvokeConstructor(InvokeConstructor node) => visitExpression(node); |
| 670 T visitConcatenateStrings(ConcatenateStrings node) => visitExpression(node); | 733 T visitConcatenateStrings(ConcatenateStrings node) => visitExpression(node); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 695 /// Recursively visits the entire CPS term, and calls abstract `process*` | 758 /// Recursively visits the entire CPS term, and calls abstract `process*` |
| 696 /// (i.e. `processLetPrim`) functions in pre-order. | 759 /// (i.e. `processLetPrim`) functions in pre-order. |
| 697 abstract class RecursiveVisitor extends Visitor { | 760 abstract class RecursiveVisitor extends Visitor { |
| 698 const RecursiveVisitor(); | 761 const RecursiveVisitor(); |
| 699 | 762 |
| 700 // Ensures that RecursiveVisitor contains overrides for all relevant nodes. | 763 // Ensures that RecursiveVisitor contains overrides for all relevant nodes. |
| 701 // As a rule of thumb, nodes with structure to traverse should be overridden | 764 // As a rule of thumb, nodes with structure to traverse should be overridden |
| 702 // with the appropriate visits in this class (for example, visitLetCont), | 765 // with the appropriate visits in this class (for example, visitLetCont), |
| 703 // while leaving other nodes for subclasses (i.e., visitLiteralList). | 766 // while leaving other nodes for subclasses (i.e., visitLiteralList). |
| 704 visitNode(Node node) { | 767 visitNode(Node node) { |
| 705 throw "RecursiveVisitor is stale, add missing visit overrides"; | 768 throw "$this is stale, add missing visit override for $node"; |
| 706 } | 769 } |
| 707 | 770 |
| 708 processReference(Reference ref) {} | 771 processReference(Reference ref) {} |
| 709 | 772 |
| 773 processRunnableBody(RunnableBody node) {} |
| 774 visitRunnableBody(RunnableBody node) { |
| 775 processRunnableBody(node); |
| 776 visit(node.body); |
| 777 } |
| 778 |
| 710 processFieldDefinition(FieldDefinition node) {} | 779 processFieldDefinition(FieldDefinition node) {} |
| 711 visitFieldDefinition(FieldDefinition node) { | 780 visitFieldDefinition(FieldDefinition node) { |
| 712 processFieldDefinition(node); | 781 processFieldDefinition(node); |
| 713 if (node.hasInitializer) { | 782 if (node.hasInitializer) { |
| 714 visit(node.body); | 783 visit(node.body); |
| 715 } | 784 } |
| 716 } | 785 } |
| 717 | 786 |
| 718 processFunctionDefinition(FunctionDefinition node) {} | 787 processFunctionDefinition(FunctionDefinition node) {} |
| 719 visitFunctionDefinition(FunctionDefinition node) { | 788 visitFunctionDefinition(FunctionDefinition node) { |
| 720 processFunctionDefinition(node); | 789 processFunctionDefinition(node); |
| 721 node.parameters.forEach(visit); | 790 node.parameters.forEach(visit); |
| 722 if (!node.isAbstract) { | 791 if (!node.isAbstract) { |
| 723 visit(node.body); | 792 visit(node.body); |
| 724 } | 793 } |
| 725 } | 794 } |
| 726 | 795 |
| 796 processConstructorDefinition(ConstructorDefinition node) {} |
| 797 visitConstructorDefinition(ConstructorDefinition node) { |
| 798 processConstructorDefinition(node); |
| 799 node.parameters.forEach(visit); |
| 800 node.initializers.forEach(visit); |
| 801 visit(node.body); |
| 802 } |
| 803 |
| 804 processFieldInitializer(FieldInitializer node) {} |
| 805 visitFieldInitializer(FieldInitializer node) { |
| 806 processFieldInitializer(node); |
| 807 visit(node.body.body); |
| 808 } |
| 809 |
| 810 processSuperInitializer(SuperInitializer node) {} |
| 811 visitSuperInitializer(SuperInitializer node) { |
| 812 processSuperInitializer(node); |
| 813 node.arguments.forEach( |
| 814 (RunnableBody argument) => visit(argument.body)); |
| 815 } |
| 816 |
| 727 // Expressions. | 817 // Expressions. |
| 728 | 818 |
| 729 processLetPrim(LetPrim node) {} | 819 processLetPrim(LetPrim node) {} |
| 730 visitLetPrim(LetPrim node) { | 820 visitLetPrim(LetPrim node) { |
| 731 processLetPrim(node); | 821 processLetPrim(node); |
| 732 visit(node.primitive); | 822 visit(node.primitive); |
| 733 visit(node.body); | 823 visit(node.body); |
| 734 } | 824 } |
| 735 | 825 |
| 736 processLetCont(LetCont node) {} | 826 processLetCont(LetCont node) {} |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 void visitReference(Reference reference) { | 1028 void visitReference(Reference reference) { |
| 939 allocate(reference.definition); | 1029 allocate(reference.definition); |
| 940 } | 1030 } |
| 941 | 1031 |
| 942 void visitFieldDefinition(FieldDefinition node) { | 1032 void visitFieldDefinition(FieldDefinition node) { |
| 943 if (node.hasInitializer) { | 1033 if (node.hasInitializer) { |
| 944 visit(node.body); | 1034 visit(node.body); |
| 945 } | 1035 } |
| 946 } | 1036 } |
| 947 | 1037 |
| 1038 void visitRunnableBody(RunnableBody node) { |
| 1039 visit(node.body); |
| 1040 } |
| 1041 |
| 948 void visitFunctionDefinition(FunctionDefinition node) { | 1042 void visitFunctionDefinition(FunctionDefinition node) { |
| 949 if (!node.isAbstract) { | 1043 if (!node.isAbstract) { |
| 950 visit(node.body); | 1044 visit(node.body); |
| 951 } | 1045 } |
| 952 // Assign indices to unused parameters. | 1046 // Assign indices to unused parameters. |
| 953 for (Definition param in node.parameters) { | 1047 for (Definition param in node.parameters) { |
| 954 if (param is Primitive) { | 1048 if (param is Primitive) { |
| 955 allocate(param); | 1049 allocate(param); |
| 956 } | 1050 } |
| 957 } | 1051 } |
| 958 } | 1052 } |
| 959 | 1053 |
| 1054 void visitConstructorDefinition(ConstructorDefinition node) { |
| 1055 if (!node.isAbstract) { |
| 1056 node.initializers.forEach(visit); |
| 1057 visit(node.body); |
| 1058 } |
| 1059 // Assign indices to unused parameters. |
| 1060 for (Definition param in node.parameters) { |
| 1061 if (param is Primitive) { |
| 1062 allocate(param); |
| 1063 } |
| 1064 } |
| 1065 } |
| 1066 |
| 1067 void visitFieldInitializer(FieldInitializer node) { |
| 1068 visit(node.body.body); |
| 1069 } |
| 1070 |
| 1071 void visitSuperInitializer(SuperInitializer node) { |
| 1072 node.arguments.forEach((RunnableBody argument) => visit(argument.body)); |
| 1073 } |
| 1074 |
| 960 void visitLetPrim(LetPrim node) { | 1075 void visitLetPrim(LetPrim node) { |
| 961 visit(node.body); | 1076 visit(node.body); |
| 962 release(node.primitive); | 1077 release(node.primitive); |
| 963 visit(node.primitive); | 1078 visit(node.primitive); |
| 964 } | 1079 } |
| 965 | 1080 |
| 966 void visitLetCont(LetCont node) { | 1081 void visitLetCont(LetCont node) { |
| 967 visit(node.continuation); | 1082 visit(node.continuation); |
| 968 visit(node.body); | 1083 visit(node.body); |
| 969 } | 1084 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 } | 1173 } |
| 1059 | 1174 |
| 1060 // JavaScript specific nodes. | 1175 // JavaScript specific nodes. |
| 1061 | 1176 |
| 1062 void visitIdentical(Identical node) { | 1177 void visitIdentical(Identical node) { |
| 1063 visitReference(node.left); | 1178 visitReference(node.left); |
| 1064 visitReference(node.right); | 1179 visitReference(node.right); |
| 1065 } | 1180 } |
| 1066 } | 1181 } |
| 1067 | 1182 |
| OLD | NEW |