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