| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 class Interceptors { | 5 class Interceptors { |
| 6 Compiler compiler; | 6 Compiler compiler; |
| 7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
| 8 | 8 |
| 9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
| 10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 value = new HLiteral(null, HType.UNKNOWN); | 231 value = new HLiteral(null, HType.UNKNOWN); |
| 232 add(value); | 232 add(value); |
| 233 } | 233 } |
| 234 fieldValues.add(value); | 234 fieldValues.add(value); |
| 235 } | 235 } |
| 236 } | 236 } |
| 237 HForeignNew newObject = new HForeignNew(classElement, fieldValues); | 237 HForeignNew newObject = new HForeignNew(classElement, fieldValues); |
| 238 add(newObject); | 238 add(newObject); |
| 239 | 239 |
| 240 // Call the method body. | 240 // Call the method body. |
| 241 SourceString methodName = compiler.namer.getConstructorName(bodyElement); | 241 SourceString methodName = bodyElement.name; |
| 242 | 242 |
| 243 List bodyCallInputs = <HInstruction>[]; | 243 List bodyCallInputs = <HInstruction>[]; |
| 244 bodyCallInputs.add(newObject); | 244 bodyCallInputs.add(newObject); |
| 245 for (Link link = parameters.nodes; !link.isEmpty(); link = link.tail) { | 245 for (Link link = parameters.nodes; !link.isEmpty(); link = link.tail) { |
| 246 Link<Node> nodeLink = link.head.definitions.nodes; | 246 Link<Node> nodeLink = link.head.definitions.nodes; |
| 247 // We expect exactly one identifier. | 247 // We expect exactly one identifier. |
| 248 assert(!nodeLink.isEmpty() && nodeLink.tail.isEmpty()); | 248 assert(!nodeLink.isEmpty() && nodeLink.tail.isEmpty()); |
| 249 Node current = nodeLink.head; | 249 Node current = nodeLink.head; |
| 250 Element parameterElement = elements[current]; | 250 Element parameterElement = elements[current]; |
| 251 HInstruction currentValue = definitions[parameterElement]; | 251 HInstruction currentValue = definitions[parameterElement]; |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 addVisitedSendArgumentsToList(Link<Node> link, List<HInstruction> list) { | 898 addVisitedSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| 899 for (; !link.isEmpty(); link = link.tail) { | 899 for (; !link.isEmpty(); link = link.tail) { |
| 900 visit(link.head); | 900 visit(link.head); |
| 901 list.add(pop()); | 901 list.add(pop()); |
| 902 } | 902 } |
| 903 } | 903 } |
| 904 | 904 |
| 905 visitDynamicSend(Send node) { | 905 visitDynamicSend(Send node) { |
| 906 var inputs = <HInstruction>[]; | 906 var inputs = <HInstruction>[]; |
| 907 | 907 |
| 908 SourceString dartMethodName = node.selector.asIdentifier().source; | 908 SourceString dartMethodName; |
| 909 bool isNotEquals = false; |
| 910 if (node.isIndex && !node.arguments.tail.isEmpty()) { |
| 911 dartMethodName = Elements.constructOperatorName( |
| 912 const SourceString('operator'), |
| 913 const SourceString('[]=')); |
| 914 } else if (node.selector.asOperator() != null) { |
| 915 SourceString name = node.selector.asIdentifier().source; |
| 916 isNotEquals = name.stringValue === '!='; |
| 917 dartMethodName = Elements.constructOperatorName( |
| 918 const SourceString('operator'), |
| 919 name, |
| 920 node.argumentsNode is Prefix); |
| 921 } else { |
| 922 dartMethodName = node.selector.asIdentifier().source; |
| 923 } |
| 909 | 924 |
| 910 Element interceptor = null; | 925 Element interceptor = null; |
| 911 if (methodInterceptionEnabled) { | 926 if (methodInterceptionEnabled) { |
| 912 interceptor = interceptors.getStaticInterceptor(dartMethodName, | 927 interceptor = interceptors.getStaticInterceptor(dartMethodName, |
| 913 node.argumentCount()); | 928 node.argumentCount()); |
| 914 } | 929 } |
| 915 if (interceptor != null) { | 930 if (interceptor != null) { |
| 916 HStatic target = new HStatic(interceptor); | 931 HStatic target = new HStatic(interceptor); |
| 917 add(target); | 932 add(target); |
| 918 inputs.add(target); | 933 inputs.add(target); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 931 inputs.add(receiver); | 946 inputs.add(receiver); |
| 932 } else { | 947 } else { |
| 933 visit(node.receiver); | 948 visit(node.receiver); |
| 934 inputs.add(pop()); | 949 inputs.add(pop()); |
| 935 } | 950 } |
| 936 | 951 |
| 937 addVisitedSendArgumentsToList(node.arguments, inputs); | 952 addVisitedSendArgumentsToList(node.arguments, inputs); |
| 938 | 953 |
| 939 // The first entry in the inputs list is the receiver. | 954 // The first entry in the inputs list is the receiver. |
| 940 push(new HInvokeDynamicMethod(dartMethodName, inputs)); | 955 push(new HInvokeDynamicMethod(dartMethodName, inputs)); |
| 956 |
| 957 if (isNotEquals) { |
| 958 HNot not = new HNot(popBoolified()); |
| 959 push(not); |
| 960 } |
| 941 } | 961 } |
| 942 | 962 |
| 943 visitClosureSend(Send node) { | 963 visitClosureSend(Send node) { |
| 944 assert(node.receiver === null); | 964 assert(node.receiver === null); |
| 945 Element element = elements[node]; | 965 Element element = elements[node]; |
| 946 HInstruction closureTarget; | 966 HInstruction closureTarget; |
| 947 if (element === null) { | 967 if (element === null) { |
| 948 visit(node.selector); | 968 visit(node.selector); |
| 949 closureTarget = pop(); | 969 closureTarget = pop(); |
| 950 } else { | 970 } else { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 961 | 981 |
| 962 visitForeignSend(Send node) { | 982 visitForeignSend(Send node) { |
| 963 Identifier selector = node.selector; | 983 Identifier selector = node.selector; |
| 964 switch (selector.source.stringValue) { | 984 switch (selector.source.stringValue) { |
| 965 case "JS": | 985 case "JS": |
| 966 Link<Node> link = node.arguments; | 986 Link<Node> link = node.arguments; |
| 967 // If the invoke is on foreign code, don't visit the first | 987 // If the invoke is on foreign code, don't visit the first |
| 968 // argument, which is the type, and the second argument, | 988 // argument, which is the type, and the second argument, |
| 969 // which is the foreign code. | 989 // which is the foreign code. |
| 970 link = link.tail.tail; | 990 link = link.tail.tail; |
| 971 var inputs = <HInstruction>[]; | 991 List<HInstruction> inputs = <HInstruction>[]; |
| 972 addVisitedSendArgumentsToList(link, inputs); | 992 addVisitedSendArgumentsToList(link, inputs); |
| 973 LiteralString type = node.arguments.head; | 993 LiteralString type = node.arguments.head; |
| 974 LiteralString literal = node.arguments.tail.head; | 994 LiteralString literal = node.arguments.tail.head; |
| 975 compiler.ensure(literal is LiteralString); | 995 compiler.ensure(literal is LiteralString); |
| 976 compiler.ensure(type is LiteralString); | 996 compiler.ensure(type is LiteralString); |
| 977 compiler.ensure(literal.value.stringValue[0] == '@'); | 997 compiler.ensure(literal.value.stringValue[0] == '@'); |
| 978 push(new HForeign(unquote(literal, 1), unquote(type, 0), inputs)); | 998 push(new HForeign(unquote(literal, 1), unquote(type, 0), inputs)); |
| 979 break; | 999 break; |
| 980 case "UNINTERCEPTED": | 1000 case "UNINTERCEPTED": |
| 981 Link<Node> link = node.arguments; | 1001 Link<Node> link = node.arguments; |
| 982 if (!link.tail.isEmpty()) { | 1002 if (!link.tail.isEmpty()) { |
| 983 compiler.cancel('More than one expression in UNINTERCEPTED()'); | 1003 compiler.cancel('More than one expression in UNINTERCEPTED()'); |
| 984 } | 1004 } |
| 985 Expression expression = link.head; | 1005 Expression expression = link.head; |
| 986 disableMethodInterception(); | 1006 disableMethodInterception(); |
| 987 visit(expression); | 1007 visit(expression); |
| 988 enableMethodInterception(); | 1008 enableMethodInterception(); |
| 989 break; | 1009 break; |
| 1010 case "JS_HAS_EQUALS": |
| 1011 List<HInstruction> inputs = <HInstruction>[]; |
| 1012 if (!node.arguments.tail.isEmpty()) { |
| 1013 compiler.cancel('More than one expression in JS_HAS_EQUALS()'); |
| 1014 } |
| 1015 addVisitedSendArgumentsToList(node.arguments, inputs); |
| 1016 String name = compiler.namer.instanceMethodName( |
| 1017 Namer.OPERATOR_EQUALS, 1); |
| 1018 push(new HForeign( |
| 1019 new SourceString('\$0.$name'), const SourceString('bool'), inputs)); |
| 1020 break; |
| 990 default: | 1021 default: |
| 991 throw "Unknown foreign: ${node.selector}"; | 1022 throw "Unknown foreign: ${node.selector}"; |
| 992 } | 1023 } |
| 993 } | 1024 } |
| 994 | 1025 |
| 995 visitSuperSend(Send node) { | 1026 visitSuperSend(Send node) { |
| 996 Element element = elements[node]; | 1027 Element element = elements[node]; |
| 997 HStatic target = new HStatic(element); | 1028 HStatic target = new HStatic(element); |
| 998 HThis context = thisDefinition; | 1029 HThis context = thisDefinition; |
| 999 if (context === null) { | 1030 if (context === null) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1010 Element element = elements[node]; | 1041 Element element = elements[node]; |
| 1011 HStatic target = new HStatic(element); | 1042 HStatic target = new HStatic(element); |
| 1012 add(target); | 1043 add(target); |
| 1013 var inputs = <HInstruction>[]; | 1044 var inputs = <HInstruction>[]; |
| 1014 inputs.add(target); | 1045 inputs.add(target); |
| 1015 addVisitedSendArgumentsToList(node.arguments, inputs); | 1046 addVisitedSendArgumentsToList(node.arguments, inputs); |
| 1016 push(new HInvokeStatic(inputs)); | 1047 push(new HInvokeStatic(inputs)); |
| 1017 } | 1048 } |
| 1018 | 1049 |
| 1019 visitSend(Send node) { | 1050 visitSend(Send node) { |
| 1020 if (node.selector is Operator) { | 1051 if (node.selector is Operator && methodInterceptionEnabled) { |
| 1021 visitOperatorSend(node); | 1052 visitOperatorSend(node); |
| 1022 } else if (node.isPropertyAccess) { | 1053 } else if (node.isPropertyAccess) { |
| 1023 generateGetter(node, elements[node]); | 1054 generateGetter(node, elements[node]); |
| 1024 } else if (Elements.isClosureSend(node, elements)) { | 1055 } else if (Elements.isClosureSend(node, elements)) { |
| 1025 visitClosureSend(node); | 1056 visitClosureSend(node); |
| 1026 } else if (node.isSuperCall) { | 1057 } else if (node.isSuperCall) { |
| 1027 visitSuperSend(node); | 1058 visitSuperSend(node); |
| 1028 } else { | 1059 } else { |
| 1029 Element element = elements[node]; | 1060 Element element = elements[node]; |
| 1030 if (element === null) { | 1061 if (element === null) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1054 if (element is !VariableElement) { | 1085 if (element is !VariableElement) { |
| 1055 compiler.internalError("expected a variable", node: node); | 1086 compiler.internalError("expected a variable", node: node); |
| 1056 } | 1087 } |
| 1057 definitions[element] = value; | 1088 definitions[element] = value; |
| 1058 return value; | 1089 return value; |
| 1059 } | 1090 } |
| 1060 | 1091 |
| 1061 visitSendSet(SendSet node) { | 1092 visitSendSet(SendSet node) { |
| 1062 Operator op = node.assignmentOperator; | 1093 Operator op = node.assignmentOperator; |
| 1063 if (node.isIndex) { | 1094 if (node.isIndex) { |
| 1064 HStatic target = new HStatic(interceptors.getIndexAssignmentInterceptor())
; | 1095 if (!methodInterceptionEnabled) { |
| 1065 add(target); | 1096 assert(op.source.stringValue === '='); |
| 1066 visit(node.receiver); | 1097 visitDynamicSend(node); |
| 1067 HInstruction receiver = pop(); | |
| 1068 visit(node.argumentsNode); | |
| 1069 if (const SourceString("=") == op.source) { | |
| 1070 HInstruction value = pop(); | |
| 1071 HInstruction index = pop(); | |
| 1072 push(new HIndexAssign(target, receiver, index, value)); | |
| 1073 } else { | 1098 } else { |
| 1074 HInstruction value; | 1099 HStatic target = new HStatic( |
| 1075 HInstruction index; | 1100 interceptors.getIndexAssignmentInterceptor()); |
| 1076 bool isCompoundAssignment = op.source.stringValue.endsWith('='); | 1101 add(target); |
| 1077 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. | 1102 visit(node.receiver); |
| 1078 Element getter = elements[node.selector]; | 1103 HInstruction receiver = pop(); |
| 1079 if (isCompoundAssignment) { | 1104 visit(node.argumentsNode); |
| 1080 value = pop(); | 1105 if (const SourceString("=") == op.source) { |
| 1081 index = pop(); | 1106 HInstruction value = pop(); |
| 1107 HInstruction index = pop(); |
| 1108 push(new HIndexAssign(target, receiver, index, value)); |
| 1082 } else { | 1109 } else { |
| 1083 index = pop(); | 1110 HInstruction value; |
| 1084 value = new HLiteral(1, HType.INTEGER); | 1111 HInstruction index; |
| 1085 add(value); | 1112 bool isCompoundAssignment = op.source.stringValue.endsWith('='); |
| 1086 } | 1113 // Compound assignments are considered as being prefix. |
| 1087 HStatic indexMethod = new HStatic(interceptors.getIndexInterceptor()); | 1114 bool isPrefix = !node.isPostfix; |
| 1088 add(indexMethod); | 1115 Element getter = elements[node.selector]; |
| 1089 HInstruction left = new HIndex(indexMethod, receiver, index); | 1116 if (isCompoundAssignment) { |
| 1090 add(left); | 1117 value = pop(); |
| 1091 Element opElement = elements[op]; | 1118 index = pop(); |
| 1092 visitBinary(left, op, value); | 1119 } else { |
| 1093 HInstruction assign = new HIndexAssign(target, receiver, index, pop()); | 1120 index = pop(); |
| 1094 add(assign); | 1121 value = new HLiteral(1, HType.INTEGER); |
| 1095 if (isPrefix) { | 1122 add(value); |
| 1096 stack.add(assign); | 1123 } |
| 1097 } else { | 1124 HStatic indexMethod = new HStatic(interceptors.getIndexInterceptor()); |
| 1098 stack.add(left); | 1125 add(indexMethod); |
| 1126 HInstruction left = new HIndex(indexMethod, receiver, index); |
| 1127 add(left); |
| 1128 Element opElement = elements[op]; |
| 1129 visitBinary(left, op, value); |
| 1130 HInstruction assign = new HIndexAssign( |
| 1131 target, receiver, index, pop()); |
| 1132 add(assign); |
| 1133 if (isPrefix) { |
| 1134 stack.add(assign); |
| 1135 } else { |
| 1136 stack.add(left); |
| 1137 } |
| 1099 } | 1138 } |
| 1100 } | 1139 } |
| 1101 } else if (const SourceString("=") == op.source) { | 1140 } else if (const SourceString("=") == op.source) { |
| 1102 Element element = elements[node]; | 1141 Element element = elements[node]; |
| 1103 Link<Node> link = node.arguments; | 1142 Link<Node> link = node.arguments; |
| 1104 assert(!link.isEmpty() && link.tail.isEmpty()); | 1143 assert(!link.isEmpty() && link.tail.isEmpty()); |
| 1105 visit(link.head); | 1144 visit(link.head); |
| 1106 HInstruction value = pop(); | 1145 HInstruction value = pop(); |
| 1107 generateSetter(node, element, value); | 1146 generateSetter(node, element, value); |
| 1108 } else if (op.source.stringValue === "is") { | 1147 } else if (op.source.stringValue === "is") { |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1408 } | 1447 } |
| 1409 | 1448 |
| 1410 visitCatchBlock(CatchBlock node) { | 1449 visitCatchBlock(CatchBlock node) { |
| 1411 compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node); | 1450 compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node); |
| 1412 } | 1451 } |
| 1413 | 1452 |
| 1414 visitTypedef(Typedef node) { | 1453 visitTypedef(Typedef node) { |
| 1415 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 1454 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 1416 } | 1455 } |
| 1417 } | 1456 } |
| OLD | NEW |