| 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 const VERBOSE_OPTIMIZER_HINTS = false; | 7 const VERBOSE_OPTIMIZER_HINTS = false; |
| 8 | 8 |
| 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
| 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| (...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 | 683 |
| 684 Resolution get resolution => compiler.resolution; | 684 Resolution get resolution => compiler.resolution; |
| 685 | 685 |
| 686 /// Returns constant environment for the JavaScript interpretation of the | 686 /// Returns constant environment for the JavaScript interpretation of the |
| 687 /// constants. | 687 /// constants. |
| 688 JavaScriptConstantCompiler get constants { | 688 JavaScriptConstantCompiler get constants { |
| 689 return constantCompilerTask.jsConstantCompiler; | 689 return constantCompilerTask.jsConstantCompiler; |
| 690 } | 690 } |
| 691 | 691 |
| 692 FunctionElement resolveExternalFunction(FunctionElement element) { | 692 FunctionElement resolveExternalFunction(FunctionElement element) { |
| 693 if (isForeign(element) || element.isJsInterop) return element; | 693 if (isForeign(element) || isJsInterop(element)) return element; |
| 694 return patchResolverTask.measure(() { | 694 return patchResolverTask.measure(() { |
| 695 return patchResolverTask.resolveExternalFunction(element); | 695 return patchResolverTask.resolveExternalFunction(element); |
| 696 }); | 696 }); |
| 697 } | 697 } |
| 698 | 698 |
| 699 // TODO(karlklose): Split into findHelperFunction and findHelperClass and | 699 // TODO(karlklose): Split into findHelperFunction and findHelperClass and |
| 700 // add a check that the element has the expected kind. | 700 // add a check that the element has the expected kind. |
| 701 Element findHelper(String name) => find(jsHelperLibrary, name); | 701 Element findHelper(String name) => find(jsHelperLibrary, name); |
| 702 Element findAsyncHelper(String name) => find(asyncLibrary, name); | 702 Element findAsyncHelper(String name) => find(asyncLibrary, name); |
| 703 Element findInterceptor(String name) => find(interceptorsLibrary, name); | 703 Element findInterceptor(String name) => find(interceptorsLibrary, name); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 | 748 |
| 749 return isAccessibleByReflection(element.declaration); | 749 return isAccessibleByReflection(element.declaration); |
| 750 } | 750 } |
| 751 | 751 |
| 752 bool canBeUsedForGlobalOptimizations(Element element) { | 752 bool canBeUsedForGlobalOptimizations(Element element) { |
| 753 return !usedByBackend(element) && !invokedReflectively(element); | 753 return !usedByBackend(element) && !invokedReflectively(element); |
| 754 } | 754 } |
| 755 | 755 |
| 756 bool isInterceptorClass(ClassElement element) { | 756 bool isInterceptorClass(ClassElement element) { |
| 757 if (element == null) return false; | 757 if (element == null) return false; |
| 758 if (Elements.isNativeOrExtendsNative(element)) return true; | 758 if (isNativeOrExtendsNative(element)) return true; |
| 759 if (interceptedClasses.contains(element)) return true; | 759 if (interceptedClasses.contains(element)) return true; |
| 760 if (classesMixedIntoInterceptedClasses.contains(element)) return true; | 760 if (classesMixedIntoInterceptedClasses.contains(element)) return true; |
| 761 return false; | 761 return false; |
| 762 } | 762 } |
| 763 | 763 |
| 764 jsAst.Name registerOneShotInterceptor(Selector selector) { | 764 jsAst.Name registerOneShotInterceptor(Selector selector) { |
| 765 Set<ClassElement> classes = getInterceptedClassesOn(selector.name); | 765 Set<ClassElement> classes = getInterceptedClassesOn(selector.name); |
| 766 jsAst.Name name = namer.nameForGetOneShotInterceptor(selector, classes); | 766 jsAst.Name name = namer.nameForGetOneShotInterceptor(selector, classes); |
| 767 if (!oneShotInterceptors.containsKey(name)) { | 767 if (!oneShotInterceptors.containsKey(name)) { |
| 768 registerSpecializedGetInterceptor(classes); | 768 registerSpecializedGetInterceptor(classes); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 791 return !selector.isGetter && !compiler.hasIncrementalSupport; | 791 return !selector.isGetter && !compiler.hasIncrementalSupport; |
| 792 } | 792 } |
| 793 | 793 |
| 794 /** | 794 /** |
| 795 * Returns `true` if [member] is called from a subclass via `super`. | 795 * Returns `true` if [member] is called from a subclass via `super`. |
| 796 */ | 796 */ |
| 797 bool isAliasedSuperMember(FunctionElement member) { | 797 bool isAliasedSuperMember(FunctionElement member) { |
| 798 return aliasedSuperMembers.contains(member); | 798 return aliasedSuperMembers.contains(member); |
| 799 } | 799 } |
| 800 | 800 |
| 801 /// The JavaScript names for elements implemented via typed JavaScript |
| 802 /// interop. |
| 803 Map<Element, String> jsInteropNames = <Element, String>{}; |
| 804 |
| 805 /// The JavaScript names for native JavaScript elements implemented. |
| 806 Map<Element, String> nativeMemberName = <Element, String>{}; |
| 807 |
| 808 /// Tag info for native JavaScript classes names. See |
| 809 /// [setNativeClassTagInfo]. |
| 810 Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{}; |
| 811 |
| 812 /// Returns `true` if [element] is explicitly marked as part of JsInterop. |
| 813 bool _isJsInterop(Element element) { |
| 814 return jsInteropNames.containsKey(element.declaration); |
| 815 } |
| 816 |
| 817 /// Returns [element] as an explicit part of JsInterop. The js interop name is |
| 818 /// expected to be computed later. |
| 819 void markAsJsInterop(Element element) { |
| 820 jsInteropNames[element.declaration] = null; |
| 821 } |
| 822 |
| 823 /// Sets the explicit js interop [name] for [element]. |
| 824 void setJsInteropName(Element element, String name) { |
| 825 assert(invariant(element, |
| 826 isJsInterop(element), |
| 827 message: |
| 828 'Element $element is not js interop but given a js interop name.')); |
| 829 jsInteropNames[element.declaration] = name; |
| 830 } |
| 831 |
| 832 /// Returns the explicit js interop name for [element]. |
| 833 String getJsInteropName(Element element) { |
| 834 return jsInteropNames[element.declaration]; |
| 835 } |
| 836 |
| 837 /// Returns `true` if [element] is part of JsInterop. |
| 838 @override |
| 839 bool isJsInterop(Element element) { |
| 840 // An function is part of JsInterop in the following cases: |
| 841 // * It has a jsInteropName annotation |
| 842 // * It is external member of a class or library tagged as JsInterop. |
| 843 if (element.isFunction || element.isConstructor || element.isAccessor) { |
| 844 FunctionElement function = element; |
| 845 if (!function.isExternal) return false; |
| 846 |
| 847 if (_isJsInterop(function)) return true; |
| 848 if (function.isClassMember) return isJsInterop(function.contextClass); |
| 849 if (function.isTopLevel) return isJsInterop(function.library); |
| 850 return false; |
| 851 } else { |
| 852 return _isJsInterop(element); |
| 853 } |
| 854 } |
| 855 |
| 856 /// Returns `true` if the name of [element] is fixed for the generated |
| 857 /// JavaScript. |
| 858 bool hasFixedBackendName(Element element) { |
| 859 return isJsInterop(element) || |
| 860 nativeMemberName.containsKey(element.declaration); |
| 861 } |
| 862 |
| 863 String _jsNameHelper(Element element) { |
| 864 String jsInteropName = jsInteropNames[element.declaration]; |
| 865 assert(invariant(element, |
| 866 !(_isJsInterop(element) && jsInteropName == null), |
| 867 message: |
| 868 'Element $element is js interop but js interop name has not yet ' |
| 869 'been computed.')); |
| 870 if (jsInteropName != null && jsInteropName.isNotEmpty) { |
| 871 return jsInteropName; |
| 872 } |
| 873 return element.isLibrary ? 'self' : element.name; |
| 874 } |
| 875 |
| 876 /// Computes the name for [element] to use in the generated JavaScript. This |
| 877 /// is either given through a native annotation or a js interop annotation. |
| 878 String getFixedBackendName(Element element) { |
| 879 String name = nativeMemberName[element.declaration]; |
| 880 if (name == null && isJsInterop(element)) { |
| 881 // If an element isJsInterop but _isJsInterop is false that means it is |
| 882 // considered interop as the parent class is interop. |
| 883 name = _jsNameHelper( |
| 884 element.isConstructor ? element.enclosingClass : element); |
| 885 nativeMemberName[element.declaration] = name; |
| 886 } |
| 887 return name; |
| 888 } |
| 889 |
| 890 /// Whether [element] corresponds to a native JavaScript construct either |
| 891 /// through the native mechanism (`@Native(...)` or the `native` pseudo |
| 892 /// keyword) which is only allowed for internal libraries or via the typed |
| 893 /// JavaScriptInterop mechanism which is allowed for user libraries. |
| 894 @override |
| 895 bool isNative(Element element) { |
| 896 if (isJsInterop(element)) return true; |
| 897 if (element.isClass) { |
| 898 return nativeClassTagInfo.containsKey(element.declaration); |
| 899 } else { |
| 900 return nativeMemberName.containsKey(element.declaration); |
| 901 } |
| 902 } |
| 903 |
| 904 /// Sets the native [name] for the member [element]. This name is used for |
| 905 /// [element] in the generated JavaScript. |
| 906 void setNativeMemberName(MemberElement element, String name) { |
| 907 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer |
| 908 // might enqueue [element] several times (before processing it) and computes |
| 909 // name on each call to `internalAddToWorkList`. |
| 910 assert(invariant(element, |
| 911 nativeMemberName[element.declaration] == null || |
| 912 nativeMemberName[element.declaration] == name, |
| 913 message: |
| 914 "Native member name set inconsistently on $element: " |
| 915 "Existing name '${nativeMemberName[element.declaration]}', " |
| 916 "new name '$name'.")); |
| 917 nativeMemberName[element.declaration] = name; |
| 918 } |
| 919 |
| 920 /// Sets the native tag info for [cls]. |
| 921 /// |
| 922 /// The tag info string contains comma-separated 'words' which are either |
| 923 /// dispatch tags (having JavaScript identifier syntax) and directives that |
| 924 /// begin with `!`. |
| 925 void setNativeClassTagInfo(ClassElement cls, String tagInfo) { |
| 926 // TODO(johnniwinther): Assert that this is only called once. The memory |
| 927 // compiler copies pre-processed elements into a new compiler through |
| 928 // [Compiler.onLibraryScanned] and thereby causes multiple calls to this |
| 929 // method. |
| 930 assert(invariant(cls, |
| 931 nativeClassTagInfo[cls.declaration] == null || |
| 932 nativeClassTagInfo[cls.declaration] == tagInfo, |
| 933 message: |
| 934 "Native tag info set inconsistently on $cls: " |
| 935 "Existing tag info '${nativeClassTagInfo[cls.declaration]}', " |
| 936 "new tag info '$tagInfo'.")); |
| 937 nativeClassTagInfo[cls.declaration] = tagInfo; |
| 938 } |
| 939 |
| 940 /// Returns the list of native tag words for [cls]. |
| 941 List<String> getNativeTagsOfClassRaw(ClassElement cls) { |
| 942 String quotedName = nativeClassTagInfo[cls.declaration]; |
| 943 return quotedName.substring(1, quotedName.length - 1).split(','); |
| 944 } |
| 945 |
| 946 /// Returns the list of non-directive native tag words for [cls]. |
| 947 List<String> getNativeTagsOfClass(ClassElement cls) { |
| 948 return getNativeTagsOfClassRaw(cls).where( |
| 949 (s) => !s.startsWith('!')).toList(); |
| 950 } |
| 951 |
| 952 /// Returns `true` if [cls] has a `!nonleaf` tag word. |
| 953 bool hasNativeTagsForcedNonLeaf(ClassElement cls) { |
| 954 return getNativeTagsOfClassRaw(cls).contains('!nonleaf'); |
| 955 } |
| 956 |
| 957 bool isNativeOrExtendsNative(ClassElement element) { |
| 958 if (element == null) return false; |
| 959 if (isNative(element) || isJsInterop(element)) { |
| 960 return true; |
| 961 } |
| 962 assert(element.isResolved); |
| 963 return isNativeOrExtendsNative(element.superclass); |
| 964 } |
| 965 |
| 801 bool isInterceptedMethod(Element element) { | 966 bool isInterceptedMethod(Element element) { |
| 802 if (!element.isInstanceMember) return false; | 967 if (!element.isInstanceMember) return false; |
| 803 if (element.isGenerativeConstructorBody) { | 968 if (element.isGenerativeConstructorBody) { |
| 804 return Elements.isNativeOrExtendsNative(element.enclosingClass); | 969 return isNativeOrExtendsNative(element.enclosingClass); |
| 805 } | 970 } |
| 806 return interceptedElements[element.name] != null; | 971 return interceptedElements[element.name] != null; |
| 807 } | 972 } |
| 808 | 973 |
| 809 bool fieldHasInterceptedGetter(Element element) { | 974 bool fieldHasInterceptedGetter(Element element) { |
| 810 assert(element.isField); | 975 assert(element.isField); |
| 811 return interceptedElements[element.name] != null; | 976 return interceptedElements[element.name] != null; |
| 812 } | 977 } |
| 813 | 978 |
| 814 bool fieldHasInterceptedSetter(Element element) { | 979 bool fieldHasInterceptedSetter(Element element) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 */ | 1024 */ |
| 860 Set<ClassElement> getInterceptedClassesOn(String name) { | 1025 Set<ClassElement> getInterceptedClassesOn(String name) { |
| 861 Set<Element> intercepted = interceptedElements[name]; | 1026 Set<Element> intercepted = interceptedElements[name]; |
| 862 if (intercepted == null) return null; | 1027 if (intercepted == null) return null; |
| 863 return interceptedClassesCache.putIfAbsent(name, () { | 1028 return interceptedClassesCache.putIfAbsent(name, () { |
| 864 // Populate the cache by running through all the elements and | 1029 // Populate the cache by running through all the elements and |
| 865 // determine if the given selector applies to them. | 1030 // determine if the given selector applies to them. |
| 866 Set<ClassElement> result = new Set<ClassElement>(); | 1031 Set<ClassElement> result = new Set<ClassElement>(); |
| 867 for (Element element in intercepted) { | 1032 for (Element element in intercepted) { |
| 868 ClassElement classElement = element.enclosingClass; | 1033 ClassElement classElement = element.enclosingClass; |
| 869 if (Elements.isNativeOrExtendsNative(classElement) | 1034 if (isNativeOrExtendsNative(classElement) |
| 870 || interceptedClasses.contains(classElement)) { | 1035 || interceptedClasses.contains(classElement)) { |
| 871 result.add(classElement); | 1036 result.add(classElement); |
| 872 } | 1037 } |
| 873 if (classesMixedIntoInterceptedClasses.contains(classElement)) { | 1038 if (classesMixedIntoInterceptedClasses.contains(classElement)) { |
| 874 Set<ClassElement> nativeSubclasses = | 1039 Set<ClassElement> nativeSubclasses = |
| 875 nativeSubclassesOfMixin(classElement); | 1040 nativeSubclassesOfMixin(classElement); |
| 876 if (nativeSubclasses != null) result.addAll(nativeSubclasses); | 1041 if (nativeSubclasses != null) result.addAll(nativeSubclasses); |
| 877 } | 1042 } |
| 878 } | 1043 } |
| 879 return result; | 1044 return result; |
| 880 }); | 1045 }); |
| 881 } | 1046 } |
| 882 | 1047 |
| 883 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) { | 1048 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) { |
| 884 ClassWorld classWorld = compiler.world; | 1049 ClassWorld classWorld = compiler.world; |
| 885 Iterable<MixinApplicationElement> uses = classWorld.mixinUsesOf(mixin); | 1050 Iterable<MixinApplicationElement> uses = classWorld.mixinUsesOf(mixin); |
| 886 Set<ClassElement> result = null; | 1051 Set<ClassElement> result = null; |
| 887 for (MixinApplicationElement use in uses) { | 1052 for (MixinApplicationElement use in uses) { |
| 888 Iterable<ClassElement> subclasses = classWorld.strictSubclassesOf(use); | 1053 Iterable<ClassElement> subclasses = classWorld.strictSubclassesOf(use); |
| 889 for (ClassElement subclass in subclasses) { | 1054 for (ClassElement subclass in subclasses) { |
| 890 if (Elements.isNativeOrExtendsNative(subclass)) { | 1055 if (isNativeOrExtendsNative(subclass)) { |
| 891 if (result == null) result = new Set<ClassElement>(); | 1056 if (result == null) result = new Set<ClassElement>(); |
| 892 result.add(subclass); | 1057 result.add(subclass); |
| 893 } | 1058 } |
| 894 } | 1059 } |
| 895 } | 1060 } |
| 896 return result; | 1061 return result; |
| 897 } | 1062 } |
| 898 | 1063 |
| 899 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { | 1064 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { |
| 900 return specialOperatorEqClasses.contains( | 1065 return specialOperatorEqClasses.contains( |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1083 // The backend will use a literal list to initialize the entries | 1248 // The backend will use a literal list to initialize the entries |
| 1084 // of the map. | 1249 // of the map. |
| 1085 enqueueClass(enqueuer, compiler.listClass, registry); | 1250 enqueueClass(enqueuer, compiler.listClass, registry); |
| 1086 enqueueClass(enqueuer, mapLiteralClass, registry); | 1251 enqueueClass(enqueuer, mapLiteralClass, registry); |
| 1087 // For map literals, the dependency between the implementation class | 1252 // For map literals, the dependency between the implementation class |
| 1088 // and [Map] is not visible, so we have to add it manually. | 1253 // and [Map] is not visible, so we have to add it manually. |
| 1089 rti.registerRtiDependency(mapLiteralClass, cls); | 1254 rti.registerRtiDependency(mapLiteralClass, cls); |
| 1090 } else if (cls == boundClosureClass) { | 1255 } else if (cls == boundClosureClass) { |
| 1091 // TODO(johnniwinther): Is this a noop? | 1256 // TODO(johnniwinther): Is this a noop? |
| 1092 enqueueClass(enqueuer, boundClosureClass, registry); | 1257 enqueueClass(enqueuer, boundClosureClass, registry); |
| 1093 } else if (Elements.isNativeOrExtendsNative(cls)) { | 1258 } else if (isNativeOrExtendsNative(cls)) { |
| 1094 enqueue(enqueuer, getNativeInterceptorMethod, registry); | 1259 enqueue(enqueuer, getNativeInterceptorMethod, registry); |
| 1095 enqueueClass(enqueuer, jsInterceptorClass, compiler.globalDependencies); | 1260 enqueueClass(enqueuer, jsInterceptorClass, compiler.globalDependencies); |
| 1096 enqueueClass(enqueuer, jsJavaScriptObjectClass, registry); | 1261 enqueueClass(enqueuer, jsJavaScriptObjectClass, registry); |
| 1097 enqueueClass(enqueuer, jsPlainJavaScriptObjectClass, registry); | 1262 enqueueClass(enqueuer, jsPlainJavaScriptObjectClass, registry); |
| 1098 enqueueClass(enqueuer, jsJavaScriptFunctionClass, registry); | 1263 enqueueClass(enqueuer, jsJavaScriptFunctionClass, registry); |
| 1099 } else if (cls == mapLiteralClass) { | 1264 } else if (cls == mapLiteralClass) { |
| 1100 // For map literals, the dependency between the implementation class | 1265 // For map literals, the dependency between the implementation class |
| 1101 // and [Map] is not visible, so we have to add it manually. | 1266 // and [Map] is not visible, so we have to add it manually. |
| 1102 Element getFactory(String name, int arity) { | 1267 Element getFactory(String name, int arity) { |
| 1103 // The constructor is on the patch class, but dart2js unit tests don't | 1268 // The constructor is on the patch class, but dart2js unit tests don't |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1173 addInterceptors(jsDoubleClass, enqueuer, registry); | 1338 addInterceptors(jsDoubleClass, enqueuer, registry); |
| 1174 addInterceptors(jsNumberClass, enqueuer, registry); | 1339 addInterceptors(jsNumberClass, enqueuer, registry); |
| 1175 } else if (cls == jsJavaScriptObjectClass) { | 1340 } else if (cls == jsJavaScriptObjectClass) { |
| 1176 addInterceptors(jsJavaScriptObjectClass, enqueuer, registry); | 1341 addInterceptors(jsJavaScriptObjectClass, enqueuer, registry); |
| 1177 } else if (cls == jsPlainJavaScriptObjectClass) { | 1342 } else if (cls == jsPlainJavaScriptObjectClass) { |
| 1178 addInterceptors(jsPlainJavaScriptObjectClass, enqueuer, registry); | 1343 addInterceptors(jsPlainJavaScriptObjectClass, enqueuer, registry); |
| 1179 } else if (cls == jsUnknownJavaScriptObjectClass) { | 1344 } else if (cls == jsUnknownJavaScriptObjectClass) { |
| 1180 addInterceptors(jsUnknownJavaScriptObjectClass, enqueuer, registry); | 1345 addInterceptors(jsUnknownJavaScriptObjectClass, enqueuer, registry); |
| 1181 } else if (cls == jsJavaScriptFunctionClass) { | 1346 } else if (cls == jsJavaScriptFunctionClass) { |
| 1182 addInterceptors(jsJavaScriptFunctionClass, enqueuer, registry); | 1347 addInterceptors(jsJavaScriptFunctionClass, enqueuer, registry); |
| 1183 } else if (Elements.isNativeOrExtendsNative(cls)) { | 1348 } else if (isNativeOrExtendsNative(cls)) { |
| 1184 addInterceptorsForNativeClassMembers(cls, enqueuer); | 1349 addInterceptorsForNativeClassMembers(cls, enqueuer); |
| 1185 } else if (cls == jsIndexingBehaviorInterface) { | 1350 } else if (cls == jsIndexingBehaviorInterface) { |
| 1186 // These two helpers are used by the emitter and the codegen. | 1351 // These two helpers are used by the emitter and the codegen. |
| 1187 // Because we cannot enqueue elements at the time of emission, | 1352 // Because we cannot enqueue elements at the time of emission, |
| 1188 // we make sure they are always generated. | 1353 // we make sure they are always generated. |
| 1189 enqueue(enqueuer, findHelper('isJsIndexable'), registry); | 1354 enqueue(enqueuer, findHelper('isJsIndexable'), registry); |
| 1190 } | 1355 } |
| 1191 | 1356 |
| 1192 customElementsAnalysis.registerInstantiatedClass(cls, enqueuer); | 1357 customElementsAnalysis.registerInstantiatedClass(cls, enqueuer); |
| 1193 if (!enqueuer.isResolutionQueue) { | 1358 if (!enqueuer.isResolutionQueue) { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1342 } | 1507 } |
| 1343 // We also need the native variant of the check (for DOM types). | 1508 // We also need the native variant of the check (for DOM types). |
| 1344 helper = getNativeCheckedModeHelper(type, typeCast: false); | 1509 helper = getNativeCheckedModeHelper(type, typeCast: false); |
| 1345 if (helper != null) { | 1510 if (helper != null) { |
| 1346 enqueue(world, helper.getElement(compiler), registry); | 1511 enqueue(world, helper.getElement(compiler), registry); |
| 1347 } | 1512 } |
| 1348 } | 1513 } |
| 1349 if (!type.treatAsRaw || type.containsTypeVariables) { | 1514 if (!type.treatAsRaw || type.containsTypeVariables) { |
| 1350 enqueueClass(world, compiler.listClass, registry); | 1515 enqueueClass(world, compiler.listClass, registry); |
| 1351 } | 1516 } |
| 1352 if (type.element != null && type.element.isNative) { | 1517 if (type.element != null && isNative(type.element)) { |
| 1353 // We will neeed to add the "$is" and "$as" properties on the | 1518 // We will neeed to add the "$is" and "$as" properties on the |
| 1354 // JavaScript object prototype, so we make sure | 1519 // JavaScript object prototype, so we make sure |
| 1355 // [:defineProperty:] is compiled. | 1520 // [:defineProperty:] is compiled. |
| 1356 enqueue(world, findHelper('defineProperty'), registry); | 1521 enqueue(world, findHelper('defineProperty'), registry); |
| 1357 } | 1522 } |
| 1358 } | 1523 } |
| 1359 | 1524 |
| 1360 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, | 1525 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, |
| 1361 DartType bound) { | 1526 DartType bound) { |
| 1362 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); | 1527 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1596 | 1761 |
| 1597 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { | 1762 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { |
| 1598 return new native.NativeResolutionEnqueuer(world, compiler); | 1763 return new native.NativeResolutionEnqueuer(world, compiler); |
| 1599 } | 1764 } |
| 1600 | 1765 |
| 1601 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { | 1766 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { |
| 1602 return new native.NativeCodegenEnqueuer(world, compiler, emitter); | 1767 return new native.NativeCodegenEnqueuer(world, compiler, emitter); |
| 1603 } | 1768 } |
| 1604 | 1769 |
| 1605 ClassElement defaultSuperclass(ClassElement element) { | 1770 ClassElement defaultSuperclass(ClassElement element) { |
| 1606 if (element.isJsInterop) return jsJavaScriptObjectClass; | 1771 if (isJsInterop(element)) return jsJavaScriptObjectClass; |
| 1607 // Native classes inherit from Interceptor. | 1772 // Native classes inherit from Interceptor. |
| 1608 return element.isNative ? jsInterceptorClass : compiler.objectClass; | 1773 return isNative(element) ? jsInterceptorClass : compiler.objectClass; |
| 1609 } | 1774 } |
| 1610 | 1775 |
| 1611 /** | 1776 /** |
| 1612 * Unit test hook that returns code of an element as a String. | 1777 * Unit test hook that returns code of an element as a String. |
| 1613 * | 1778 * |
| 1614 * Invariant: [element] must be a declaration element. | 1779 * Invariant: [element] must be a declaration element. |
| 1615 */ | 1780 */ |
| 1616 String getGeneratedCode(Element element) { | 1781 String getGeneratedCode(Element element) { |
| 1617 assert(invariant(element, element.isDeclaration)); | 1782 assert(invariant(element, element.isDeclaration)); |
| 1618 return jsAst.prettyPrint(generatedCode[element], compiler).getText(); | 1783 return jsAst.prettyPrint(generatedCode[element], compiler).getText(); |
| (...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2527 lookupMapAnalysis.onCodegenStart(); | 2692 lookupMapAnalysis.onCodegenStart(); |
| 2528 } | 2693 } |
| 2529 | 2694 |
| 2530 void onElementResolved(Element element, TreeElements elements) { | 2695 void onElementResolved(Element element, TreeElements elements) { |
| 2531 if ((element.isFunction || element.isGenerativeConstructor) && | 2696 if ((element.isFunction || element.isGenerativeConstructor) && |
| 2532 annotations.noInline(element)) { | 2697 annotations.noInline(element)) { |
| 2533 inlineCache.markAsNonInlinable(element); | 2698 inlineCache.markAsNonInlinable(element); |
| 2534 } | 2699 } |
| 2535 | 2700 |
| 2536 LibraryElement library = element.library; | 2701 LibraryElement library = element.library; |
| 2537 if (!library.isPlatformLibrary && !library.canUseNative) return; | 2702 if (!library.isPlatformLibrary && !canLibraryUseNative(library)) return; |
| 2538 bool hasNoInline = false; | 2703 bool hasNoInline = false; |
| 2539 bool hasForceInline = false; | 2704 bool hasForceInline = false; |
| 2540 bool hasNoThrows = false; | 2705 bool hasNoThrows = false; |
| 2541 bool hasNoSideEffects = false; | 2706 bool hasNoSideEffects = false; |
| 2542 for (MetadataAnnotation metadata in element.implementation.metadata) { | 2707 for (MetadataAnnotation metadata in element.implementation.metadata) { |
| 2543 metadata.ensureResolved(resolution); | 2708 metadata.ensureResolved(resolution); |
| 2544 ConstantValue constantValue = | 2709 ConstantValue constantValue = |
| 2545 compiler.constants.getConstantValue(metadata.constant); | 2710 compiler.constants.getConstantValue(metadata.constant); |
| 2546 if (!constantValue.isConstructedObject) continue; | 2711 if (!constantValue.isConstructedObject) continue; |
| 2547 ObjectConstantValue value = constantValue; | 2712 ObjectConstantValue value = constantValue; |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3028 registerBackendImpact(transformed, impacts.typeVariableTypeCheck); | 3193 registerBackendImpact(transformed, impacts.typeVariableTypeCheck); |
| 3029 if (inCheckedMode) { | 3194 if (inCheckedMode) { |
| 3030 registerBackendImpact(transformed, | 3195 registerBackendImpact(transformed, |
| 3031 impacts.typeVariableCheckedModeTypeCheck); | 3196 impacts.typeVariableCheckedModeTypeCheck); |
| 3032 } | 3197 } |
| 3033 } | 3198 } |
| 3034 } | 3199 } |
| 3035 if (type is FunctionType) { | 3200 if (type is FunctionType) { |
| 3036 registerBackendImpact(transformed, impacts.functionTypeCheck); | 3201 registerBackendImpact(transformed, impacts.functionTypeCheck); |
| 3037 } | 3202 } |
| 3038 if (type.element != null && type.element.isNative) { | 3203 if (type.element != null && backend.isNative(type.element)) { |
| 3039 registerBackendImpact(transformed, impacts.nativeTypeCheck); | 3204 registerBackendImpact(transformed, impacts.nativeTypeCheck); |
| 3040 } | 3205 } |
| 3041 } | 3206 } |
| 3042 } | 3207 } |
| 3043 | 3208 |
| 3044 /// Records that [constant] is used by the element behind [registry]. | 3209 /// Records that [constant] is used by the element behind [registry]. |
| 3045 class Dependency { | 3210 class Dependency { |
| 3046 final ConstantValue constant; | 3211 final ConstantValue constant; |
| 3047 final Element annotatedElement; | 3212 final Element annotatedElement; |
| 3048 | 3213 |
| 3049 const Dependency(this.constant, this.annotatedElement); | 3214 const Dependency(this.constant, this.annotatedElement); |
| 3050 } | 3215 } |
| 3051 | 3216 |
| OLD | NEW |