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

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

Issue 12525007: Record dependency information to implement first version of dependency (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased/merged Created 7 years, 9 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 824 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 jsStringConcat = compiler.lookupElementIn( 835 jsStringConcat = compiler.lookupElementIn(
836 jsStringClass, const SourceString('concat')); 836 jsStringClass, const SourceString('concat'));
837 jsStringToString = compiler.lookupElementIn( 837 jsStringToString = compiler.lookupElementIn(
838 jsStringClass, const SourceString('toString')); 838 jsStringClass, const SourceString('toString'));
839 839
840 for (ClassElement cls in classes) { 840 for (ClassElement cls in classes) {
841 if (cls != null) interceptedClasses.add(cls); 841 if (cls != null) interceptedClasses.add(cls);
842 } 842 }
843 } 843 }
844 844
845 void addInterceptors(ClassElement cls, Enqueuer enqueuer) { 845 void addInterceptors(ClassElement cls,
846 Enqueuer enqueuer,
847 TreeElements elements) {
846 if (enqueuer.isResolutionQueue) { 848 if (enqueuer.isResolutionQueue) {
847 cls.ensureResolved(compiler); 849 cls.ensureResolved(compiler);
848 cls.forEachMember((ClassElement classElement, Element member) { 850 cls.forEachMember((ClassElement classElement, Element member) {
849 Set<Element> set = interceptedElements.putIfAbsent( 851 Set<Element> set = interceptedElements.putIfAbsent(
850 member.name, () => new Set<Element>()); 852 member.name, () => new Set<Element>());
851 set.add(member); 853 set.add(member);
852 }, 854 },
853 includeSuperMembers: true); 855 includeSuperMembers: true);
854 } 856 }
855 enqueuer.registerInstantiatedClass(cls); 857 enqueuer.registerInstantiatedClass(cls, elements);
856 } 858 }
857 859
858 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { 860 void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
859 String name = namer.getInterceptorName(getInterceptorMethod, classes); 861 String name = namer.getInterceptorName(getInterceptorMethod, classes);
860 if (classes.contains(compiler.objectClass)) { 862 if (classes.contains(compiler.objectClass)) {
861 // We can't use a specialized [getInterceptorMethod], so we make 863 // We can't use a specialized [getInterceptorMethod], so we make
862 // sure we emit the one with all checks. 864 // sure we emit the one with all checks.
863 specializedGetInterceptors[name] = interceptedClasses; 865 specializedGetInterceptors[name] = interceptedClasses;
864 } else { 866 } else {
865 specializedGetInterceptors[name] = classes; 867 specializedGetInterceptors[name] = classes;
866 } 868 }
867 } 869 }
868 870
869 void initializeNoSuchMethod() { 871 void initializeNoSuchMethod() {
870 // In case the emitter generates noSuchMethod calls, we need to 872 // In case the emitter generates noSuchMethod calls, we need to
871 // make sure all [noSuchMethod] methods know they might take a 873 // make sure all [noSuchMethod] methods know they might take a
872 // [JsInvocationMirror] as parameter. 874 // [JsInvocationMirror] as parameter.
873 HTypeList types = new HTypeList(1); 875 HTypeList types = new HTypeList(1);
874 types[0] = new HType.nonNullExact( 876 types[0] = new HType.nonNullExact(
875 compiler.jsInvocationMirrorClass.computeType(compiler), 877 compiler.jsInvocationMirrorClass.computeType(compiler),
876 compiler); 878 compiler);
877 argumentTypes.registerDynamicInvocation(types, new Selector.noSuchMethod()); 879 argumentTypes.registerDynamicInvocation(types, new Selector.noSuchMethod());
878 } 880 }
879 881
880 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { 882 void registerInstantiatedClass(ClassElement cls,
883 Enqueuer enqueuer,
884 TreeElements elements) {
881 if (!seenAnyClass) { 885 if (!seenAnyClass) {
882 initializeNoSuchMethod(); 886 initializeNoSuchMethod();
883 seenAnyClass = true; 887 seenAnyClass = true;
884 } 888 }
885 889
886 // Register any helper that will be needed by the backend. 890 // Register any helper that will be needed by the backend.
887 if (enqueuer.isResolutionQueue) { 891 if (enqueuer.isResolutionQueue) {
888 if (cls == compiler.intClass 892 if (cls == compiler.intClass
889 || cls == compiler.doubleClass 893 || cls == compiler.doubleClass
890 || cls == compiler.numClass) { 894 || cls == compiler.numClass) {
891 // The backend will try to optimize number operations and use the 895 // The backend will try to optimize number operations and use the
892 // `iae` helper directly. 896 // `iae` helper directly.
893 enqueuer.registerStaticUse( 897 enqueuer.registerStaticUse(
894 compiler.findHelper(const SourceString('iae'))); 898 compiler.findHelper(const SourceString('iae')));
895 } else if (cls == compiler.listClass 899 } else if (cls == compiler.listClass
896 || cls == compiler.stringClass) { 900 || cls == compiler.stringClass) {
897 // The backend will try to optimize array and string access and use the 901 // The backend will try to optimize array and string access and use the
898 // `ioore` and `iae` helpers directly. 902 // `ioore` and `iae` helpers directly.
899 enqueuer.registerStaticUse( 903 enqueuer.registerStaticUse(
900 compiler.findHelper(const SourceString('ioore'))); 904 compiler.findHelper(const SourceString('ioore')));
901 enqueuer.registerStaticUse( 905 enqueuer.registerStaticUse(
902 compiler.findHelper(const SourceString('iae'))); 906 compiler.findHelper(const SourceString('iae')));
903 } else if (cls == compiler.functionClass) { 907 } else if (cls == compiler.functionClass) {
904 enqueuer.registerInstantiatedClass(compiler.closureClass); 908 enqueuer.registerInstantiatedClass(compiler.closureClass, elements);
905 } else if (cls == compiler.mapClass) { 909 } else if (cls == compiler.mapClass) {
906 // The backend will use a literal list to initialize the entries 910 // The backend will use a literal list to initialize the entries
907 // of the map. 911 // of the map.
908 enqueuer.registerInstantiatedClass(compiler.listClass); 912 enqueuer.registerInstantiatedClass(compiler.listClass, elements);
909 enqueuer.registerInstantiatedClass(compiler.mapLiteralClass); 913 enqueuer.registerInstantiatedClass(compiler.mapLiteralClass, elements);
910 enqueueInResolution(getMapMaker()); 914 enqueueInResolution(getMapMaker(), elements);
911 } 915 }
912 } 916 }
913 ClassElement result = null; 917 ClassElement result = null;
914 if (cls == compiler.stringClass) { 918 if (cls == compiler.stringClass) {
915 addInterceptors(jsStringClass, enqueuer); 919 addInterceptors(jsStringClass, enqueuer, elements);
916 } else if (cls == compiler.listClass) { 920 } else if (cls == compiler.listClass) {
917 addInterceptors(jsArrayClass, enqueuer); 921 addInterceptors(jsArrayClass, enqueuer, elements);
918 } else if (cls == compiler.intClass) { 922 } else if (cls == compiler.intClass) {
919 addInterceptors(jsIntClass, enqueuer); 923 addInterceptors(jsIntClass, enqueuer, elements);
920 addInterceptors(jsNumberClass, enqueuer); 924 addInterceptors(jsNumberClass, enqueuer, elements);
921 } else if (cls == compiler.doubleClass) { 925 } else if (cls == compiler.doubleClass) {
922 addInterceptors(jsDoubleClass, enqueuer); 926 addInterceptors(jsDoubleClass, enqueuer, elements);
923 addInterceptors(jsNumberClass, enqueuer); 927 addInterceptors(jsNumberClass, enqueuer, elements);
924 } else if (cls == compiler.functionClass) { 928 } else if (cls == compiler.functionClass) {
925 addInterceptors(jsFunctionClass, enqueuer); 929 addInterceptors(jsFunctionClass, enqueuer, elements);
926 } else if (cls == compiler.boolClass) { 930 } else if (cls == compiler.boolClass) {
927 addInterceptors(jsBoolClass, enqueuer); 931 addInterceptors(jsBoolClass, enqueuer, elements);
928 } else if (cls == compiler.nullClass) { 932 } else if (cls == compiler.nullClass) {
929 addInterceptors(jsNullClass, enqueuer); 933 addInterceptors(jsNullClass, enqueuer, elements);
930 } else if (cls == compiler.numClass) { 934 } else if (cls == compiler.numClass) {
931 addInterceptors(jsIntClass, enqueuer); 935 addInterceptors(jsIntClass, enqueuer, elements);
932 addInterceptors(jsDoubleClass, enqueuer); 936 addInterceptors(jsDoubleClass, enqueuer, elements);
933 addInterceptors(jsNumberClass, enqueuer); 937 addInterceptors(jsNumberClass, enqueuer, elements);
934 } else if (cls == compiler.mapClass) { 938 } else if (cls == compiler.mapClass) {
935 } 939 }
936 940
937 if (compiler.enableTypeAssertions) { 941 if (compiler.enableTypeAssertions) {
938 // We need to register is checks for assignments to fields. 942 // We need to register is checks for assignments to fields.
939 cls.forEachLocalMember((Element member) { 943 cls.forEachLocalMember((Element member) {
940 if (!member.isInstanceMember() || !member.isField()) return; 944 if (!member.isInstanceMember() || !member.isField()) return;
941 DartType type = member.computeType(compiler); 945 DartType type = member.computeType(compiler);
942 enqueuer.registerIsCheck(type); 946 enqueuer.registerIsCheck(type, elements);
943 }); 947 });
944 } 948 }
945 } 949 }
946 950
947 JavaScriptItemCompilationContext createItemCompilationContext() { 951 JavaScriptItemCompilationContext createItemCompilationContext() {
948 return new JavaScriptItemCompilationContext(); 952 return new JavaScriptItemCompilationContext();
949 } 953 }
950 954
951 void addBackendRtiDependencies(World world) { 955 void addBackendRtiDependencies(World world) {
952 if (jsArrayClass != null) { 956 if (jsArrayClass != null) {
953 world.registerRtiDependency(jsArrayClass, compiler.listClass); 957 world.registerRtiDependency(jsArrayClass, compiler.listClass);
954 } 958 }
955 } 959 }
956 960
957 void enqueueHelpers(ResolutionEnqueuer world) { 961 void enqueueHelpers(ResolutionEnqueuer world, TreeElements elements) {
958 jsIndexingBehaviorInterface = 962 jsIndexingBehaviorInterface =
959 compiler.findHelper(const SourceString('JavaScriptIndexingBehavior')); 963 compiler.findHelper(const SourceString('JavaScriptIndexingBehavior'));
960 if (jsIndexingBehaviorInterface != null) { 964 if (jsIndexingBehaviorInterface != null) {
961 world.registerIsCheck(jsIndexingBehaviorInterface.computeType(compiler)); 965 world.registerIsCheck(jsIndexingBehaviorInterface.computeType(compiler),
966 elements);
962 } 967 }
963 968
964 if (compiler.enableTypeAssertions) { 969 if (compiler.enableTypeAssertions) {
965 // Unconditionally register the helper that checks if the 970 // Unconditionally register the helper that checks if the
966 // expression in an if/while/for is a boolean. 971 // expression in an if/while/for is a boolean.
967 // TODO(ngeoffray): Should we have the resolver register those instead? 972 // TODO(ngeoffray): Should we have the resolver register those instead?
968 Element e = 973 Element e =
969 compiler.findHelper(const SourceString('boolConversionCheck')); 974 compiler.findHelper(const SourceString('boolConversionCheck'));
970 if (e != null) world.addToWorkList(e); 975 if (e != null) world.addToWorkList(e);
971 } 976 }
972 } 977 }
973 978
974 void registerStringInterpolation() { 979 void registerStringInterpolation(TreeElements elements) {
975 enqueueInResolution(getStringInterpolationHelper()); 980 enqueueInResolution(getStringInterpolationHelper(), elements);
976 } 981 }
977 982
978 void registerCatchStatement() { 983 void registerCatchStatement(TreeElements elements) {
979 enqueueInResolution(getExceptionUnwrapper()); 984 enqueueInResolution(getExceptionUnwrapper(), elements);
980 } 985 }
981 986
982 void registerThrow() { 987 void registerThrow(TreeElements elements) {
983 enqueueInResolution(getThrowHelper()); 988 enqueueInResolution(getThrowHelper(), elements);
984 } 989 }
985 990
986 void registerLazyField() { 991 void registerLazyField(TreeElements elements) {
987 enqueueInResolution(getCyclicThrowHelper()); 992 enqueueInResolution(getCyclicThrowHelper(), elements);
988 } 993 }
989 994
990 void registerTypeLiteral() { 995 void registerTypeLiteral(TreeElements elements) {
991 enqueueInResolution(getCreateRuntimeType()); 996 enqueueInResolution(getCreateRuntimeType(), elements);
992 } 997 }
993 998
994 void registerStackTraceInCatch() { 999 void registerStackTraceInCatch(TreeElements elements) {
995 enqueueInResolution(getTraceFromException()); 1000 enqueueInResolution(getTraceFromException(), elements);
996 } 1001 }
997 1002
998 void registerSetRuntimeType() { 1003 void registerSetRuntimeType(TreeElements elements) {
999 enqueueInResolution(getSetRuntimeTypeInfo()); 1004 enqueueInResolution(getSetRuntimeTypeInfo(), elements);
1000 } 1005 }
1001 1006
1002 void registerGetRuntimeTypeArgument() { 1007 void registerGetRuntimeTypeArgument(TreeElements elements) {
1003 enqueueInResolution(getGetRuntimeTypeArgument()); 1008 enqueueInResolution(getGetRuntimeTypeArgument(), elements);
1004 } 1009 }
1005 1010
1006 void registerRuntimeType() { 1011 void registerRuntimeType(TreeElements elements) {
1007 enqueueInResolution(getSetRuntimeTypeInfo()); 1012 enqueueInResolution(getSetRuntimeTypeInfo(), elements);
1008 enqueueInResolution(getGetRuntimeTypeInfo()); 1013 enqueueInResolution(getGetRuntimeTypeInfo(), elements);
1009 enqueueInResolution(getGetRuntimeTypeArgument()); 1014 enqueueInResolution(getGetRuntimeTypeArgument(), elements);
1010 compiler.enqueuer.resolution.registerInstantiatedClass(compiler.listClass); 1015 compiler.enqueuer.resolution.registerInstantiatedClass(
1016 compiler.listClass, elements);
1011 } 1017 }
1012 1018
1013 void registerIsCheck(DartType type, Enqueuer world) { 1019 void registerIsCheck(DartType type, Enqueuer world, TreeElements elements) {
1014 bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE; 1020 bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE;
1015 if (!type.isRaw || isTypeVariable) { 1021 if (!type.isRaw || isTypeVariable) {
1016 enqueueInResolution(getSetRuntimeTypeInfo()); 1022 enqueueInResolution(getSetRuntimeTypeInfo(), elements);
1017 enqueueInResolution(getGetRuntimeTypeInfo()); 1023 enqueueInResolution(getGetRuntimeTypeInfo(), elements);
1018 enqueueInResolution(getGetRuntimeTypeArgument()); 1024 enqueueInResolution(getGetRuntimeTypeArgument(), elements);
1019 enqueueInResolution(getCheckArguments()); 1025 enqueueInResolution(getCheckArguments(), elements);
1020 if (isTypeVariable) enqueueInResolution(getGetObjectIsSubtype()); 1026 if (isTypeVariable) {
1021 world.registerInstantiatedClass(compiler.listClass); 1027 enqueueInResolution(getGetObjectIsSubtype(), elements);
1028 }
1029 world.registerInstantiatedClass(compiler.listClass, elements);
1022 } 1030 }
1023 // [registerIsCheck] is also called for checked mode checks, so we 1031 // [registerIsCheck] is also called for checked mode checks, so we
1024 // need to register checked mode helpers. 1032 // need to register checked mode helpers.
1025 if (compiler.enableTypeAssertions) { 1033 if (compiler.enableTypeAssertions) {
1026 Element e = getCheckedModeHelper(type, typeCast: false); 1034 Element e = getCheckedModeHelper(type, typeCast: false);
1027 if (e != null) world.addToWorkList(e); 1035 if (e != null) world.addToWorkList(e);
1028 // We also need the native variant of the check (for DOM types). 1036 // We also need the native variant of the check (for DOM types).
1029 e = getNativeCheckedModeHelper(type, typeCast: false); 1037 e = getNativeCheckedModeHelper(type, typeCast: false);
1030 if (e != null) world.addToWorkList(e); 1038 if (e != null) world.addToWorkList(e);
1031 } 1039 }
1032 if (type.element.isNative()) { 1040 if (type.element.isNative()) {
1033 // We will neeed to add the "$is" and "$as" properties on the 1041 // We will neeed to add the "$is" and "$as" properties on the
1034 // JavaScript object prototype, so we make sure 1042 // JavaScript object prototype, so we make sure
1035 // [:defineProperty:] is compiled. 1043 // [:defineProperty:] is compiled.
1036 world.addToWorkList( 1044 world.addToWorkList(
1037 compiler.findHelper(const SourceString('defineProperty'))); 1045 compiler.findHelper(const SourceString('defineProperty')));
1038 } 1046 }
1039 } 1047 }
1040 1048
1041 void registerAsCheck(DartType type) { 1049 void registerAsCheck(DartType type, TreeElements elements) {
1042 Element e = getCheckedModeHelper(type, typeCast: true); 1050 Element e = getCheckedModeHelper(type, typeCast: true);
1043 enqueueInResolution(e); 1051 enqueueInResolution(e, elements);
1044 // We also need the native variant of the check (for DOM types). 1052 // We also need the native variant of the check (for DOM types).
1045 e = getNativeCheckedModeHelper(type, typeCast: true); 1053 e = getNativeCheckedModeHelper(type, typeCast: true);
1046 enqueueInResolution(e); 1054 enqueueInResolution(e, elements);
1047 } 1055 }
1048 1056
1049 void registerThrowNoSuchMethod() { 1057 void registerThrowNoSuchMethod(TreeElements elements) {
1050 enqueueInResolution(getThrowNoSuchMethod()); 1058 enqueueInResolution(getThrowNoSuchMethod(), elements);
1051 } 1059 }
1052 1060
1053 void registerThrowRuntimeError() { 1061 void registerThrowRuntimeError(TreeElements elements) {
1054 enqueueInResolution(getThrowRuntimeError()); 1062 enqueueInResolution(getThrowRuntimeError(), elements);
1055 } 1063 }
1056 1064
1057 void registerAbstractClassInstantiation() { 1065 void registerAbstractClassInstantiation(TreeElements elements) {
1058 enqueueInResolution(getThrowAbstractClassInstantiationError()); 1066 enqueueInResolution(getThrowAbstractClassInstantiationError(), elements);
1059 } 1067 }
1060 1068
1061 void registerFallThroughError() { 1069 void registerFallThroughError(TreeElements elements) {
1062 enqueueInResolution(getFallThroughError()); 1070 enqueueInResolution(getFallThroughError(), elements);
1063 } 1071 }
1064 1072
1065 void registerSuperNoSuchMethod() { 1073 void registerSuperNoSuchMethod(TreeElements elements) {
1066 enqueueInResolution(getCreateInvocationMirror()); 1074 enqueueInResolution(getCreateInvocationMirror(), elements);
1067 enqueueInResolution( 1075 enqueueInResolution(
1068 compiler.objectClass.lookupLocalMember(Compiler.NO_SUCH_METHOD)); 1076 compiler.objectClass.lookupLocalMember(Compiler.NO_SUCH_METHOD),
1069 compiler.enqueuer.resolution.registerInstantiatedClass(compiler.listClass); 1077 elements);
1078 compiler.enqueuer.resolution.registerInstantiatedClass(
1079 compiler.listClass, elements);
1070 } 1080 }
1071 1081
1072 void enqueueInResolution(Element e) { 1082 void enqueueInResolution(Element e, TreeElements elements) {
1073 if (e != null) compiler.enqueuer.resolution.addToWorkList(e); 1083 if (e == null) return;
1084 ResolutionEnqueuer enqueuer = compiler.enqueuer.resolution;
1085 enqueuer.addToWorkList(e);
1086 elements.registerDependency(e);
1074 } 1087 }
1075 1088
1076 void registerConstantMap() { 1089 void registerConstantMap(TreeElements elements) {
1077 Element e = compiler.findHelper(const SourceString('ConstantMap')); 1090 Element e = compiler.findHelper(const SourceString('ConstantMap'));
1078 if (e != null) compiler.enqueuer.resolution.registerInstantiatedClass(e); 1091 if (e != null) {
1092 compiler.enqueuer.resolution.registerInstantiatedClass(e, elements);
1093 }
1079 e = compiler.findHelper(const SourceString('ConstantProtoMap')); 1094 e = compiler.findHelper(const SourceString('ConstantProtoMap'));
1080 if (e != null) compiler.enqueuer.resolution.registerInstantiatedClass(e); 1095 if (e != null) {
1096 compiler.enqueuer.resolution.registerInstantiatedClass(e, elements);
1097 }
1081 } 1098 }
1082 1099
1083 void codegen(CodegenWorkItem work) { 1100 void codegen(CodegenWorkItem work) {
1084 Element element = work.element; 1101 Element element = work.element;
1085 if (element.kind.category == ElementCategory.VARIABLE) { 1102 if (element.kind.category == ElementCategory.VARIABLE) {
1086 Constant initialValue = compiler.constantHandler.compileWorkItem(work); 1103 Constant initialValue = compiler.constantHandler.compileWorkItem(work);
1087 if (initialValue != null) { 1104 if (initialValue != null) {
1088 return; 1105 return;
1089 } else { 1106 } else {
1090 // If the constant-handler was not able to produce a result we have to 1107 // If the constant-handler was not able to produce a result we have to
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after
1507 assert(invariant(element, element.isDeclaration)); 1524 assert(invariant(element, element.isDeclaration));
1508 generatedCode.remove(element); 1525 generatedCode.remove(element);
1509 generatedBailoutCode.remove(element); 1526 generatedBailoutCode.remove(element);
1510 compiler.enqueuer.codegen.addToWorkList(element); 1527 compiler.enqueuer.codegen.addToWorkList(element);
1511 } 1528 }
1512 1529
1513 bool isNullImplementation(ClassElement cls) { 1530 bool isNullImplementation(ClassElement cls) {
1514 return cls == jsNullClass; 1531 return cls == jsNullClass;
1515 } 1532 }
1516 } 1533 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698