| 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; |
| 11 import '../cps_ir/optimizers.dart'; | 11 import '../cps_ir/optimizers.dart'; |
| 12 import '../dart_types.dart' show DartType, GenericType; | 12 import '../dart_types.dart' show DartType, GenericType; |
| 13 import '../dart2jslib.dart' as dart2js show invariant; | 13 import '../dart2jslib.dart' as dart2js show |
| 14 CURRENT_ELEMENT_SPANNABLE, |
| 15 InternalErrorFunction, |
| 16 invariant; |
| 14 import '../elements/elements.dart'; | 17 import '../elements/elements.dart'; |
| 15 import '../io/source_information.dart' show SourceInformation; | 18 import '../io/source_information.dart' show SourceInformation; |
| 16 import '../universe/universe.dart' show Selector, SelectorKind; | 19 import '../universe/universe.dart' show Selector, SelectorKind; |
| 17 | 20 |
| 18 abstract class Node { | 21 abstract class Node { |
| 19 /// A pointer to the parent node. Is null until set by optimization passes. | 22 /// A pointer to the parent node. Is null until set by optimization passes. |
| 20 Node parent; | 23 Node parent; |
| 21 | 24 |
| 22 accept(Visitor visitor); | 25 accept(Visitor visitor); |
| 23 } | 26 } |
| (...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 applyPass(Pass pass) => pass.rewriteConstructorDefinition(this); | 868 applyPass(Pass pass) => pass.rewriteConstructorDefinition(this); |
| 866 } | 869 } |
| 867 | 870 |
| 868 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { | 871 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |
| 869 return definitions.map((e) => new Reference<Primitive>(e)).toList(); | 872 return definitions.map((e) => new Reference<Primitive>(e)).toList(); |
| 870 } | 873 } |
| 871 | 874 |
| 872 abstract class Visitor<T> { | 875 abstract class Visitor<T> { |
| 873 const Visitor(); | 876 const Visitor(); |
| 874 | 877 |
| 875 T visit(Node node) => node.accept(this); | 878 T visit(Node node); |
| 876 // Abstract classes. | |
| 877 T visitNode(Node node) => null; | |
| 878 T visitExpression(Expression node) => visitNode(node); | |
| 879 T visitDefinition(Definition node) => visitNode(node); | |
| 880 T visitPrimitive(Primitive node) => visitDefinition(node); | |
| 881 T visitCondition(Condition node) => visitNode(node); | |
| 882 T visitRunnableBody(RunnableBody node) => visitNode(node); | |
| 883 | 879 |
| 884 // Concrete classes. | 880 // Concrete classes. |
| 885 T visitFieldDefinition(FieldDefinition node) => visitNode(node); | 881 T visitFieldDefinition(FieldDefinition node); |
| 886 T visitFunctionDefinition(FunctionDefinition node) => visitNode(node); | 882 T visitFunctionDefinition(FunctionDefinition node); |
| 887 T visitConstructorDefinition(ConstructorDefinition node) { | 883 T visitConstructorDefinition(ConstructorDefinition node); |
| 888 return visitFunctionDefinition(node); | 884 T visitRunnableBody(RunnableBody node); |
| 889 } | |
| 890 | 885 |
| 891 // Initializers | 886 // Initializers |
| 892 T visitInitializer(Initializer node) => visitNode(node); | 887 T visitFieldInitializer(FieldInitializer node); |
| 893 T visitFieldInitializer(FieldInitializer node) => visitInitializer(node); | 888 T visitSuperInitializer(SuperInitializer node); |
| 894 T visitSuperInitializer(SuperInitializer node) => visitInitializer(node); | |
| 895 | 889 |
| 896 // Expressions. | 890 // Expressions. |
| 897 T visitLetPrim(LetPrim node) => visitExpression(node); | 891 T visitLetPrim(LetPrim node); |
| 898 T visitLetCont(LetCont node) => visitExpression(node); | 892 T visitLetCont(LetCont node); |
| 899 T visitLetHandler(LetHandler node) => visitExpression(node); | 893 T visitLetHandler(LetHandler node); |
| 900 T visitLetMutable(LetMutable node) => visitExpression(node); | 894 T visitLetMutable(LetMutable node); |
| 901 T visitInvokeStatic(InvokeStatic node) => visitExpression(node); | 895 T visitInvokeContinuation(InvokeContinuation node); |
| 902 T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node); | 896 T visitInvokeStatic(InvokeStatic node); |
| 903 T visitInvokeMethod(InvokeMethod node) => visitExpression(node); | 897 T visitInvokeMethod(InvokeMethod node); |
| 904 T visitInvokeMethodDirectly(InvokeMethodDirectly node) => visitExpression(node
); | 898 T visitInvokeMethodDirectly(InvokeMethodDirectly node); |
| 905 T visitInvokeConstructor(InvokeConstructor node) => visitExpression(node); | 899 T visitInvokeConstructor(InvokeConstructor node); |
| 906 T visitConcatenateStrings(ConcatenateStrings node) => visitExpression(node); | 900 T visitConcatenateStrings(ConcatenateStrings node); |
| 907 T visitBranch(Branch node) => visitExpression(node); | 901 T visitBranch(Branch node); |
| 908 T visitTypeOperator(TypeOperator node) => visitExpression(node); | 902 T visitTypeOperator(TypeOperator node); |
| 909 T visitSetMutableVariable(SetMutableVariable node) => visitExpression(node); | 903 T visitSetMutableVariable(SetMutableVariable node); |
| 910 T visitDeclareFunction(DeclareFunction node) => visitExpression(node); | 904 T visitDeclareFunction(DeclareFunction node); |
| 911 T visitSetField(SetField node) => visitExpression(node); | |
| 912 | 905 |
| 913 // Definitions. | 906 // Definitions. |
| 914 T visitLiteralList(LiteralList node) => visitPrimitive(node); | 907 T visitLiteralList(LiteralList node); |
| 915 T visitLiteralMap(LiteralMap node) => visitPrimitive(node); | 908 T visitLiteralMap(LiteralMap node); |
| 916 T visitConstant(Constant node) => visitPrimitive(node); | 909 T visitConstant(Constant node); |
| 917 T visitThis(This node) => visitPrimitive(node); | 910 T visitThis(This node); |
| 918 T visitReifyTypeVar(ReifyTypeVar node) => visitPrimitive(node); | 911 T visitReifyTypeVar(ReifyTypeVar node); |
| 919 T visitCreateFunction(CreateFunction node) => visitPrimitive(node); | 912 T visitCreateFunction(CreateFunction node); |
| 920 T visitGetMutableVariable(GetMutableVariable node) => visitPrimitive(node); | 913 T visitGetMutableVariable(GetMutableVariable node); |
| 921 T visitParameter(Parameter node) => visitPrimitive(node); | 914 T visitParameter(Parameter node); |
| 922 T visitContinuation(Continuation node) => visitDefinition(node); | 915 T visitContinuation(Continuation node); |
| 923 T visitMutableVariable(MutableVariable node) => visitDefinition(node); | 916 T visitMutableVariable(MutableVariable node); |
| 924 T visitGetField(GetField node) => visitDefinition(node); | |
| 925 T visitCreateBox(CreateBox node) => visitDefinition(node); | |
| 926 T visitCreateInstance(CreateInstance node) => visitDefinition(node); | |
| 927 | 917 |
| 928 // Conditions. | 918 // Conditions. |
| 929 T visitIsTrue(IsTrue node) => visitCondition(node); | 919 T visitIsTrue(IsTrue node); |
| 930 | 920 |
| 931 // JavaScript specific nodes. | 921 // JavaScript specific nodes. |
| 932 T visitIdentical(Identical node) => visitPrimitive(node); | 922 // Expressions. |
| 933 T visitInterceptor(Interceptor node) => visitPrimitive(node); | 923 T visitSetField(SetField node); |
| 924 // Definitions. |
| 925 T visitIdentical(Identical node); |
| 926 T visitInterceptor(Interceptor node); |
| 927 T visitCreateInstance(CreateInstance node); |
| 928 T visitGetField(GetField node); |
| 929 T visitCreateBox(CreateBox node); |
| 934 } | 930 } |
| 935 | 931 |
| 936 /// Recursively visits the entire CPS term, and calls abstract `process*` | 932 /// Recursively visits the entire CPS term, and calls abstract `process*` |
| 937 /// (i.e. `processLetPrim`) functions in pre-order. | 933 /// (i.e. `processLetPrim`) functions in pre-order. |
| 938 abstract class RecursiveVisitor extends Visitor { | 934 class RecursiveVisitor implements Visitor { |
| 939 const RecursiveVisitor(); | 935 const RecursiveVisitor(); |
| 940 | 936 |
| 941 // Ensures that RecursiveVisitor contains overrides for all relevant nodes. | 937 visit(Node node) => node.accept(this); |
| 942 // As a rule of thumb, nodes with structure to traverse should be overridden | |
| 943 // with the appropriate visits in this class (for example, visitLetCont), | |
| 944 // while leaving other nodes for subclasses (i.e., visitLiteralList). | |
| 945 visitNode(Node node) { | |
| 946 throw "$this is stale, add missing visit override for $node"; | |
| 947 } | |
| 948 | 938 |
| 949 processReference(Reference ref) {} | 939 processReference(Reference ref) {} |
| 950 | 940 |
| 951 processRunnableBody(RunnableBody node) {} | 941 processRunnableBody(RunnableBody node) {} |
| 952 visitRunnableBody(RunnableBody node) { | 942 visitRunnableBody(RunnableBody node) { |
| 953 processRunnableBody(node); | 943 processRunnableBody(node); |
| 954 visit(node.returnContinuation); | 944 visit(node.returnContinuation); |
| 955 visit(node.body); | 945 visit(node.body); |
| 956 } | 946 } |
| 957 | 947 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 976 visitConstructorDefinition(ConstructorDefinition node) { | 966 visitConstructorDefinition(ConstructorDefinition node) { |
| 977 processConstructorDefinition(node); | 967 processConstructorDefinition(node); |
| 978 node.parameters.forEach(visit); | 968 node.parameters.forEach(visit); |
| 979 node.initializers.forEach(visit); | 969 node.initializers.forEach(visit); |
| 980 visit(node.body); | 970 visit(node.body); |
| 981 } | 971 } |
| 982 | 972 |
| 983 processFieldInitializer(FieldInitializer node) {} | 973 processFieldInitializer(FieldInitializer node) {} |
| 984 visitFieldInitializer(FieldInitializer node) { | 974 visitFieldInitializer(FieldInitializer node) { |
| 985 processFieldInitializer(node); | 975 processFieldInitializer(node); |
| 986 visit(node.body.body); | 976 visit(node.body); |
| 987 } | 977 } |
| 988 | 978 |
| 989 processSuperInitializer(SuperInitializer node) {} | 979 processSuperInitializer(SuperInitializer node) {} |
| 990 visitSuperInitializer(SuperInitializer node) { | 980 visitSuperInitializer(SuperInitializer node) { |
| 991 processSuperInitializer(node); | 981 processSuperInitializer(node); |
| 992 node.arguments.forEach( | 982 node.arguments.forEach(visit); |
| 993 (RunnableBody argument) => visit(argument.body)); | |
| 994 } | 983 } |
| 995 | 984 |
| 996 // Expressions. | 985 // Expressions. |
| 997 | 986 |
| 998 processLetPrim(LetPrim node) {} | 987 processLetPrim(LetPrim node) {} |
| 999 visitLetPrim(LetPrim node) { | 988 visitLetPrim(LetPrim node) { |
| 1000 processLetPrim(node); | 989 processLetPrim(node); |
| 1001 visit(node.primitive); | 990 visit(node.primitive); |
| 1002 visit(node.body); | 991 visit(node.body); |
| 1003 } | 992 } |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1132 } | 1121 } |
| 1133 | 1122 |
| 1134 processMutableVariable(node) {} | 1123 processMutableVariable(node) {} |
| 1135 visitMutableVariable(MutableVariable node) { | 1124 visitMutableVariable(MutableVariable node) { |
| 1136 processMutableVariable(node); | 1125 processMutableVariable(node); |
| 1137 } | 1126 } |
| 1138 | 1127 |
| 1139 processGetMutableVariable(GetMutableVariable node) {} | 1128 processGetMutableVariable(GetMutableVariable node) {} |
| 1140 visitGetMutableVariable(GetMutableVariable node) { | 1129 visitGetMutableVariable(GetMutableVariable node) { |
| 1141 processGetMutableVariable(node); | 1130 processGetMutableVariable(node); |
| 1131 processReference(node.variable); |
| 1142 } | 1132 } |
| 1143 | 1133 |
| 1144 processParameter(Parameter node) {} | 1134 processParameter(Parameter node) {} |
| 1145 visitParameter(Parameter node) => processParameter(node); | 1135 visitParameter(Parameter node) => processParameter(node); |
| 1146 | 1136 |
| 1147 processContinuation(Continuation node) {} | 1137 processContinuation(Continuation node) {} |
| 1148 visitContinuation(Continuation node) { | 1138 visitContinuation(Continuation node) { |
| 1149 processContinuation(node); | 1139 processContinuation(node); |
| 1150 node.parameters.forEach(visitParameter); | 1140 node.parameters.forEach(visitParameter); |
| 1151 if (node.body != null) visit(node.body); | 1141 if (node.body != null) visit(node.body); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1217 freeStack.add(index); | 1207 freeStack.add(index); |
| 1218 } | 1208 } |
| 1219 } | 1209 } |
| 1220 | 1210 |
| 1221 /// Assigns indices to each primitive in the IR such that primitives that are | 1211 /// Assigns indices to each primitive in the IR such that primitives that are |
| 1222 /// live simultaneously never get assigned the same index. | 1212 /// live simultaneously never get assigned the same index. |
| 1223 /// This information is used by the dart tree builder to generate fewer | 1213 /// This information is used by the dart tree builder to generate fewer |
| 1224 /// redundant variables. | 1214 /// redundant variables. |
| 1225 /// Currently, the liveness analysis is very simple and is often inadequate | 1215 /// Currently, the liveness analysis is very simple and is often inadequate |
| 1226 /// for removing all of the redundant variables. | 1216 /// for removing all of the redundant variables. |
| 1227 class RegisterAllocator extends Visitor { | 1217 class RegisterAllocator implements Visitor { |
| 1218 final dart2js.InternalErrorFunction internalError; |
| 1219 |
| 1228 /// Separate register spaces for each source-level variable/parameter. | 1220 /// Separate register spaces for each source-level variable/parameter. |
| 1229 /// Note that null is used as key for primitives without hints. | 1221 /// Note that null is used as key for primitives without hints. |
| 1230 final Map<Local, RegisterArray> elementRegisters = <Local, RegisterArray>{}; | 1222 final Map<Local, RegisterArray> elementRegisters = <Local, RegisterArray>{}; |
| 1231 | 1223 |
| 1224 RegisterAllocator(this.internalError); |
| 1225 |
| 1232 RegisterArray getRegisterArray(Local local) { | 1226 RegisterArray getRegisterArray(Local local) { |
| 1233 RegisterArray registers = elementRegisters[local]; | 1227 RegisterArray registers = elementRegisters[local]; |
| 1234 if (registers == null) { | 1228 if (registers == null) { |
| 1235 registers = new RegisterArray(); | 1229 registers = new RegisterArray(); |
| 1236 elementRegisters[local] = registers; | 1230 elementRegisters[local] = registers; |
| 1237 } | 1231 } |
| 1238 return registers; | 1232 return registers; |
| 1239 } | 1233 } |
| 1240 | 1234 |
| 1241 void allocate(Primitive primitive) { | 1235 void allocate(Primitive primitive) { |
| 1242 if (primitive.registerIndex == null) { | 1236 if (primitive.registerIndex == null) { |
| 1243 primitive.registerIndex = getRegisterArray(primitive.hint).makeIndex(); | 1237 primitive.registerIndex = getRegisterArray(primitive.hint).makeIndex(); |
| 1244 } | 1238 } |
| 1245 } | 1239 } |
| 1246 | 1240 |
| 1247 void release(Primitive primitive) { | 1241 void release(Primitive primitive) { |
| 1248 // Do not share indices for temporaries as this may obstruct inlining. | 1242 // Do not share indices for temporaries as this may obstruct inlining. |
| 1249 if (primitive.hint == null) return; | 1243 if (primitive.hint == null) return; |
| 1250 if (primitive.registerIndex != null) { | 1244 if (primitive.registerIndex != null) { |
| 1251 getRegisterArray(primitive.hint).releaseIndex(primitive.registerIndex); | 1245 getRegisterArray(primitive.hint).releaseIndex(primitive.registerIndex); |
| 1252 } | 1246 } |
| 1253 } | 1247 } |
| 1254 | 1248 |
| 1249 void visit(Node node) => node.accept(this); |
| 1250 |
| 1255 void visitReference(Reference reference) { | 1251 void visitReference(Reference reference) { |
| 1256 allocate(reference.definition); | 1252 allocate(reference.definition); |
| 1257 } | 1253 } |
| 1258 | 1254 |
| 1259 void visitFieldDefinition(FieldDefinition node) { | 1255 void visitFieldDefinition(FieldDefinition node) { |
| 1260 if (node.hasInitializer) { | 1256 if (node.hasInitializer) { |
| 1261 visit(node.body); | 1257 visit(node.body); |
| 1262 } | 1258 } |
| 1263 } | 1259 } |
| 1264 | 1260 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 void visitConstant(Constant node) { | 1375 void visitConstant(Constant node) { |
| 1380 } | 1376 } |
| 1381 | 1377 |
| 1382 void visitThis(This node) { | 1378 void visitThis(This node) { |
| 1383 } | 1379 } |
| 1384 | 1380 |
| 1385 void visitReifyTypeVar(ReifyTypeVar node) { | 1381 void visitReifyTypeVar(ReifyTypeVar node) { |
| 1386 } | 1382 } |
| 1387 | 1383 |
| 1388 void visitCreateFunction(CreateFunction node) { | 1384 void visitCreateFunction(CreateFunction node) { |
| 1389 new RegisterAllocator().visit(node.definition); | 1385 new RegisterAllocator(internalError).visit(node.definition); |
| 1390 } | 1386 } |
| 1391 | 1387 |
| 1392 void visitGetMutableVariable(GetMutableVariable node) { | 1388 void visitGetMutableVariable(GetMutableVariable node) { |
| 1393 } | 1389 } |
| 1394 | 1390 |
| 1395 void visitSetMutableVariable(SetMutableVariable node) { | 1391 void visitSetMutableVariable(SetMutableVariable node) { |
| 1396 visit(node.body); | 1392 visit(node.body); |
| 1397 visitReference(node.value); | 1393 visitReference(node.value); |
| 1398 } | 1394 } |
| 1399 | 1395 |
| 1400 void visitDeclareFunction(DeclareFunction node) { | 1396 void visitDeclareFunction(DeclareFunction node) { |
| 1401 new RegisterAllocator().visit(node.definition); | 1397 new RegisterAllocator(internalError).visit(node.definition); |
| 1402 visit(node.body); | 1398 visit(node.body); |
| 1403 } | 1399 } |
| 1404 | 1400 |
| 1405 void visitParameter(Parameter node) { | 1401 void visitParameter(Parameter node) { |
| 1406 throw "Parameters should not be visited by RegisterAllocator"; | 1402 // Parameters are handled differently depending on whether they are |
| 1403 // function parameters, continuation parameters, exception handler |
| 1404 // parameters, etc. Thus we do not call visitParameter directly and |
| 1405 // handle them explicitly in their parent IR node. |
| 1406 internalError(dart2js.CURRENT_ELEMENT_SPANNABLE, |
| 1407 'tried to allocate a parameter'); |
| 1407 } | 1408 } |
| 1408 | 1409 |
| 1410 void visitMutableVariable(MutableVariable node) {} |
| 1411 |
| 1409 void visitContinuation(Continuation node) { | 1412 void visitContinuation(Continuation node) { |
| 1410 visit(node.body); | 1413 visit(node.body); |
| 1411 | 1414 |
| 1412 // Arguments get allocated left-to-right, so we release parameters | 1415 // Arguments get allocated left-to-right, so we release parameters |
| 1413 // right-to-left. This increases the likelihood that arguments can be | 1416 // right-to-left. This increases the likelihood that arguments can be |
| 1414 // transferred without intermediate assignments. | 1417 // transferred without intermediate assignments. |
| 1415 for (int i = node.parameters.length - 1; i >= 0; --i) { | 1418 for (int i = node.parameters.length - 1; i >= 0; --i) { |
| 1416 release(node.parameters[i]); | 1419 release(node.parameters[i]); |
| 1417 } | 1420 } |
| 1418 } | 1421 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1442 | 1445 |
| 1443 void visitIdentical(Identical node) { | 1446 void visitIdentical(Identical node) { |
| 1444 visitReference(node.left); | 1447 visitReference(node.left); |
| 1445 visitReference(node.right); | 1448 visitReference(node.right); |
| 1446 } | 1449 } |
| 1447 | 1450 |
| 1448 void visitInterceptor(Interceptor node) { | 1451 void visitInterceptor(Interceptor node) { |
| 1449 visitReference(node.input); | 1452 visitReference(node.input); |
| 1450 } | 1453 } |
| 1451 } | 1454 } |
| OLD | NEW |