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

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) {
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.
938 var e = compiler.findHelper(helper); 955 // TODO(ngeoffray): 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 // [registerIsCheck] is also called for checked mode checks, so we
1000 // need to register checked mode helpers.
1001 if (compiler.enableTypeAssertions) {
1002 SourceString helperName = getCheckedModeHelper(type);
1003 Element e = compiler.findHelper(helperName);
1004 if (e != null) world.addToWorkList(e);
1005 // We also need the native variant of the check (for DOM types).
1006 helperName = nativeNames[helperName.stringValue];
1007 if (helperName != null) {
1008 e = compiler.findHelper(helperName);
1009 if (e != null) world.addToWorkList(e);
1010 }
1011 }
1012 }
1013
1014 void registerAsCheck(DartType type) {
1015 SourceString checkedHelperName = getCheckedModeHelper(type);
1016 SourceString helperName = castNames[checkedHelperName.stringValue];
1017 Element e = compiler.findHelper(helperName);
1018 enqueueInResolution(e);
1019 // We also need the native variant of the check (for DOM types).
1020 checkedHelperName = nativeNames[checkedHelperName.stringValue];
1021 if (checkedHelperName != null) {
1022 helperName = castNames[checkedHelperName.stringValue];
1023 Element e = compiler.findHelper(helperName);
1024 enqueueInResolution(e);
1025 }
1026 }
1027
1028 void registerThrowNoSuchMethod() {
1029 enqueueInResolution(getThrowNoSuchMethod());
1030 }
1031
1032 void registerThrowRuntimeError() {
1033 enqueueInResolution(getThrowRuntimeError());
1034 }
1035
1036 void registerAbstractClassInstantiation() {
1037 enqueueInResolution(getThrowAbstractClassInstantiationError());
1038 }
1039
1040 void registerFallThroughError() {
1041 enqueueInResolution(getFallThroughError());
1042 }
1043
1044 void registerSuperNoSuchMethod() {
1045 enqueueInResolution(getCreateInvocationMirror());
1046 }
1047
1048 void enqueueInResolution(Element e) {
1049 if (e != null) compiler.enqueuer.resolution.addToWorkList(e);
1050 }
1051
1052 void registerConstantMap() {
1053 Element e = compiler.findHelper(const SourceString('ConstantMap'));
1054 if (e != null) compiler.enqueuer.resolution.registerInstantiatedClass(e);
1055 e = compiler.findHelper(const SourceString('ConstantProtoMap'));
1056 if (e != null) compiler.enqueuer.resolution.registerInstantiatedClass(e);
1057 }
1058
943 void codegen(CodegenWorkItem work) { 1059 void codegen(CodegenWorkItem work) {
944 Element element = work.element; 1060 Element element = work.element;
945 if (element.kind.category == ElementCategory.VARIABLE) { 1061 if (element.kind.category == ElementCategory.VARIABLE) {
946 Constant initialValue = compiler.constantHandler.compileWorkItem(work); 1062 Constant initialValue = compiler.constantHandler.compileWorkItem(work);
947 if (initialValue != null) { 1063 if (initialValue != null) {
948 return; 1064 return;
949 } else { 1065 } else {
950 // If the constant-handler was not able to produce a result we have to 1066 // 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 1067 // go through the builder (below) to generate the lazy initializer for
952 // the static variable. 1068 // the static variable.
953 // We also need to register the use of the cyclic-error helper. 1069 // We also need to register the use of the cyclic-error helper.
954 compiler.enqueuer.codegen.registerStaticUse(cyclicThrowHelper); 1070 compiler.enqueuer.codegen.registerStaticUse(getCyclicThrowHelper());
955 } 1071 }
956 } 1072 }
957 1073
958 HGraph graph = builder.build(work); 1074 HGraph graph = builder.build(work);
959 optimizer.optimize(work, graph, false); 1075 optimizer.optimize(work, graph, false);
960 if (work.allowSpeculativeOptimization 1076 if (work.allowSpeculativeOptimization
961 && optimizer.trySpeculativeOptimizations(work, graph)) { 1077 && optimizer.trySpeculativeOptimizations(work, graph)) {
962 jsAst.Expression code = generator.generateBailoutMethod(work, graph); 1078 jsAst.Expression code = generator.generateBailoutMethod(work, graph);
963 generatedBailoutCode[element] = code; 1079 generatedBailoutCode[element] = code;
964 optimizer.prepareForSpeculativeOptimizations(work, graph); 1080 optimizer.prepareForSpeculativeOptimizations(work, graph);
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1187 ? const SourceString('listSuperNativeTypeCheck') 1303 ? const SourceString('listSuperNativeTypeCheck')
1188 : const SourceString('listSuperTypeCheck'); 1304 : const SourceString('listSuperTypeCheck');
1189 } else { 1305 } else {
1190 return nativeCheck 1306 return nativeCheck
1191 ? const SourceString('callTypeCheck') 1307 ? const SourceString('callTypeCheck')
1192 : const SourceString('propertyTypeCheck'); 1308 : const SourceString('propertyTypeCheck');
1193 } 1309 }
1194 } 1310 }
1195 } 1311 }
1196 1312
1313 Map<String, SourceString> nativeNames = const <String, SourceString> {
ahe 2013/02/18 12:38:04 Document this.
1314 'stringSuperTypeCheck':
1315 const SourceString('stringSuperNativeTypeCheck'),
1316 'numberOrStringSuperTypeCheck':
1317 const SourceString('numberOrStringSuperNativeTypeCheck'),
1318 'listSuperTypeCheck':
1319 const SourceString('listSuperNativeTypeCheck'),
1320 'propertyTypeCheck':
1321 const SourceString('callTypeCheck')
1322 };
1323
1324 Map<String, SourceString> castNames = const <String, SourceString> {
ahe 2013/02/18 12:38:04 Ditto.
1325 "stringTypeCheck":
1326 const SourceString("stringTypeCast"),
1327 "doubleTypeCheck":
1328 const SourceString("doubleTypeCast"),
1329 "numTypeCheck":
1330 const SourceString("numTypeCast"),
1331 "boolTypeCheck":
1332 const SourceString("boolTypeCast"),
1333 "functionTypeCheck":
1334 const SourceString("functionTypeCast"),
1335 "intTypeCheck":
1336 const SourceString("intTypeCast"),
1337 "numberOrStringSuperNativeTypeCheck":
1338 const SourceString("numberOrStringSuperNativeTypeCast"),
1339 "numberOrStringSuperTypeCheck":
1340 const SourceString("numberOrStringSuperTypeCast"),
1341 "stringSuperNativeTypeCheck":
1342 const SourceString("stringSuperNativeTypeCast"),
1343 "stringSuperTypeCheck":
1344 const SourceString("stringSuperTypeCast"),
1345 "listTypeCheck":
1346 const SourceString("listTypeCast"),
1347 "listSuperNativeTypeCheck":
1348 const SourceString("listSuperNativeTypeCast"),
1349 "listSuperTypeCheck":
1350 const SourceString("listSuperTypeCast"),
1351 "callTypeCheck":
1352 const SourceString("callTypeCast"),
1353 "propertyTypeCheck":
1354 const SourceString("propertyTypeCast"),
1355 // TODO(johnniwinther): Add a malformedTypeCast which produces a TypeError
1356 // with another message.
1357 "malformedTypeCheck":
1358 const SourceString("malformedTypeCheck")
1359 };
1360
1197 void dumpInferredTypes() { 1361 void dumpInferredTypes() {
1198 print("Inferred argument types:"); 1362 print("Inferred argument types:");
1199 print("------------------------"); 1363 print("------------------------");
1200 argumentTypes.dump(); 1364 argumentTypes.dump();
1201 print(""); 1365 print("");
1202 print("Inferred return types:"); 1366 print("Inferred return types:");
1203 print("----------------------"); 1367 print("----------------------");
1204 dumpReturnTypes(); 1368 dumpReturnTypes();
1205 print(""); 1369 print("");
1206 print("Inferred field types:"); 1370 print("Inferred field types:");
(...skipping 13 matching lines...) Expand all
1220 Element getThrowMalformedSubtypeError() { 1384 Element getThrowMalformedSubtypeError() {
1221 return compiler.findHelper( 1385 return compiler.findHelper(
1222 const SourceString('throwMalformedSubtypeError')); 1386 const SourceString('throwMalformedSubtypeError'));
1223 } 1387 }
1224 1388
1225 Element getThrowAbstractClassInstantiationError() { 1389 Element getThrowAbstractClassInstantiationError() {
1226 return compiler.findHelper( 1390 return compiler.findHelper(
1227 const SourceString('throwAbstractClassInstantiationError')); 1391 const SourceString('throwAbstractClassInstantiationError'));
1228 } 1392 }
1229 1393
1394 Element getStringInterpolationHelper() {
1395 return compiler.findHelper(const SourceString('S'));
1396 }
1397
1398 Element getThrowHelper() {
1399 return compiler.findHelper(const SourceString(r'$throw'));
1400 }
1401
1230 Element getClosureConverter() { 1402 Element getClosureConverter() {
1231 return compiler.findHelper(const SourceString('convertDartClosureToJS')); 1403 return compiler.findHelper(const SourceString('convertDartClosureToJS'));
1232 } 1404 }
1233 1405
1234 Element getTraceFromException() { 1406 Element getTraceFromException() {
1235 return compiler.findHelper(const SourceString('getTraceFromException')); 1407 return compiler.findHelper(const SourceString('getTraceFromException'));
1236 } 1408 }
1237 1409
1238 Element getMapMaker() { 1410 Element getMapMaker() {
1239 return compiler.findHelper(const SourceString('makeLiteralMap')); 1411 return compiler.findHelper(const SourceString('makeLiteralMap'));
1240 } 1412 }
1241 1413
1242 Element getSetRuntimeTypeInfo() { 1414 Element getSetRuntimeTypeInfo() {
1243 return compiler.findHelper(const SourceString('setRuntimeTypeInfo')); 1415 return compiler.findHelper(const SourceString('setRuntimeTypeInfo'));
1244 } 1416 }
1245 1417
1246 Element getGetRuntimeTypeInfo() { 1418 Element getGetRuntimeTypeInfo() {
1247 return compiler.findHelper(const SourceString('getRuntimeTypeInfo')); 1419 return compiler.findHelper(const SourceString('getRuntimeTypeInfo'));
1248 } 1420 }
1249 1421
1250 Element getGetRuntimeTypeArgument() { 1422 Element getGetRuntimeTypeArgument() {
1251 return compiler.findHelper(const SourceString('getRuntimeTypeArgument')); 1423 return compiler.findHelper(const SourceString('getRuntimeTypeArgument'));
1252 } 1424 }
1253 1425
1426 Element getCheckArguments() {
1427 return compiler.findHelper(const SourceString('checkArguments'));
1428 }
1429
1430 Element getThrowNoSuchMethod() {
1431 return compiler.findHelper(const SourceString('throwNoSuchMethod'));
1432 }
1433
1434 Element getCreateRuntimeType() {
1435 return compiler.findHelper(const SourceString('createRuntimeType'));
1436 }
1437
1438 Element getFallThroughError() {
1439 return compiler.findHelper(const SourceString("getFallThroughError"));
1440 }
1441
1442 Element getCreateInvocationMirror() {
1443 return compiler.findHelper(Compiler.CREATE_INVOCATION_MIRROR);
1444 }
1445
1446 Element getCyclicThrowHelper() {
1447 return compiler.findHelper(const SourceString("throwCyclicInit"));
1448 }
1449
1254 /** 1450 /**
1255 * Remove [element] from the set of generated code, and put it back 1451 * Remove [element] from the set of generated code, and put it back
1256 * into the worklist. 1452 * into the worklist.
1257 * 1453 *
1258 * Invariant: [element] must be a declaration element. 1454 * Invariant: [element] must be a declaration element.
1259 */ 1455 */
1260 void eagerRecompile(Element element) { 1456 void eagerRecompile(Element element) {
1261 assert(invariant(element, element.isDeclaration)); 1457 assert(invariant(element, element.isDeclaration));
1262 generatedCode.remove(element); 1458 generatedCode.remove(element);
1263 generatedBailoutCode.remove(element); 1459 generatedBailoutCode.remove(element);
1264 compiler.enqueuer.codegen.addToWorkList(element); 1460 compiler.enqueuer.codegen.addToWorkList(element);
1265 } 1461 }
1266 } 1462 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698