Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/backend.dart

Issue 12299008: Stop resolving all of js_helper unconditionally. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of js_backend; 5 part of js_backend;
6 6
7 typedef void Recompile(Element element); 7 typedef void Recompile(Element element);
8 8
9 class ReturnInfo { 9 class ReturnInfo {
10 HType returnType; 10 HType returnType;
(...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after
869 compiler.jsInvocationMirrorClass.computeType(compiler)); 869 compiler.jsInvocationMirrorClass.computeType(compiler));
870 argumentTypes.registerDynamicInvocation(types, new Selector.noSuchMethod()); 870 argumentTypes.registerDynamicInvocation(types, new Selector.noSuchMethod());
871 } 871 }
872 872
873 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { 873 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) {
874 if (!seenAnyClass) { 874 if (!seenAnyClass) {
875 initializeInterceptorElements(); 875 initializeInterceptorElements();
876 initializeNoSuchMethod(); 876 initializeNoSuchMethod();
877 seenAnyClass = true; 877 seenAnyClass = true;
878 } 878 }
879
880 // Register any helper that will be needed by the backend.
881 if (enqueuer.isResolutionQueue) {
882 if (cls == compiler.intClass
883 || cls == compiler.doubleClass
884 || cls == compiler.numClass) {
885 // The backend will try to optimize number operations and use the
886 // `iae` helper directly.
887 enqueuer.registerStaticUse(
888 compiler.findHelper(const SourceString('iae')));
889 } else if (cls == compiler.listClass
890 ||cls == compiler.stringClass) {
kasperl 2013/02/18 10:31:52 ||cls -> cls
ngeoffray 2013/02/18 11:32:18 Done.
891 // The backend will try to optimize array and string access and use the
892 // `ioore` and `iae` helpers directly.
893 enqueuer.registerStaticUse(
894 compiler.findHelper(const SourceString('ioore')));
895 enqueuer.registerStaticUse(
896 compiler.findHelper(const SourceString('iae')));
897 } else if (cls == compiler.functionClass) {
898 enqueuer.registerInstantiatedClass(compiler.closureClass);
899 } else if (cls == compiler.mapClass) {
900 // The backend will use a literal list to initialize the entries
901 // of the map.
902 enqueuer.registerInstantiatedClass(compiler.listClass);
903 enqueuer.registerInstantiatedClass(compiler.mapLiteralClass);
904 enqueueInResolution(getMapMaker());
905 }
906 }
879 ClassElement result = null; 907 ClassElement result = null;
880 if (cls == compiler.stringClass) { 908 if (cls == compiler.stringClass) {
881 addInterceptors(jsStringClass, enqueuer); 909 addInterceptors(jsStringClass, enqueuer);
882 } else if (cls == compiler.listClass) { 910 } else if (cls == compiler.listClass) {
883 addInterceptors(jsArrayClass, enqueuer); 911 addInterceptors(jsArrayClass, enqueuer);
884 // The backend will try to optimize array access and use the
885 // `ioore` and `iae` helpers directly.
886 if (enqueuer.isResolutionQueue) {
887 enqueuer.registerStaticUse(
888 compiler.findHelper(const SourceString('ioore')));
889 enqueuer.registerStaticUse(
890 compiler.findHelper(const SourceString('iae')));
891 }
892 } else if (cls == compiler.intClass) { 912 } else if (cls == compiler.intClass) {
893 addInterceptors(jsIntClass, enqueuer); 913 addInterceptors(jsIntClass, enqueuer);
894 addInterceptors(jsNumberClass, enqueuer); 914 addInterceptors(jsNumberClass, enqueuer);
895 } else if (cls == compiler.doubleClass) { 915 } else if (cls == compiler.doubleClass) {
896 addInterceptors(jsDoubleClass, enqueuer); 916 addInterceptors(jsDoubleClass, enqueuer);
897 addInterceptors(jsNumberClass, enqueuer); 917 addInterceptors(jsNumberClass, enqueuer);
898 } else if (cls == compiler.functionClass) { 918 } else if (cls == compiler.functionClass) {
899 addInterceptors(jsFunctionClass, enqueuer); 919 addInterceptors(jsFunctionClass, enqueuer);
900 } else if (cls == compiler.boolClass) { 920 } else if (cls == compiler.boolClass) {
901 addInterceptors(jsBoolClass, enqueuer); 921 addInterceptors(jsBoolClass, enqueuer);
902 } else if (cls == compiler.nullClass) { 922 } else if (cls == compiler.nullClass) {
903 addInterceptors(jsNullClass, enqueuer); 923 addInterceptors(jsNullClass, enqueuer);
904 } else if (cls == compiler.numClass) { 924 } else if (cls == compiler.numClass) {
905 addInterceptors(jsIntClass, enqueuer); 925 addInterceptors(jsIntClass, enqueuer);
906 addInterceptors(jsDoubleClass, enqueuer); 926 addInterceptors(jsDoubleClass, enqueuer);
907 addInterceptors(jsNumberClass, enqueuer); 927 addInterceptors(jsNumberClass, enqueuer);
908 } else if (cls == compiler.mapClass) { 928 } else if (cls == compiler.mapClass) {
909 // The backend will use a literal list to initialize the entries 929 }
910 // of the map. 930
911 if (enqueuer.isResolutionQueue) { 931 if (compiler.enableTypeAssertions) {
912 enqueuer.registerInstantiatedClass(compiler.listClass); 932 // We need to register is checks for assignments to fields.
913 enqueuer.registerInstantiatedClass(compiler.mapLiteralClass); 933 cls.forEachLocalMember((Element member) {
914 } 934 if (!member.isInstanceMember() || !member.isField()) return;
935 DartType type = member.computeType(compiler);
936 enqueuer.registerIsCheck(type);
937 });
915 } 938 }
916 } 939 }
917 940
918 Element get cyclicThrowHelper {
919 return compiler.findHelper(const SourceString("throwCyclicInit"));
920 }
921
922 JavaScriptItemCompilationContext createItemCompilationContext() { 941 JavaScriptItemCompilationContext createItemCompilationContext() {
923 return new JavaScriptItemCompilationContext(); 942 return new JavaScriptItemCompilationContext();
924 } 943 }
925 944
926 void enqueueHelpers(ResolutionEnqueuer world) { 945 void enqueueHelpers(ResolutionEnqueuer world) {
927 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world);
928
929 jsIndexingBehaviorInterface = 946 jsIndexingBehaviorInterface =
930 compiler.findHelper(const SourceString('JavaScriptIndexingBehavior')); 947 compiler.findHelper(const SourceString('JavaScriptIndexingBehavior'));
931 if (jsIndexingBehaviorInterface != null) { 948 if (jsIndexingBehaviorInterface != null) {
932 world.registerIsCheck(jsIndexingBehaviorInterface.computeType(compiler)); 949 world.registerIsCheck(jsIndexingBehaviorInterface.computeType(compiler));
933 } 950 }
934 951
935 for (var helper in [const SourceString('Closure'), 952 if (compiler.enableTypeAssertions) {
936 const SourceString('ConstantMap'), 953 // Unconditionally register the helper that checks if the
937 const SourceString('ConstantProtoMap')]) { 954 // expression in an if/while/for is a boolean. TODO(ngeoffray):
kasperl 2013/02/18 10:31:52 Put the TODO on the next line in a "fresh" comment
ngeoffray 2013/02/18 11:32:18 Done.
938 var e = compiler.findHelper(helper); 955 // Should we have the resolver register those instead?
939 if (e != null) world.registerInstantiatedClass(e); 956 Element e =
957 compiler.findHelper(const SourceString('boolConversionCheck'));
958 if (e != null) world.addToWorkList(e);
940 } 959 }
941 } 960 }
942 961
962 void registerStringInterpolation() {
963 enqueueInResolution(getStringInterpolationHelper());
964 }
965
966 void registerCatchStatement() {
967 enqueueInResolution(getExceptionUnwrapper());
968 }
969
970 void registerThrow() {
971 enqueueInResolution(getThrowHelper());
972 }
973
974 void registerLazyField() {
975 enqueueInResolution(getCyclicThrowHelper());
976 }
977
978 void registerTypeLiteral() {
979 enqueueInResolution(getCreateRuntimeType());
980 }
981
982 void registerStackTraceInCatch() {
983 enqueueInResolution(getTraceFromException());
984 }
985
986 void registerRuntimeType() {
987 enqueueInResolution(getSetRuntimeTypeInfo());
988 enqueueInResolution(getGetRuntimeTypeInfo());
989 enqueueInResolution(getGetRuntimeTypeArgument());
990 }
991
992 void registerIsCheck(DartType type, Enqueuer world) {
993 if (!type.isRaw) {
994 enqueueInResolution(getSetRuntimeTypeInfo());
995 enqueueInResolution(getGetRuntimeTypeInfo());
996 enqueueInResolution(getGetRuntimeTypeArgument());
997 enqueueInResolution(getCheckArguments());
998 }
999 if (compiler.enableTypeAssertions) {
kasperl 2013/02/18 10:31:52 Add a comment that explains why we need to registe
ngeoffray 2013/02/18 11:32:18 Done.
1000 SourceString helperName = getCheckedModeHelper(type);
1001 Element e = compiler.findHelper(helperName);
1002 world.addToWorkList(e);
1003 // We also need the native variant of the check (for DOM types).
1004 helperName = nativeNames[helperName.stringValue];
1005 if (helperName != null) {
1006 e = compiler.findHelper(helperName);
1007 world.addToWorkList(e);
1008 }
1009 }
1010 }
1011
1012 void registerAsCheck(DartType type) {
1013 SourceString checkedHelperName = getCheckedModeHelper(type);
1014 SourceString helperName = castNames[checkedHelperName.stringValue];
1015 Element e = compiler.findHelper(helperName);
1016 enqueueInResolution(e);
1017 // We also need the native variant of the check (for DOM types).
1018 checkedHelperName = nativeNames[checkedHelperName.stringValue];
1019 if (checkedHelperName != null) {
1020 helperName = castNames[checkedHelperName.stringValue];
1021 Element e = compiler.findHelper(helperName);
1022 enqueueInResolution(e);
1023 }
1024 }
1025
1026 void registerThrowNoSuchMethod() {
1027 enqueueInResolution(getThrowNoSuchMethod());
1028 }
1029
1030 void registerThrowRuntimeError() {
1031 enqueueInResolution(getThrowRuntimeError());
1032 }
1033
1034 void registerAbstractClassInstantiation() {
1035 enqueueInResolution(getThrowAbstractClassInstantiationError());
1036 }
1037
1038 void registerFallThroughError() {
1039 enqueueInResolution(getFallThroughError());
1040 }
1041
1042 void registerSuperNoSuchMethod() {
1043 enqueueInResolution(getCreateInvocationMirror());
1044 }
1045
1046 void enqueueInResolution(Element e) {
1047 if (e != null) compiler.enqueuer.resolution.addToWorkList(e);
1048 }
1049
1050 void registerConstantMap() {
1051 Element e = compiler.findHelper(const SourceString('ConstantMap'));
1052 if (e != null) compiler.enqueuer.resolution.registerInstantiatedClass(e);
1053 e = compiler.findHelper(const SourceString('ConstantProtoMap'));
1054 if (e != null) compiler.enqueuer.resolution.registerInstantiatedClass(e);
1055 }
1056
943 void codegen(CodegenWorkItem work) { 1057 void codegen(CodegenWorkItem work) {
944 Element element = work.element; 1058 Element element = work.element;
945 if (element.kind.category == ElementCategory.VARIABLE) { 1059 if (element.kind.category == ElementCategory.VARIABLE) {
946 Constant initialValue = compiler.constantHandler.compileWorkItem(work); 1060 Constant initialValue = compiler.constantHandler.compileWorkItem(work);
947 if (initialValue != null) { 1061 if (initialValue != null) {
948 return; 1062 return;
949 } else { 1063 } else {
950 // If the constant-handler was not able to produce a result we have to 1064 // If the constant-handler was not able to produce a result we have to
951 // go through the builder (below) to generate the lazy initializer for 1065 // go through the builder (below) to generate the lazy initializer for
952 // the static variable. 1066 // the static variable.
953 // We also need to register the use of the cyclic-error helper. 1067 // We also need to register the use of the cyclic-error helper.
954 compiler.enqueuer.codegen.registerStaticUse(cyclicThrowHelper); 1068 compiler.enqueuer.codegen.registerStaticUse(getCyclicThrowHelper());
kasperl 2013/02/18 10:31:52 Use registerLazyField instead of all this and remo
ngeoffray 2013/02/18 11:32:18 This is at the codegen level, so I cannot call reg
955 } 1069 }
956 } 1070 }
957 1071
958 HGraph graph = builder.build(work); 1072 HGraph graph = builder.build(work);
959 optimizer.optimize(work, graph, false); 1073 optimizer.optimize(work, graph, false);
960 if (work.allowSpeculativeOptimization 1074 if (work.allowSpeculativeOptimization
961 && optimizer.trySpeculativeOptimizations(work, graph)) { 1075 && optimizer.trySpeculativeOptimizations(work, graph)) {
962 jsAst.Expression code = generator.generateBailoutMethod(work, graph); 1076 jsAst.Expression code = generator.generateBailoutMethod(work, graph);
963 generatedBailoutCode[element] = code; 1077 generatedBailoutCode[element] = code;
964 optimizer.prepareForSpeculativeOptimizations(work, graph); 1078 optimizer.prepareForSpeculativeOptimizations(work, graph);
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1187 ? const SourceString('listSuperNativeTypeCheck') 1301 ? const SourceString('listSuperNativeTypeCheck')
1188 : const SourceString('listSuperTypeCheck'); 1302 : const SourceString('listSuperTypeCheck');
1189 } else { 1303 } else {
1190 return nativeCheck 1304 return nativeCheck
1191 ? const SourceString('callTypeCheck') 1305 ? const SourceString('callTypeCheck')
1192 : const SourceString('propertyTypeCheck'); 1306 : const SourceString('propertyTypeCheck');
1193 } 1307 }
1194 } 1308 }
1195 } 1309 }
1196 1310
1311 Map<String, SourceString> nativeNames = const <String, SourceString> {
1312 'stringSuperTypeCheck':
1313 const SourceString('stringSuperNativeTypeCheck'),
1314 'numberOrStringSuperTypeCheck':
1315 const SourceString('numberOrStringSuperNativeTypeCheck'),
1316 'listSuperTypeCheck':
1317 const SourceString('listSuperNativeTypeCheck'),
1318 'propertyTypeCheck':
1319 const SourceString('callTypeCheck')
1320 };
1321
1322 Map<String, SourceString> castNames = const <String, SourceString> {
1323 "stringTypeCheck":
1324 const SourceString("stringTypeCast"),
1325 "doubleTypeCheck":
1326 const SourceString("doubleTypeCast"),
1327 "numTypeCheck":
1328 const SourceString("numTypeCast"),
1329 "boolTypeCheck":
1330 const SourceString("boolTypeCast"),
1331 "functionTypeCheck":
1332 const SourceString("functionTypeCast"),
1333 "intTypeCheck":
1334 const SourceString("intTypeCast"),
1335 "numberOrStringSuperNativeTypeCheck":
1336 const SourceString("numberOrStringSuperNativeTypeCast"),
1337 "numberOrStringSuperTypeCheck":
1338 const SourceString("numberOrStringSuperTypeCast"),
1339 "stringSuperNativeTypeCheck":
1340 const SourceString("stringSuperNativeTypeCast"),
1341 "stringSuperTypeCheck":
1342 const SourceString("stringSuperTypeCast"),
1343 "listTypeCheck":
1344 const SourceString("listTypeCast"),
1345 "listSuperNativeTypeCheck":
1346 const SourceString("listSuperNativeTypeCast"),
1347 "listSuperTypeCheck":
1348 const SourceString("listSuperTypeCast"),
1349 "callTypeCheck":
1350 const SourceString("callTypeCast"),
1351 "propertyTypeCheck":
1352 const SourceString("propertyTypeCast"),
1353 // TODO(johnniwinther): Add a malformedTypeCast which produces a TypeError
1354 // with another message.
1355 "malformedTypeCheck":
1356 const SourceString("malformedTypeCheck")
1357 };
1358
1197 void dumpInferredTypes() { 1359 void dumpInferredTypes() {
1198 print("Inferred argument types:"); 1360 print("Inferred argument types:");
1199 print("------------------------"); 1361 print("------------------------");
1200 argumentTypes.dump(); 1362 argumentTypes.dump();
1201 print(""); 1363 print("");
1202 print("Inferred return types:"); 1364 print("Inferred return types:");
1203 print("----------------------"); 1365 print("----------------------");
1204 dumpReturnTypes(); 1366 dumpReturnTypes();
1205 print(""); 1367 print("");
1206 print("Inferred field types:"); 1368 print("Inferred field types:");
(...skipping 13 matching lines...) Expand all
1220 Element getThrowMalformedSubtypeError() { 1382 Element getThrowMalformedSubtypeError() {
1221 return compiler.findHelper( 1383 return compiler.findHelper(
1222 const SourceString('throwMalformedSubtypeError')); 1384 const SourceString('throwMalformedSubtypeError'));
1223 } 1385 }
1224 1386
1225 Element getThrowAbstractClassInstantiationError() { 1387 Element getThrowAbstractClassInstantiationError() {
1226 return compiler.findHelper( 1388 return compiler.findHelper(
1227 const SourceString('throwAbstractClassInstantiationError')); 1389 const SourceString('throwAbstractClassInstantiationError'));
1228 } 1390 }
1229 1391
1392 Element getStringInterpolationHelper() {
1393 return compiler.findHelper(const SourceString('S'));
1394 }
1395
1396 Element getThrowHelper() {
1397 return compiler.findHelper(const SourceString(r'$throw'));
1398 }
1399
1230 Element getClosureConverter() { 1400 Element getClosureConverter() {
1231 return compiler.findHelper(const SourceString('convertDartClosureToJS')); 1401 return compiler.findHelper(const SourceString('convertDartClosureToJS'));
1232 } 1402 }
1233 1403
1234 Element getTraceFromException() { 1404 Element getTraceFromException() {
1235 return compiler.findHelper(const SourceString('getTraceFromException')); 1405 return compiler.findHelper(const SourceString('getTraceFromException'));
1236 } 1406 }
1237 1407
1238 Element getMapMaker() { 1408 Element getMapMaker() {
1239 return compiler.findHelper(const SourceString('makeLiteralMap')); 1409 return compiler.findHelper(const SourceString('makeLiteralMap'));
1240 } 1410 }
1241 1411
1242 Element getSetRuntimeTypeInfo() { 1412 Element getSetRuntimeTypeInfo() {
1243 return compiler.findHelper(const SourceString('setRuntimeTypeInfo')); 1413 return compiler.findHelper(const SourceString('setRuntimeTypeInfo'));
1244 } 1414 }
1245 1415
1246 Element getGetRuntimeTypeInfo() { 1416 Element getGetRuntimeTypeInfo() {
1247 return compiler.findHelper(const SourceString('getRuntimeTypeInfo')); 1417 return compiler.findHelper(const SourceString('getRuntimeTypeInfo'));
1248 } 1418 }
1249 1419
1250 Element getGetRuntimeTypeArgument() { 1420 Element getGetRuntimeTypeArgument() {
1251 return compiler.findHelper(const SourceString('getRuntimeTypeArgument')); 1421 return compiler.findHelper(const SourceString('getRuntimeTypeArgument'));
1252 } 1422 }
1253 1423
1424 Element getCheckArguments() {
1425 return compiler.findHelper(const SourceString('checkArguments'));
1426 }
1427
1428 Element getThrowNoSuchMethod() {
1429 return compiler.findHelper(const SourceString('throwNoSuchMethod'));
1430 }
1431
1432 Element getCreateRuntimeType() {
1433 return compiler.findHelper(const SourceString('createRuntimeType'));
1434 }
1435
1436 Element getFallThroughError() {
1437 return compiler.findHelper(const SourceString("getFallThroughError"));
1438 }
1439
1440 Element getCreateInvocationMirror() {
1441 return compiler.findHelper(Compiler.CREATE_INVOCATION_MIRROR);
1442 }
1443
1444 Element getCyclicThrowHelper() {
1445 return compiler.findHelper(const SourceString("throwCyclicInit"));
1446 }
1447
1254 /** 1448 /**
1255 * Remove [element] from the set of generated code, and put it back 1449 * Remove [element] from the set of generated code, and put it back
1256 * into the worklist. 1450 * into the worklist.
1257 * 1451 *
1258 * Invariant: [element] must be a declaration element. 1452 * Invariant: [element] must be a declaration element.
1259 */ 1453 */
1260 void eagerRecompile(Element element) { 1454 void eagerRecompile(Element element) {
1261 assert(invariant(element, element.isDeclaration)); 1455 assert(invariant(element, element.isDeclaration));
1262 generatedCode.remove(element); 1456 generatedCode.remove(element);
1263 generatedBailoutCode.remove(element); 1457 generatedBailoutCode.remove(element);
1264 compiler.enqueuer.codegen.addToWorkList(element); 1458 compiler.enqueuer.codegen.addToWorkList(element);
1265 } 1459 }
1266 } 1460 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698