OLD | NEW |
---|---|
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 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
845 void addInterceptors(ClassElement cls, Enqueuer enqueuer) { | 845 void addInterceptors(ClassElement cls, Enqueuer enqueuer) { |
846 if (enqueuer.isResolutionQueue) { | 846 if (enqueuer.isResolutionQueue) { |
847 cls.ensureResolved(compiler); | 847 cls.ensureResolved(compiler); |
848 cls.forEachMember((ClassElement classElement, Element member) { | 848 cls.forEachMember((ClassElement classElement, Element member) { |
849 Set<Element> set = interceptedElements.putIfAbsent( | 849 Set<Element> set = interceptedElements.putIfAbsent( |
850 member.name, () => new Set<Element>()); | 850 member.name, () => new Set<Element>()); |
851 set.add(member); | 851 set.add(member); |
852 }, | 852 }, |
853 includeSuperMembers: true); | 853 includeSuperMembers: true); |
854 } | 854 } |
855 enqueuer.registerInstantiatedClass(cls); | 855 // This is a true global dependency. |
kasperl
2013/03/06 20:39:43
Extend comment to explain why? You could also add
ahe
2013/03/06 20:54:03
Actually, I need to think more about this. How ma
| |
856 enqueuer.registerInstantiatedClass(cls, compiler.globalDependencies); | |
856 } | 857 } |
857 | 858 |
858 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { | 859 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { |
859 String name = namer.getInterceptorName(getInterceptorMethod, classes); | 860 String name = namer.getInterceptorName(getInterceptorMethod, classes); |
860 if (classes.contains(compiler.objectClass)) { | 861 if (classes.contains(compiler.objectClass)) { |
861 // We can't use a specialized [getInterceptorMethod], so we make | 862 // We can't use a specialized [getInterceptorMethod], so we make |
862 // sure we emit the one with all checks. | 863 // sure we emit the one with all checks. |
863 specializedGetInterceptors[name] = interceptedClasses; | 864 specializedGetInterceptors[name] = interceptedClasses; |
864 } else { | 865 } else { |
865 specializedGetInterceptors[name] = classes; | 866 specializedGetInterceptors[name] = classes; |
866 } | 867 } |
867 } | 868 } |
868 | 869 |
869 void initializeNoSuchMethod() { | 870 void initializeNoSuchMethod() { |
870 // In case the emitter generates noSuchMethod calls, we need to | 871 // In case the emitter generates noSuchMethod calls, we need to |
871 // make sure all [noSuchMethod] methods know they might take a | 872 // make sure all [noSuchMethod] methods know they might take a |
872 // [JsInvocationMirror] as parameter. | 873 // [JsInvocationMirror] as parameter. |
873 HTypeList types = new HTypeList(1); | 874 HTypeList types = new HTypeList(1); |
874 types[0] = new HType.nonNullExact( | 875 types[0] = new HType.nonNullExact( |
875 compiler.jsInvocationMirrorClass.computeType(compiler), | 876 compiler.jsInvocationMirrorClass.computeType(compiler), |
876 compiler); | 877 compiler); |
877 argumentTypes.registerDynamicInvocation(types, new Selector.noSuchMethod()); | 878 argumentTypes.registerDynamicInvocation(types, new Selector.noSuchMethod()); |
878 } | 879 } |
879 | 880 |
880 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { | 881 void registerInstantiatedClass(ClassElement cls, |
882 Enqueuer enqueuer, | |
883 TreeElements elements) { | |
881 if (!seenAnyClass) { | 884 if (!seenAnyClass) { |
882 initializeNoSuchMethod(); | 885 initializeNoSuchMethod(); |
883 seenAnyClass = true; | 886 seenAnyClass = true; |
884 } | 887 } |
885 | 888 |
886 // Register any helper that will be needed by the backend. | 889 // Register any helper that will be needed by the backend. |
887 if (enqueuer.isResolutionQueue) { | 890 if (enqueuer.isResolutionQueue) { |
888 if (cls == compiler.intClass | 891 if (cls == compiler.intClass |
889 || cls == compiler.doubleClass | 892 || cls == compiler.doubleClass |
890 || cls == compiler.numClass) { | 893 || cls == compiler.numClass) { |
891 // The backend will try to optimize number operations and use the | 894 // The backend will try to optimize number operations and use the |
892 // `iae` helper directly. | 895 // `iae` helper directly. |
893 enqueuer.registerStaticUse( | 896 enqueuer.registerStaticUse( |
894 compiler.findHelper(const SourceString('iae'))); | 897 compiler.findHelper(const SourceString('iae'))); |
895 } else if (cls == compiler.listClass | 898 } else if (cls == compiler.listClass |
896 || cls == compiler.stringClass) { | 899 || cls == compiler.stringClass) { |
897 // The backend will try to optimize array and string access and use the | 900 // The backend will try to optimize array and string access and use the |
898 // `ioore` and `iae` helpers directly. | 901 // `ioore` and `iae` helpers directly. |
899 enqueuer.registerStaticUse( | 902 enqueuer.registerStaticUse( |
900 compiler.findHelper(const SourceString('ioore'))); | 903 compiler.findHelper(const SourceString('ioore'))); |
901 enqueuer.registerStaticUse( | 904 enqueuer.registerStaticUse( |
902 compiler.findHelper(const SourceString('iae'))); | 905 compiler.findHelper(const SourceString('iae'))); |
903 } else if (cls == compiler.functionClass) { | 906 } else if (cls == compiler.functionClass) { |
904 enqueuer.registerInstantiatedClass(compiler.closureClass); | 907 enqueuer.registerInstantiatedClass(compiler.closureClass, elements); |
905 } else if (cls == compiler.mapClass) { | 908 } else if (cls == compiler.mapClass) { |
906 // The backend will use a literal list to initialize the entries | 909 // The backend will use a literal list to initialize the entries |
907 // of the map. | 910 // of the map. |
908 enqueuer.registerInstantiatedClass(compiler.listClass); | 911 enqueuer.registerInstantiatedClass(compiler.listClass, elements); |
909 enqueuer.registerInstantiatedClass(compiler.mapLiteralClass); | 912 enqueuer.registerInstantiatedClass(compiler.mapLiteralClass, elements); |
910 enqueueInResolution(getMapMaker()); | 913 enqueueInResolution(getMapMaker(), elements); |
911 } | 914 } |
912 } | 915 } |
913 ClassElement result = null; | 916 ClassElement result = null; |
914 if (cls == compiler.stringClass) { | 917 if (cls == compiler.stringClass) { |
915 addInterceptors(jsStringClass, enqueuer); | 918 addInterceptors(jsStringClass, enqueuer); |
916 } else if (cls == compiler.listClass) { | 919 } else if (cls == compiler.listClass) { |
917 addInterceptors(jsArrayClass, enqueuer); | 920 addInterceptors(jsArrayClass, enqueuer); |
918 } else if (cls == compiler.intClass) { | 921 } else if (cls == compiler.intClass) { |
919 addInterceptors(jsIntClass, enqueuer); | 922 addInterceptors(jsIntClass, enqueuer); |
920 addInterceptors(jsNumberClass, enqueuer); | 923 addInterceptors(jsNumberClass, enqueuer); |
(...skipping 11 matching lines...) Expand all Loading... | |
932 addInterceptors(jsDoubleClass, enqueuer); | 935 addInterceptors(jsDoubleClass, enqueuer); |
933 addInterceptors(jsNumberClass, enqueuer); | 936 addInterceptors(jsNumberClass, enqueuer); |
934 } else if (cls == compiler.mapClass) { | 937 } else if (cls == compiler.mapClass) { |
935 } | 938 } |
936 | 939 |
937 if (compiler.enableTypeAssertions) { | 940 if (compiler.enableTypeAssertions) { |
938 // We need to register is checks for assignments to fields. | 941 // We need to register is checks for assignments to fields. |
939 cls.forEachLocalMember((Element member) { | 942 cls.forEachLocalMember((Element member) { |
940 if (!member.isInstanceMember() || !member.isField()) return; | 943 if (!member.isInstanceMember() || !member.isField()) return; |
941 DartType type = member.computeType(compiler); | 944 DartType type = member.computeType(compiler); |
942 enqueuer.registerIsCheck(type); | 945 enqueuer.registerIsCheck(type, elements); |
943 }); | 946 }); |
944 } | 947 } |
945 } | 948 } |
946 | 949 |
947 JavaScriptItemCompilationContext createItemCompilationContext() { | 950 JavaScriptItemCompilationContext createItemCompilationContext() { |
948 return new JavaScriptItemCompilationContext(); | 951 return new JavaScriptItemCompilationContext(); |
949 } | 952 } |
950 | 953 |
951 void addBackendRtiDependencies(World world) { | 954 void addBackendRtiDependencies(World world) { |
952 if (jsArrayClass != null) { | 955 if (jsArrayClass != null) { |
953 world.registerRtiDependency(jsArrayClass, compiler.listClass); | 956 world.registerRtiDependency(jsArrayClass, compiler.listClass); |
954 } | 957 } |
955 } | 958 } |
956 | 959 |
957 void enqueueHelpers(ResolutionEnqueuer world) { | 960 void enqueueHelpers(ResolutionEnqueuer world) { |
958 jsIndexingBehaviorInterface = | 961 jsIndexingBehaviorInterface = |
959 compiler.findHelper(const SourceString('JavaScriptIndexingBehavior')); | 962 compiler.findHelper(const SourceString('JavaScriptIndexingBehavior')); |
960 if (jsIndexingBehaviorInterface != null) { | 963 if (jsIndexingBehaviorInterface != null) { |
961 world.registerIsCheck(jsIndexingBehaviorInterface.computeType(compiler)); | 964 world.registerIsCheck(jsIndexingBehaviorInterface.computeType(compiler), |
965 // This is a true global dependency. | |
966 compiler.globalDependencies); | |
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 } | 1040 } |
1033 | 1041 |
1034 void registerAsCheck(DartType type) { | 1042 void registerAsCheck(DartType type, TreeElements elements) { |
1035 Element e = getCheckedModeHelper(type, typeCast: true); | 1043 Element e = getCheckedModeHelper(type, typeCast: true); |
1036 enqueueInResolution(e); | 1044 enqueueInResolution(e, elements); |
1037 // We also need the native variant of the check (for DOM types). | 1045 // We also need the native variant of the check (for DOM types). |
1038 e = getNativeCheckedModeHelper(type, typeCast: true); | 1046 e = getNativeCheckedModeHelper(type, typeCast: true); |
1039 enqueueInResolution(e); | 1047 enqueueInResolution(e, elements); |
1040 } | 1048 } |
1041 | 1049 |
1042 void registerThrowNoSuchMethod() { | 1050 void registerThrowNoSuchMethod(TreeElements elements) { |
1043 enqueueInResolution(getThrowNoSuchMethod()); | 1051 enqueueInResolution(getThrowNoSuchMethod(), elements); |
1044 } | 1052 } |
1045 | 1053 |
1046 void registerThrowRuntimeError() { | 1054 void registerThrowRuntimeError(TreeElements elements) { |
1047 enqueueInResolution(getThrowRuntimeError()); | 1055 enqueueInResolution(getThrowRuntimeError(), elements); |
1048 } | 1056 } |
1049 | 1057 |
1050 void registerAbstractClassInstantiation() { | 1058 void registerAbstractClassInstantiation(TreeElements elements) { |
1051 enqueueInResolution(getThrowAbstractClassInstantiationError()); | 1059 enqueueInResolution(getThrowAbstractClassInstantiationError(), elements); |
1052 } | 1060 } |
1053 | 1061 |
1054 void registerFallThroughError() { | 1062 void registerFallThroughError(TreeElements elements) { |
1055 enqueueInResolution(getFallThroughError()); | 1063 enqueueInResolution(getFallThroughError(), elements); |
1056 } | 1064 } |
1057 | 1065 |
1058 void registerSuperNoSuchMethod() { | 1066 void registerSuperNoSuchMethod(TreeElements elements) { |
1059 enqueueInResolution(getCreateInvocationMirror()); | 1067 enqueueInResolution(getCreateInvocationMirror(), elements); |
1060 enqueueInResolution( | 1068 enqueueInResolution( |
1061 compiler.objectClass.lookupLocalMember(Compiler.NO_SUCH_METHOD)); | 1069 compiler.objectClass.lookupLocalMember(Compiler.NO_SUCH_METHOD), |
1062 compiler.enqueuer.resolution.registerInstantiatedClass(compiler.listClass); | 1070 elements); |
1071 compiler.enqueuer.resolution.registerInstantiatedClass( | |
1072 compiler.listClass, elements); | |
1063 } | 1073 } |
1064 | 1074 |
1065 void enqueueInResolution(Element e) { | 1075 void enqueueInResolution(Element e, TreeElements elements) { |
1066 if (e != null) compiler.enqueuer.resolution.addToWorkList(e); | 1076 if (e == null) return; |
1077 ResolutionEnqueuer enqueuer = compiler.enqueuer.resolution; | |
1078 enqueuer.addToWorkList(e); | |
1079 elements.registerBackendDependency(e); | |
1067 } | 1080 } |
1068 | 1081 |
1069 void registerConstantMap() { | 1082 void registerConstantMap(TreeElements elements) { |
1070 Element e = compiler.findHelper(const SourceString('ConstantMap')); | 1083 Element e = compiler.findHelper(const SourceString('ConstantMap')); |
1071 if (e != null) compiler.enqueuer.resolution.registerInstantiatedClass(e); | 1084 if (e != null) { |
1085 compiler.enqueuer.resolution.registerInstantiatedClass(e, elements); | |
1086 } | |
1072 e = compiler.findHelper(const SourceString('ConstantProtoMap')); | 1087 e = compiler.findHelper(const SourceString('ConstantProtoMap')); |
1073 if (e != null) compiler.enqueuer.resolution.registerInstantiatedClass(e); | 1088 if (e != null) { |
1089 compiler.enqueuer.resolution.registerInstantiatedClass(e, elements); | |
1090 } | |
1074 } | 1091 } |
1075 | 1092 |
1076 void codegen(CodegenWorkItem work) { | 1093 void codegen(CodegenWorkItem work) { |
1077 Element element = work.element; | 1094 Element element = work.element; |
1078 if (element.kind.category == ElementCategory.VARIABLE) { | 1095 if (element.kind.category == ElementCategory.VARIABLE) { |
1079 Constant initialValue = compiler.constantHandler.compileWorkItem(work); | 1096 Constant initialValue = compiler.constantHandler.compileWorkItem(work); |
1080 if (initialValue != null) { | 1097 if (initialValue != null) { |
1081 return; | 1098 return; |
1082 } else { | 1099 } else { |
1083 // If the constant-handler was not able to produce a result we have to | 1100 // If the constant-handler was not able to produce a result we have to |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1496 * | 1513 * |
1497 * Invariant: [element] must be a declaration element. | 1514 * Invariant: [element] must be a declaration element. |
1498 */ | 1515 */ |
1499 void eagerRecompile(Element element) { | 1516 void eagerRecompile(Element element) { |
1500 assert(invariant(element, element.isDeclaration)); | 1517 assert(invariant(element, element.isDeclaration)); |
1501 generatedCode.remove(element); | 1518 generatedCode.remove(element); |
1502 generatedBailoutCode.remove(element); | 1519 generatedBailoutCode.remove(element); |
1503 compiler.enqueuer.codegen.addToWorkList(element); | 1520 compiler.enqueuer.codegen.addToWorkList(element); |
1504 } | 1521 } |
1505 } | 1522 } |
OLD | NEW |