| 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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 | 117 |
| 118 Expression plug(Expression expr) { | 118 Expression plug(Expression expr) { |
| 119 assert(body == null); | 119 assert(body == null); |
| 120 return body = expr; | 120 return body = expr; |
| 121 } | 121 } |
| 122 | 122 |
| 123 accept(Visitor visitor) => visitor.visitLetPrim(this); | 123 accept(Visitor visitor) => visitor.visitLetPrim(this); |
| 124 } | 124 } |
| 125 | 125 |
| 126 | 126 |
| 127 /// Binding continuations. | 127 /// Binding a continuation: 'let cont k(v) = E in E'. The bound continuation |
| 128 /// | 128 /// is in scope in the body and the continuation parameter is in scope in the |
| 129 /// let cont k0(v0 ...) = E0 | 129 /// continuation body. |
| 130 /// k1(v1 ...) = E1 | 130 /// During one-pass construction a LetCont with an empty continuation body is |
| 131 /// ... | 131 /// used to represent the one-level context 'let cont k(v) = [] in E'. |
| 132 /// in E | |
| 133 /// | |
| 134 /// The bound continuations are in scope in the body and the continuation | |
| 135 /// parameters are in scope in the respective continuation bodies. | |
| 136 /// During one-pass construction a LetCont whose first continuation has an empty | |
| 137 /// body is used to represent the one-level context | |
| 138 /// 'let cont ... k(v) = [] ... in E'. | |
| 139 class LetCont extends Expression implements InteriorNode { | 132 class LetCont extends Expression implements InteriorNode { |
| 140 List<Continuation> continuations; | 133 Continuation continuation; |
| 141 Expression body; | 134 Expression body; |
| 142 | 135 |
| 143 LetCont(this.continuations, this.body); | 136 LetCont(this.continuation, this.body); |
| 144 | 137 |
| 145 Expression plug(Expression expr) { | 138 Expression plug(Expression expr) { |
| 146 assert(continuations != null && | 139 assert(continuation != null && continuation.body == null); |
| 147 continuations.isNotEmpty && | 140 return continuation.body = expr; |
| 148 continuations.first.body == null); | |
| 149 return continuations.first.body = expr; | |
| 150 } | 141 } |
| 151 | 142 |
| 152 accept(Visitor visitor) => visitor.visitLetCont(this); | 143 accept(Visitor visitor) => visitor.visitLetCont(this); |
| 153 } | 144 } |
| 154 | 145 |
| 155 abstract class Invoke { | 146 abstract class Invoke { |
| 156 Selector get selector; | 147 Selector get selector; |
| 157 List<Reference<Primitive>> get arguments; | 148 List<Reference<Primitive>> get arguments; |
| 158 } | 149 } |
| 159 | 150 |
| 160 /// Represents a node with a child node, which can be accessed through the | 151 /// Represents a node with a child node, which can be accessed through the |
| 161 /// `body` member. A typical usage is when removing a node from the CPS graph: | 152 /// `body` member. A typical usage is when removing a node from the CPS graph: |
| 162 /// | 153 /// |
| 163 /// Node child = node.body; | 154 /// Node child = node.body; |
| 164 /// InteriorNode parent = node.parent; | 155 /// InteriorNode parent = node.parent; |
| 165 /// | 156 /// |
| 166 /// child.parent = parent; | 157 /// child.parent = parent; |
| 167 /// parent.body = child; | 158 /// parent.body = child; |
| 168 abstract class InteriorNode extends Node { | 159 abstract class InteriorNode implements Node { |
| 169 Expression body; | 160 Expression body; |
| 170 } | 161 } |
| 171 | 162 |
| 172 /// Invoke a static function or static field getter/setter. | 163 /// Invoke a static function or static field getter/setter. |
| 173 class InvokeStatic extends Expression implements Invoke { | 164 class InvokeStatic extends Expression implements Invoke { |
| 174 /// [FunctionElement] or [FieldElement]. | 165 /// [FunctionElement] or [FieldElement]. |
| 175 final Entity target; | 166 final Entity target; |
| 176 | 167 |
| 177 /** | 168 /** |
| 178 * The selector encodes how the function is invoked: number of positional | 169 * The selector encodes how the function is invoked: number of positional |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 accept(Visitor visitor) => visitor.visitParameter(this); | 601 accept(Visitor visitor) => visitor.visitParameter(this); |
| 611 } | 602 } |
| 612 | 603 |
| 613 /// Continuations are normally bound by 'let cont'. A continuation with one | 604 /// Continuations are normally bound by 'let cont'. A continuation with one |
| 614 /// parameter and no body is used to represent a function's return continuation. | 605 /// parameter and no body is used to represent a function's return continuation. |
| 615 /// The return continuation is bound by the Function, not by 'let cont'. | 606 /// The return continuation is bound by the Function, not by 'let cont'. |
| 616 class Continuation extends Definition<Continuation> implements InteriorNode { | 607 class Continuation extends Definition<Continuation> implements InteriorNode { |
| 617 final List<Parameter> parameters; | 608 final List<Parameter> parameters; |
| 618 Expression body = null; | 609 Expression body = null; |
| 619 | 610 |
| 620 // In addition to a parent pointer to the containing LetCont, continuations | |
| 621 // have an index into the list of continuations bound by the LetCont. This | |
| 622 // gives constant-time access to the continuation from the parent. | |
| 623 int parent_index; | |
| 624 | |
| 625 // A continuation is recursive if it has any recursive invocations. | 611 // A continuation is recursive if it has any recursive invocations. |
| 626 bool isRecursive = false; | 612 bool isRecursive = false; |
| 627 | 613 |
| 628 bool get isReturnContinuation => body == null; | 614 bool get isReturnContinuation => body == null; |
| 629 | 615 |
| 630 Continuation(this.parameters); | 616 Continuation(this.parameters); |
| 631 | 617 |
| 632 Continuation.retrn() : parameters = <Parameter>[new Parameter(null)]; | 618 Continuation.retrn() : parameters = <Parameter>[new Parameter(null)]; |
| 633 | 619 |
| 634 accept(Visitor visitor) => visitor.visitContinuation(this); | 620 accept(Visitor visitor) => visitor.visitContinuation(this); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 class ClosureVariable extends Definition { | 665 class ClosureVariable extends Definition { |
| 680 /// Body of code that declares this closure variable. | 666 /// Body of code that declares this closure variable. |
| 681 ExecutableElement host; | 667 ExecutableElement host; |
| 682 Entity hint; | 668 Entity hint; |
| 683 | 669 |
| 684 ClosureVariable(this.host, this.hint); | 670 ClosureVariable(this.host, this.hint); |
| 685 | 671 |
| 686 accept(Visitor v) => v.visitClosureVariable(this); | 672 accept(Visitor v) => v.visitClosureVariable(this); |
| 687 } | 673 } |
| 688 | 674 |
| 689 class RunnableBody extends InteriorNode { | 675 class RunnableBody implements InteriorNode { |
| 690 Expression body; | 676 Expression body; |
| 691 final Continuation returnContinuation; | 677 final Continuation returnContinuation; |
| 678 Node parent; |
| 692 RunnableBody(this.body, this.returnContinuation); | 679 RunnableBody(this.body, this.returnContinuation); |
| 693 accept(Visitor visitor) => visitor.visitRunnableBody(this); | 680 accept(Visitor visitor) => visitor.visitRunnableBody(this); |
| 694 } | 681 } |
| 695 | 682 |
| 696 /// A function definition, consisting of parameters and a body. The parameters | 683 /// A function definition, consisting of parameters and a body. The parameters |
| 697 /// include a distinguished continuation parameter. | 684 /// include a distinguished continuation parameter. |
| 698 class FunctionDefinition extends Node | 685 class FunctionDefinition extends Node |
| 699 implements ExecutableDefinition { | 686 implements ExecutableDefinition { |
| 700 final FunctionElement element; | 687 final FunctionElement element; |
| 701 /// Mixed list of [Parameter]s and [ClosureVariable]s. | 688 /// Mixed list of [Parameter]s and [ClosureVariable]s. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 728 | 715 |
| 729 /// Returns `true` if this function is abstract or external. | 716 /// Returns `true` if this function is abstract or external. |
| 730 /// | 717 /// |
| 731 /// If `true`, [body] and [returnContinuation] are `null` and [localConstants] | 718 /// If `true`, [body] and [returnContinuation] are `null` and [localConstants] |
| 732 /// is empty. | 719 /// is empty. |
| 733 bool get isAbstract => body == null; | 720 bool get isAbstract => body == null; |
| 734 } | 721 } |
| 735 | 722 |
| 736 abstract class Initializer extends Node {} | 723 abstract class Initializer extends Node {} |
| 737 | 724 |
| 738 class FieldInitializer extends Initializer { | 725 class FieldInitializer implements Initializer { |
| 739 final FieldElement element; | 726 final FieldElement element; |
| 740 final RunnableBody body; | 727 final RunnableBody body; |
| 728 Node parent; |
| 741 | 729 |
| 742 FieldInitializer(this.element, this.body); | 730 FieldInitializer(this.element, this.body); |
| 743 accept(Visitor visitor) => visitor.visitFieldInitializer(this); | 731 accept(Visitor visitor) => visitor.visitFieldInitializer(this); |
| 744 } | 732 } |
| 745 | 733 |
| 746 class SuperInitializer extends Initializer { | 734 class SuperInitializer implements Initializer { |
| 747 final ConstructorElement target; | 735 final ConstructorElement target; |
| 748 final List<RunnableBody> arguments; | 736 final List<RunnableBody> arguments; |
| 749 final Selector selector; | 737 final Selector selector; |
| 738 Node parent; |
| 750 SuperInitializer(this.target, this.arguments, this.selector); | 739 SuperInitializer(this.target, this.arguments, this.selector); |
| 751 accept(Visitor visitor) => visitor.visitSuperInitializer(this); | 740 accept(Visitor visitor) => visitor.visitSuperInitializer(this); |
| 752 } | 741 } |
| 753 | 742 |
| 754 class ConstructorDefinition extends FunctionDefinition { | 743 class ConstructorDefinition extends FunctionDefinition { |
| 755 final List<Initializer> initializers; | 744 final List<Initializer> initializers; |
| 756 | 745 |
| 757 ConstructorDefinition(ConstructorElement element, | 746 ConstructorDefinition(ConstructorElement element, |
| 758 List<Definition> parameters, | 747 List<Definition> parameters, |
| 759 RunnableBody body, | 748 RunnableBody body, |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 907 processLetPrim(LetPrim node) {} | 896 processLetPrim(LetPrim node) {} |
| 908 visitLetPrim(LetPrim node) { | 897 visitLetPrim(LetPrim node) { |
| 909 processLetPrim(node); | 898 processLetPrim(node); |
| 910 visit(node.primitive); | 899 visit(node.primitive); |
| 911 visit(node.body); | 900 visit(node.body); |
| 912 } | 901 } |
| 913 | 902 |
| 914 processLetCont(LetCont node) {} | 903 processLetCont(LetCont node) {} |
| 915 visitLetCont(LetCont node) { | 904 visitLetCont(LetCont node) { |
| 916 processLetCont(node); | 905 processLetCont(node); |
| 917 node.continuations.forEach(visit); | 906 visit(node.continuation); |
| 918 visit(node.body); | 907 visit(node.body); |
| 919 } | 908 } |
| 920 | 909 |
| 921 processInvokeStatic(InvokeStatic node) {} | 910 processInvokeStatic(InvokeStatic node) {} |
| 922 visitInvokeStatic(InvokeStatic node) { | 911 visitInvokeStatic(InvokeStatic node) { |
| 923 processInvokeStatic(node); | 912 processInvokeStatic(node); |
| 924 processReference(node.continuation); | 913 processReference(node.continuation); |
| 925 node.arguments.forEach(processReference); | 914 node.arguments.forEach(processReference); |
| 926 } | 915 } |
| 927 | 916 |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 allocate(param); | 1169 allocate(param); |
| 1181 } | 1170 } |
| 1182 } | 1171 } |
| 1183 } | 1172 } |
| 1184 | 1173 |
| 1185 void visitFieldInitializer(FieldInitializer node) { | 1174 void visitFieldInitializer(FieldInitializer node) { |
| 1186 visit(node.body.body); | 1175 visit(node.body.body); |
| 1187 } | 1176 } |
| 1188 | 1177 |
| 1189 void visitSuperInitializer(SuperInitializer node) { | 1178 void visitSuperInitializer(SuperInitializer node) { |
| 1190 node.arguments.forEach(visit); | 1179 node.arguments.forEach((RunnableBody argument) => visit(argument.body)); |
| 1191 } | 1180 } |
| 1192 | 1181 |
| 1193 void visitLetPrim(LetPrim node) { | 1182 void visitLetPrim(LetPrim node) { |
| 1194 visit(node.body); | 1183 visit(node.body); |
| 1195 release(node.primitive); | 1184 release(node.primitive); |
| 1196 visit(node.primitive); | 1185 visit(node.primitive); |
| 1197 } | 1186 } |
| 1198 | 1187 |
| 1199 void visitLetCont(LetCont node) { | 1188 void visitLetCont(LetCont node) { |
| 1200 node.continuations.forEach(visit); | 1189 visit(node.continuation); |
| 1201 visit(node.body); | 1190 visit(node.body); |
| 1202 } | 1191 } |
| 1203 | 1192 |
| 1204 void visitInvokeStatic(InvokeStatic node) { | 1193 void visitInvokeStatic(InvokeStatic node) { |
| 1205 node.arguments.forEach(visitReference); | 1194 node.arguments.forEach(visitReference); |
| 1206 } | 1195 } |
| 1207 | 1196 |
| 1208 void visitInvokeContinuation(InvokeContinuation node) { | 1197 void visitInvokeContinuation(InvokeContinuation node) { |
| 1209 node.arguments.forEach(visitReference); | 1198 node.arguments.forEach(visitReference); |
| 1210 } | 1199 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1311 | 1300 |
| 1312 void visitIdentical(Identical node) { | 1301 void visitIdentical(Identical node) { |
| 1313 visitReference(node.left); | 1302 visitReference(node.left); |
| 1314 visitReference(node.right); | 1303 visitReference(node.right); |
| 1315 } | 1304 } |
| 1316 | 1305 |
| 1317 void visitInterceptor(Interceptor node) { | 1306 void visitInterceptor(Interceptor node) { |
| 1318 visitReference(node.input); | 1307 visitReference(node.input); |
| 1319 } | 1308 } |
| 1320 } | 1309 } |
| OLD | NEW |