OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
9 import '../common/names.dart'; | 9 import '../common/names.dart'; |
10 import '../common/tasks.dart' show CompilerTask; | 10 import '../common/tasks.dart' show CompilerTask; |
11 import '../compiler.dart'; | 11 import '../compiler.dart'; |
| 12 import '../constants/values.dart' show StringConstantValue; |
12 import '../dart_types.dart'; | 13 import '../dart_types.dart'; |
13 import '../elements/elements.dart'; | 14 import '../elements/elements.dart'; |
14 import '../io/source_information.dart'; | 15 import '../io/source_information.dart'; |
| 16 import '../js/js.dart' as js; |
15 import '../js_backend/backend.dart' show JavaScriptBackend; | 17 import '../js_backend/backend.dart' show JavaScriptBackend; |
16 import '../kernel/kernel.dart'; | 18 import '../kernel/kernel.dart'; |
| 19 import '../native/native.dart' as native; |
17 import '../resolution/tree_elements.dart'; | 20 import '../resolution/tree_elements.dart'; |
18 import '../tree/dartstring.dart'; | 21 import '../tree/dartstring.dart'; |
19 import '../tree/nodes.dart' show FunctionExpression, Node; | 22 import '../tree/nodes.dart' show FunctionExpression, Node; |
20 import '../types/masks.dart'; | 23 import '../types/masks.dart'; |
21 import '../universe/call_structure.dart' show CallStructure; | 24 import '../universe/call_structure.dart' show CallStructure; |
22 import '../universe/selector.dart'; | 25 import '../universe/selector.dart'; |
23 import '../universe/use.dart' show TypeUse; | 26 import '../universe/use.dart' show TypeUse; |
| 27 import '../universe/side_effects.dart' show SideEffects; |
24 import 'graph_builder.dart'; | 28 import 'graph_builder.dart'; |
25 import 'kernel_ast_adapter.dart'; | 29 import 'kernel_ast_adapter.dart'; |
26 import 'kernel_string_builder.dart'; | 30 import 'kernel_string_builder.dart'; |
27 import 'locals_handler.dart'; | 31 import 'locals_handler.dart'; |
28 import 'loop_handler.dart'; | 32 import 'loop_handler.dart'; |
29 import 'nodes.dart'; | 33 import 'nodes.dart'; |
30 import 'ssa_branch_builder.dart'; | 34 import 'ssa_branch_builder.dart'; |
31 import 'type_builder.dart'; | 35 import 'type_builder.dart'; |
32 import 'types.dart' show TypeMaskFactory; | 36 import 'types.dart' show TypeMaskFactory; |
33 | 37 |
(...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 @override | 862 @override |
859 void visitMapEntry(ir.MapEntry mapEntry) { | 863 void visitMapEntry(ir.MapEntry mapEntry) { |
860 // Visit value before the key because each will push an expression to the | 864 // Visit value before the key because each will push an expression to the |
861 // stack, so when we pop them off, the key is popped first, then the value. | 865 // stack, so when we pop them off, the key is popped first, then the value. |
862 mapEntry.value.accept(this); | 866 mapEntry.value.accept(this); |
863 mapEntry.key.accept(this); | 867 mapEntry.key.accept(this); |
864 } | 868 } |
865 | 869 |
866 @override | 870 @override |
867 void visitStaticGet(ir.StaticGet staticGet) { | 871 void visitStaticGet(ir.StaticGet staticGet) { |
868 var staticTarget = staticGet.target; | 872 ir.Member staticTarget = staticGet.target; |
869 if (staticTarget is ir.Procedure && | 873 if (staticTarget is ir.Procedure && |
870 staticTarget.kind == ir.ProcedureKind.Getter) { | 874 staticTarget.kind == ir.ProcedureKind.Getter) { |
871 // Invoke the getter | 875 // Invoke the getter |
872 _pushStaticInvocation(staticTarget, const <HInstruction>[], | 876 _pushStaticInvocation(staticTarget, const <HInstruction>[], |
873 astAdapter.returnTypeOf(staticTarget)); | 877 astAdapter.returnTypeOf(staticTarget)); |
| 878 } else if (staticTarget is ir.Field && staticTarget.isConst) { |
| 879 assert(staticTarget.initializer != null); |
| 880 stack.add(graph.addConstant( |
| 881 astAdapter.getConstantFor(staticTarget.initializer), compiler)); |
874 } else { | 882 } else { |
875 push(new HStatic(astAdapter.getMember(staticTarget), | 883 push(new HStatic(astAdapter.getMember(staticTarget), |
876 astAdapter.inferredTypeOf(staticTarget))); | 884 astAdapter.inferredTypeOf(staticTarget))); |
877 } | 885 } |
878 } | 886 } |
879 | 887 |
880 @override | 888 @override |
881 void visitStaticSet(ir.StaticSet staticSet) { | 889 void visitStaticSet(ir.StaticSet staticSet) { |
882 staticSet.value.accept(this); | 890 staticSet.value.accept(this); |
883 HInstruction value = pop(); | 891 HInstruction value = pop(); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
966 argument.value.accept(this); | 974 argument.value.accept(this); |
967 result.add(pop()); | 975 result.add(pop()); |
968 } | 976 } |
969 | 977 |
970 return result; | 978 return result; |
971 } | 979 } |
972 | 980 |
973 @override | 981 @override |
974 void visitStaticInvocation(ir.StaticInvocation invocation) { | 982 void visitStaticInvocation(ir.StaticInvocation invocation) { |
975 ir.Procedure target = invocation.target; | 983 ir.Procedure target = invocation.target; |
| 984 if (astAdapter.isInForeignLibrary(target)) { |
| 985 handleInvokeStaticForeign(invocation, target); |
| 986 return; |
| 987 } |
976 TypeMask typeMask = astAdapter.returnTypeOf(target); | 988 TypeMask typeMask = astAdapter.returnTypeOf(target); |
977 | 989 |
978 List<HInstruction> arguments = _visitArguments(invocation.arguments); | 990 List<HInstruction> arguments = _visitArguments(invocation.arguments); |
979 | 991 |
980 _pushStaticInvocation(target, arguments, typeMask); | 992 _pushStaticInvocation(target, arguments, typeMask); |
981 } | 993 } |
982 | 994 |
| 995 void handleInvokeStaticForeign( |
| 996 ir.StaticInvocation invocation, ir.Procedure target) { |
| 997 String name = target.name.name; |
| 998 if (name == 'JS') { |
| 999 handleForeignJs(invocation); |
| 1000 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { |
| 1001 handleForeignJsCurrentIsolateContext(invocation); |
| 1002 } else if (name == 'JS_CALL_IN_ISOLATE') { |
| 1003 handleForeignJsCallInIsolate(invocation); |
| 1004 } else if (name == 'DART_CLOSURE_TO_JS') { |
| 1005 handleForeignDartClosureToJs(invocation, 'DART_CLOSURE_TO_JS'); |
| 1006 } else if (name == 'RAW_DART_FUNCTION_REF') { |
| 1007 handleForeignRawFunctionRef(invocation, 'RAW_DART_FUNCTION_REF'); |
| 1008 } else if (name == 'JS_SET_STATIC_STATE') { |
| 1009 handleForeignJsSetStaticState(invocation); |
| 1010 } else if (name == 'JS_GET_STATIC_STATE') { |
| 1011 handleForeignJsGetStaticState(invocation); |
| 1012 } else if (name == 'JS_GET_NAME') { |
| 1013 handleForeignJsGetName(invocation); |
| 1014 } else if (name == 'JS_EMBEDDED_GLOBAL') { |
| 1015 handleForeignJsEmbeddedGlobal(invocation); |
| 1016 } else if (name == 'JS_BUILTIN') { |
| 1017 handleForeignJsBuiltin(invocation); |
| 1018 } else if (name == 'JS_GET_FLAG') { |
| 1019 handleForeignJsGetFlag(invocation); |
| 1020 } else if (name == 'JS_EFFECT') { |
| 1021 stack.add(graph.addConstantNull(compiler)); |
| 1022 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
| 1023 handleJsInterceptorConstant(invocation); |
| 1024 } else if (name == 'JS_STRING_CONCAT') { |
| 1025 handleJsStringConcat(invocation); |
| 1026 } else { |
| 1027 compiler.reporter.internalError( |
| 1028 astAdapter.getNode(invocation), "Unknown foreign: ${name}"); |
| 1029 } |
| 1030 } |
| 1031 |
| 1032 bool _unexpectedForeignArguments( |
| 1033 ir.StaticInvocation invocation, int minPositional, |
| 1034 [int maxPositional]) { |
| 1035 String pluralizeArguments(int count) { |
| 1036 if (count == 0) return 'no arguments'; |
| 1037 if (count == 1) return 'one argument'; |
| 1038 if (count == 2) return 'two arguments'; |
| 1039 return '$count arguments'; |
| 1040 } |
| 1041 |
| 1042 String name() => invocation.target.name.name; |
| 1043 |
| 1044 ir.Arguments arguments = invocation.arguments; |
| 1045 bool bad = false; |
| 1046 if (arguments.types.isNotEmpty) { |
| 1047 compiler.reporter.reportErrorMessage( |
| 1048 astAdapter.getNode(invocation), |
| 1049 MessageKind.GENERIC, |
| 1050 {'text': "Error: '${name()}' does not take type arguments."}); |
| 1051 bad = true; |
| 1052 } |
| 1053 if (arguments.positional.length < minPositional) { |
| 1054 String phrase = pluralizeArguments(minPositional); |
| 1055 if (maxPositional != minPositional) phrase = 'at least $phrase'; |
| 1056 compiler.reporter.reportErrorMessage( |
| 1057 astAdapter.getNode(invocation), |
| 1058 MessageKind.GENERIC, |
| 1059 {'text': "Error: Too few arguments. '${name()}' takes $phrase."}); |
| 1060 bad = true; |
| 1061 } |
| 1062 if (maxPositional != null && arguments.positional.length > maxPositional) { |
| 1063 String phrase = pluralizeArguments(maxPositional); |
| 1064 if (maxPositional != minPositional) phrase = 'at most $phrase'; |
| 1065 compiler.reporter.reportErrorMessage( |
| 1066 astAdapter.getNode(invocation), |
| 1067 MessageKind.GENERIC, |
| 1068 {'text': "Error: Too many arguments. '${name()}' takes $phrase."}); |
| 1069 bad = true; |
| 1070 } |
| 1071 if (arguments.named.isNotEmpty) { |
| 1072 compiler.reporter.reportErrorMessage( |
| 1073 astAdapter.getNode(invocation), |
| 1074 MessageKind.GENERIC, |
| 1075 {'text': "Error: '${name()}' does not take named arguments."}); |
| 1076 bad = true; |
| 1077 } |
| 1078 return bad; |
| 1079 } |
| 1080 |
| 1081 /// Returns the value of the string argument. The argument must evaluate to a |
| 1082 /// constant. If there is an error, the error is reported and `null` is |
| 1083 /// returned. |
| 1084 String _foreignConstantStringArgument( |
| 1085 ir.StaticInvocation invocation, int position, String methodName, |
| 1086 [String adjective = '']) { |
| 1087 ir.Expression argument = invocation.arguments.positional[position]; |
| 1088 argument.accept(this); |
| 1089 HInstruction instruction = pop(); |
| 1090 |
| 1091 if (!instruction.isConstantString()) { |
| 1092 compiler.reporter.reportErrorMessage( |
| 1093 astAdapter.getNode(argument), MessageKind.GENERIC, { |
| 1094 'text': "Error: Expected String constant as ${adjective}argument " |
| 1095 "to '$methodName'." |
| 1096 }); |
| 1097 return null; |
| 1098 } |
| 1099 |
| 1100 HConstant hConstant = instruction; |
| 1101 StringConstantValue stringConstant = hConstant.constant; |
| 1102 return stringConstant.primitiveValue.slowToString(); |
| 1103 } |
| 1104 |
| 1105 // TODO(sra): Remove when handleInvokeStaticForeign fully implemented. |
| 1106 void unhandledForeign(ir.StaticInvocation invocation) { |
| 1107 ir.Procedure target = invocation.target; |
| 1108 TypeMask typeMask = astAdapter.returnTypeOf(target); |
| 1109 List<HInstruction> arguments = _visitArguments(invocation.arguments); |
| 1110 _pushStaticInvocation(target, arguments, typeMask); |
| 1111 } |
| 1112 |
| 1113 void handleForeignJsCurrentIsolateContext(ir.StaticInvocation invocation) { |
| 1114 if (_unexpectedForeignArguments(invocation, 0, 0)) { |
| 1115 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1116 return; |
| 1117 } |
| 1118 |
| 1119 if (!compiler.hasIsolateSupport) { |
| 1120 // If the isolate library is not used, we just generate code |
| 1121 // to fetch the static state. |
| 1122 String name = backend.namer.staticStateHolder; |
| 1123 push(new HForeignCode( |
| 1124 js.js.parseForeignJS(name), backend.dynamicType, <HInstruction>[], |
| 1125 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
| 1126 } else { |
| 1127 // Call a helper method from the isolate library. The isolate library uses |
| 1128 // its own isolate structure that encapsulates the isolate structure used |
| 1129 // for binding to methods. |
| 1130 ir.Procedure target = astAdapter.currentIsolate; |
| 1131 if (target == null) { |
| 1132 compiler.reporter.internalError(astAdapter.getNode(invocation), |
| 1133 'Isolate library and compiler mismatch.'); |
| 1134 } |
| 1135 _pushStaticInvocation(target, <HInstruction>[], backend.dynamicType); |
| 1136 } |
| 1137 |
| 1138 /* |
| 1139 if (!node.arguments.isEmpty) { |
| 1140 reporter.internalError( |
| 1141 node, 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.'); |
| 1142 } |
| 1143 |
| 1144 if (!compiler.hasIsolateSupport) { |
| 1145 // If the isolate library is not used, we just generate code |
| 1146 // to fetch the static state. |
| 1147 String name = backend.namer.staticStateHolder; |
| 1148 push(new HForeignCode( |
| 1149 js.js.parseForeignJS(name), backend.dynamicType, <HInstruction>[], |
| 1150 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
| 1151 } else { |
| 1152 // Call a helper method from the isolate library. The isolate |
| 1153 // library uses its own isolate structure, that encapsulates |
| 1154 // Leg's isolate. |
| 1155 Element element = helpers.currentIsolate; |
| 1156 if (element == null) { |
| 1157 reporter.internalError(node, 'Isolate library and compiler mismatch.'); |
| 1158 } |
| 1159 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); |
| 1160 } |
| 1161 */ |
| 1162 } |
| 1163 |
| 1164 void handleForeignJsCallInIsolate(ir.StaticInvocation invocation) { |
| 1165 unhandledForeign(invocation); |
| 1166 } |
| 1167 |
| 1168 void handleForeignDartClosureToJs( |
| 1169 ir.StaticInvocation invocation, String name) { |
| 1170 unhandledForeign(invocation); |
| 1171 } |
| 1172 |
| 1173 void handleForeignRawFunctionRef( |
| 1174 ir.StaticInvocation invocation, String name) { |
| 1175 unhandledForeign(invocation); |
| 1176 } |
| 1177 |
| 1178 void handleForeignJsSetStaticState(ir.StaticInvocation invocation) { |
| 1179 if (_unexpectedForeignArguments(invocation, 0, 0)) { |
| 1180 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1181 return; |
| 1182 } |
| 1183 _visitArguments(invocation.arguments); |
| 1184 String isolateName = backend.namer.staticStateHolder; |
| 1185 SideEffects sideEffects = new SideEffects.empty(); |
| 1186 sideEffects.setAllSideEffects(); |
| 1187 push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"), |
| 1188 backend.dynamicType, <HInstruction>[pop()], |
| 1189 nativeBehavior: native.NativeBehavior.CHANGES_OTHER, |
| 1190 effects: sideEffects)); |
| 1191 } |
| 1192 |
| 1193 void handleForeignJsGetStaticState(ir.StaticInvocation invocation) { |
| 1194 if (_unexpectedForeignArguments(invocation, 0, 0)) { |
| 1195 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1196 return; |
| 1197 } |
| 1198 |
| 1199 push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder), |
| 1200 backend.dynamicType, <HInstruction>[], |
| 1201 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
| 1202 } |
| 1203 |
| 1204 void handleForeignJsGetName(ir.StaticInvocation invocation) { |
| 1205 if (_unexpectedForeignArguments(invocation, 1, 1)) { |
| 1206 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1207 return; |
| 1208 } |
| 1209 |
| 1210 ir.Node argument = invocation.arguments.positional.first; |
| 1211 argument.accept(this); |
| 1212 HInstruction instruction = pop(); |
| 1213 |
| 1214 if (instruction is HConstant) { |
| 1215 js.Name name = |
| 1216 astAdapter.getNameForJsGetName(argument, instruction.constant); |
| 1217 stack.add(graph.addConstantStringFromName(name, compiler)); |
| 1218 return; |
| 1219 } |
| 1220 |
| 1221 compiler.reporter.reportErrorMessage( |
| 1222 astAdapter.getNode(argument), |
| 1223 MessageKind.GENERIC, |
| 1224 {'text': 'Error: Expected a JsGetName enum value.'}); |
| 1225 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1226 } |
| 1227 |
| 1228 void handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) { |
| 1229 if (_unexpectedForeignArguments(invocation, 2, 2)) { |
| 1230 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1231 return; |
| 1232 } |
| 1233 String globalName = _foreignConstantStringArgument( |
| 1234 invocation, 1, 'JS_EMBEDDED_GLOBAL', 'second '); |
| 1235 js.Template expr = js.js.expressionTemplateYielding( |
| 1236 backend.emitter.generateEmbeddedGlobalAccess(globalName)); |
| 1237 |
| 1238 native.NativeBehavior nativeBehavior = |
| 1239 astAdapter.getNativeBehavior(invocation); |
| 1240 assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null, |
| 1241 message: "No NativeBehavior for $invocation")); |
| 1242 |
| 1243 TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior); |
| 1244 push(new HForeignCode(expr, ssaType, const <HInstruction>[], |
| 1245 nativeBehavior: nativeBehavior)); |
| 1246 } |
| 1247 |
| 1248 void handleForeignJsBuiltin(ir.StaticInvocation invocation) { |
| 1249 if (_unexpectedForeignArguments(invocation, 2)) { |
| 1250 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1251 return; |
| 1252 } |
| 1253 |
| 1254 List<ir.Expression> arguments = invocation.arguments.positional; |
| 1255 ir.Expression nameArgument = arguments[1]; |
| 1256 |
| 1257 nameArgument.accept(this); |
| 1258 HInstruction instruction = pop(); |
| 1259 |
| 1260 js.Template template; |
| 1261 if (instruction is HConstant) { |
| 1262 template = astAdapter.getJsBuiltinTemplate(instruction.constant); |
| 1263 } |
| 1264 if (template == null) { |
| 1265 compiler.reporter.reportErrorMessage( |
| 1266 astAdapter.getNode(nameArgument), |
| 1267 MessageKind.GENERIC, |
| 1268 {'text': 'Error: Expected a JsBuiltin enum value.'}); |
| 1269 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1270 return; |
| 1271 } |
| 1272 |
| 1273 List<HInstruction> inputs = <HInstruction>[]; |
| 1274 for (ir.Expression argument in arguments.skip(2)) { |
| 1275 argument.accept(this); |
| 1276 inputs.add(pop()); |
| 1277 } |
| 1278 |
| 1279 native.NativeBehavior nativeBehavior = |
| 1280 astAdapter.getNativeBehavior(invocation); |
| 1281 assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null, |
| 1282 message: "No NativeBehavior for $invocation")); |
| 1283 |
| 1284 TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior); |
| 1285 push(new HForeignCode(template, ssaType, inputs, |
| 1286 nativeBehavior: nativeBehavior)); |
| 1287 } |
| 1288 |
| 1289 void handleForeignJsGetFlag(ir.StaticInvocation invocation) { |
| 1290 if (_unexpectedForeignArguments(invocation, 1, 1)) { |
| 1291 stack.add( |
| 1292 graph.addConstantBool(false, compiler)); // Result expected on stack. |
| 1293 return; |
| 1294 } |
| 1295 String name = _foreignConstantStringArgument(invocation, 0, 'JS_GET_FLAG'); |
| 1296 bool value = false; |
| 1297 switch (name) { |
| 1298 case 'MUST_RETAIN_METADATA': |
| 1299 value = backend.mustRetainMetadata; |
| 1300 break; |
| 1301 case 'USE_CONTENT_SECURITY_POLICY': |
| 1302 value = compiler.options.useContentSecurityPolicy; |
| 1303 break; |
| 1304 default: |
| 1305 compiler.reporter.reportErrorMessage( |
| 1306 astAdapter.getNode(invocation), |
| 1307 MessageKind.GENERIC, |
| 1308 {'text': 'Error: Unknown internal flag "$name".'}); |
| 1309 } |
| 1310 stack.add(graph.addConstantBool(value, compiler)); |
| 1311 } |
| 1312 |
| 1313 void handleJsInterceptorConstant(ir.StaticInvocation invocation) { |
| 1314 unhandledForeign(invocation); |
| 1315 } |
| 1316 |
| 1317 void handleForeignJs(ir.StaticInvocation invocation) { |
| 1318 if (_unexpectedForeignArguments(invocation, 2)) { |
| 1319 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1320 return; |
| 1321 } |
| 1322 |
| 1323 native.NativeBehavior nativeBehavior = |
| 1324 astAdapter.getNativeBehavior(invocation); |
| 1325 assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null, |
| 1326 message: "No NativeBehavior for $invocation")); |
| 1327 |
| 1328 List<HInstruction> inputs = <HInstruction>[]; |
| 1329 for (ir.Expression argument in invocation.arguments.positional.skip(2)) { |
| 1330 argument.accept(this); |
| 1331 inputs.add(pop()); |
| 1332 } |
| 1333 |
| 1334 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { |
| 1335 compiler.reporter.reportErrorMessage( |
| 1336 astAdapter.getNode(invocation), MessageKind.GENERIC, { |
| 1337 'text': 'Mismatch between number of placeholders' |
| 1338 ' and number of arguments.' |
| 1339 }); |
| 1340 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1341 return; |
| 1342 } |
| 1343 |
| 1344 if (native.HasCapturedPlaceholders.check(nativeBehavior.codeTemplate.ast)) { |
| 1345 compiler.reporter.reportErrorMessage( |
| 1346 astAdapter.getNode(invocation), MessageKind.JS_PLACEHOLDER_CAPTURE); |
| 1347 } |
| 1348 |
| 1349 TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior); |
| 1350 |
| 1351 SourceInformation sourceInformation = null; |
| 1352 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs, |
| 1353 isStatement: !nativeBehavior.codeTemplate.isExpression, |
| 1354 effects: nativeBehavior.sideEffects, |
| 1355 nativeBehavior: nativeBehavior)..sourceInformation = sourceInformation); |
| 1356 } |
| 1357 |
| 1358 void handleJsStringConcat(ir.StaticInvocation invocation) { |
| 1359 if (_unexpectedForeignArguments(invocation, 2, 2)) { |
| 1360 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1361 return; |
| 1362 } |
| 1363 List<HInstruction> inputs = _visitArguments(invocation.arguments); |
| 1364 push(new HStringConcat(inputs[0], inputs[1], backend.stringType)); |
| 1365 } |
| 1366 |
983 void _pushStaticInvocation( | 1367 void _pushStaticInvocation( |
984 ir.Node target, List<HInstruction> arguments, TypeMask typeMask) { | 1368 ir.Node target, List<HInstruction> arguments, TypeMask typeMask) { |
985 HInvokeStatic instruction = new HInvokeStatic( | 1369 HInvokeStatic instruction = new HInvokeStatic( |
986 astAdapter.getMember(target), arguments, typeMask, | 1370 astAdapter.getMember(target), arguments, typeMask, |
987 targetCanThrow: astAdapter.getCanThrow(target)); | 1371 targetCanThrow: astAdapter.getCanThrow(target)); |
988 if (currentImplicitInstantiations.isNotEmpty) { | 1372 if (currentImplicitInstantiations.isNotEmpty) { |
989 instruction.instantiatedTypes = | 1373 instruction.instantiatedTypes = |
990 new List<DartType>.from(currentImplicitInstantiations); | 1374 new List<DartType>.from(currentImplicitInstantiations); |
991 } | 1375 } |
992 instruction.sideEffects = astAdapter.getSideEffects(target); | 1376 instruction.sideEffects = astAdapter.getSideEffects(target); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1123 push(new HNot(popBoolified(), backend.boolType)); | 1507 push(new HNot(popBoolified(), backend.boolType)); |
1124 } | 1508 } |
1125 | 1509 |
1126 @override | 1510 @override |
1127 void visitStringConcatenation(ir.StringConcatenation stringConcat) { | 1511 void visitStringConcatenation(ir.StringConcatenation stringConcat) { |
1128 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); | 1512 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); |
1129 stringConcat.accept(stringBuilder); | 1513 stringConcat.accept(stringBuilder); |
1130 stack.add(stringBuilder.result); | 1514 stack.add(stringBuilder.result); |
1131 } | 1515 } |
1132 } | 1516 } |
OLD | NEW |