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 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
258 /// True if a call to disableTreeShaking has been seen. | 258 /// True if a call to disableTreeShaking has been seen. |
259 bool isTreeShakingDisabled = false; | 259 bool isTreeShakingDisabled = false; |
260 | 260 |
261 /// True if there isn't sufficient @MirrorsUsed data. | 261 /// True if there isn't sufficient @MirrorsUsed data. |
262 bool hasInsufficientMirrorsUsed = false; | 262 bool hasInsufficientMirrorsUsed = false; |
263 | 263 |
264 /// List of constants from metadata. If metadata must be preserved, | 264 /// List of constants from metadata. If metadata must be preserved, |
265 /// these constants must be registered. | 265 /// these constants must be registered. |
266 final List<Dependency> metadataConstants = <Dependency>[]; | 266 final List<Dependency> metadataConstants = <Dependency>[]; |
267 | 267 |
268 /// List of symbols that the user has requested for reflection. | |
269 final Set<String> symbolsUsed = new Set<String>(); | |
270 | |
271 /// List of elements that the user has requested for reflection. | 268 /// List of elements that the user has requested for reflection. |
272 final Set<Element> targetsUsed = new Set<Element>(); | 269 final Set<Element> targetsUsed = new Set<Element>(); |
273 | 270 |
274 /// List of annotations provided by user that indicate that the annotated | 271 /// List of annotations provided by user that indicate that the annotated |
275 /// element must be retained. | 272 /// element must be retained. |
276 final Set<Element> metaTargetsUsed = new Set<Element>(); | 273 final Set<Element> metaTargetsUsed = new Set<Element>(); |
277 | 274 |
275 /// Set of methods that are needed by reflection. Computed using | |
276 /// [computeMembersNeededForReflection] on first use. | |
277 Iterable<Element> _membersNeededForReflection = null; | |
278 Iterable<Element> get membersNeededForReflection { | |
279 assert(_membersNeededForReflection != null); | |
280 return _membersNeededForReflection; | |
281 } | |
282 | |
283 /// List of symbols that the user has requested for reflection. | |
284 final Set<String> symbolsUsed = new Set<String>(); | |
285 | |
278 /// List of elements that the backend may use. | 286 /// List of elements that the backend may use. |
279 final Set<Element> helpersUsed = new Set<Element>(); | 287 final Set<Element> helpersUsed = new Set<Element>(); |
280 | 288 |
281 | |
282 /// Set of typedefs that are used as type literals. | 289 /// Set of typedefs that are used as type literals. |
283 final Set<TypedefElement> typedefTypeLiterals = new Set<TypedefElement>(); | 290 final Set<TypedefElement> typedefTypeLiterals = new Set<TypedefElement>(); |
284 | 291 |
285 /// All the checked mode helpers. | 292 /// All the checked mode helpers. |
286 static const checkedModeHelpers = CheckedModeHelper.helpers; | 293 static const checkedModeHelpers = CheckedModeHelper.helpers; |
287 | 294 |
288 // Checked mode helpers indexed by name. | 295 // Checked mode helpers indexed by name. |
289 Map<String, CheckedModeHelper> checkedModeHelperByName = | 296 Map<String, CheckedModeHelper> checkedModeHelperByName = |
290 new Map<String, CheckedModeHelper>.fromIterable( | 297 new Map<String, CheckedModeHelper>.fromIterable( |
291 checkedModeHelpers, | 298 checkedModeHelpers, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
346 if (invokedReflectively(element.enclosingElement)) return true; | 353 if (invokedReflectively(element.enclosingElement)) return true; |
347 } | 354 } |
348 | 355 |
349 if (element.isField) { | 356 if (element.isField) { |
350 if (Elements.isStaticOrTopLevel(element) | 357 if (Elements.isStaticOrTopLevel(element) |
351 && (element.isFinal || element.isConst)) { | 358 && (element.isFinal || element.isConst)) { |
352 return false; | 359 return false; |
353 } | 360 } |
354 } | 361 } |
355 | 362 |
356 return isNeededForReflection(element.declaration); | 363 return isAccessibleByReflection(element.declaration); |
357 } | 364 } |
358 | 365 |
359 bool canBeUsedForGlobalOptimizations(Element element) { | 366 bool canBeUsedForGlobalOptimizations(Element element) { |
360 return !usedByBackend(element) && !invokedReflectively(element); | 367 return !usedByBackend(element) && !invokedReflectively(element); |
361 } | 368 } |
362 | 369 |
363 bool isInterceptorClass(ClassElement element) { | 370 bool isInterceptorClass(ClassElement element) { |
364 if (element == null) return false; | 371 if (element == null) return false; |
365 if (Elements.isNativeOrExtendsNative(element)) return true; | 372 if (Elements.isNativeOrExtendsNative(element)) return true; |
366 if (interceptedClasses.contains(element)) return true; | 373 if (interceptedClasses.contains(element)) return true; |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
767 if (e != null) enqueue(world, e, registry); | 774 if (e != null) enqueue(world, e, registry); |
768 } | 775 } |
769 if (TRACE_CALLS) { | 776 if (TRACE_CALLS) { |
770 traceHelper = compiler.findHelper('traceHelper'); | 777 traceHelper = compiler.findHelper('traceHelper'); |
771 assert(traceHelper != null); | 778 assert(traceHelper != null); |
772 enqueueInResolution(traceHelper, registry); | 779 enqueueInResolution(traceHelper, registry); |
773 } | 780 } |
774 registerCheckedModeHelpers(registry); | 781 registerCheckedModeHelpers(registry); |
775 } | 782 } |
776 | 783 |
777 onResolutionComplete() => rti.computeClassesNeedingRti(); | 784 onResolutionComplete() { |
785 computeMembersNeededForReflection(); | |
786 rti.computeClassesNeedingRti(); | |
787 } | |
778 | 788 |
779 void onStringInterpolation(Registry registry) { | 789 void onStringInterpolation(Registry registry) { |
780 assert(registry.isForResolution); | 790 assert(registry.isForResolution); |
781 registerBackendStaticInvocation(getStringInterpolationHelper(), registry); | 791 registerBackendStaticInvocation(getStringInterpolationHelper(), registry); |
782 } | 792 } |
783 | 793 |
784 void onCatchStatement(Registry registry) { | 794 void onCatchStatement(Registry registry) { |
785 assert(registry.isForResolution); | 795 assert(registry.isForResolution); |
786 registerBackendStaticInvocation(getExceptionUnwrapper(), registry); | 796 registerBackendStaticInvocation(getExceptionUnwrapper(), registry); |
787 registerBackendInstantiation(jsPlainJavaScriptObjectClass, registry); | 797 registerBackendInstantiation(jsPlainJavaScriptObjectClass, registry); |
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1567 /// Called when resolving the `Symbol` constructor. | 1577 /// Called when resolving the `Symbol` constructor. |
1568 void onSymbolConstructor(Registry registry) { | 1578 void onSymbolConstructor(Registry registry) { |
1569 assert(registry.isForResolution); | 1579 assert(registry.isForResolution); |
1570 // Make sure that _internals.Symbol.validated is registered. | 1580 // Make sure that _internals.Symbol.validated is registered. |
1571 assert(compiler.symbolValidatedConstructor != null); | 1581 assert(compiler.symbolValidatedConstructor != null); |
1572 registerBackendStaticInvocation(compiler.symbolValidatedConstructor, | 1582 registerBackendStaticInvocation(compiler.symbolValidatedConstructor, |
1573 registry); | 1583 registry); |
1574 } | 1584 } |
1575 | 1585 |
1576 /// Should [element] (a getter) be retained for reflection? | 1586 /// Should [element] (a getter) be retained for reflection? |
1577 bool shouldRetainGetter(Element element) => isNeededForReflection(element); | 1587 bool shouldRetainGetter(Element element) { |
1588 return isAccessibleByReflection(element); | |
1589 } | |
1578 | 1590 |
1579 /// Should [element] (a setter) be retained for reflection? | 1591 /// Should [element] (a setter) be retained for reflection? |
1580 bool shouldRetainSetter(Element element) => isNeededForReflection(element); | 1592 bool shouldRetainSetter(Element element) { |
1593 return isAccessibleByReflection(element); | |
1594 } | |
1581 | 1595 |
1582 /// Should [name] be retained for reflection? | 1596 /// Should [name] be retained for reflection? |
1583 bool shouldRetainName(String name) { | 1597 bool shouldRetainName(String name) { |
1584 if (hasInsufficientMirrorsUsed) return mustPreserveNames; | 1598 if (hasInsufficientMirrorsUsed) return mustPreserveNames; |
1585 if (name == '') return false; | 1599 if (name == '') return false; |
1586 return symbolsUsed.contains(name); | 1600 return symbolsUsed.contains(name); |
1587 } | 1601 } |
1588 | 1602 |
1589 bool get rememberLazies => isTreeShakingDisabled; | 1603 bool get rememberLazies => isTreeShakingDisabled; |
1590 | 1604 |
1591 bool retainMetadataOf(Element element) { | 1605 bool retainMetadataOf(Element element) { |
1592 if (mustRetainMetadata) hasRetainedMetadata = true; | 1606 if (mustRetainMetadata) hasRetainedMetadata = true; |
1593 if (mustRetainMetadata && isNeededForReflection(element)) { | 1607 if (mustRetainMetadata && referencedFromMirrorSystem(element)) { |
1594 for (MetadataAnnotation metadata in element.metadata) { | 1608 for (MetadataAnnotation metadata in element.metadata) { |
1595 metadata.ensureResolved(compiler); | 1609 metadata.ensureResolved(compiler); |
1596 Constant constant = constants.getConstantForMetadata(metadata); | 1610 Constant constant = constants.getConstantForMetadata(metadata); |
1597 constants.addCompileTimeConstantForEmission(constant); | 1611 constants.addCompileTimeConstantForEmission(constant); |
1598 } | 1612 } |
1599 return true; | 1613 return true; |
1600 } | 1614 } |
1601 return false; | 1615 return false; |
1602 } | 1616 } |
1603 | 1617 |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1768 /** | 1782 /** |
1769 * Returns `true` if [element] can be accessed through reflection, that is, | 1783 * Returns `true` if [element] can be accessed through reflection, that is, |
1770 * is in the set of elements covered by a `MirrorsUsed` annotation. | 1784 * is in the set of elements covered by a `MirrorsUsed` annotation. |
1771 * | 1785 * |
1772 * This property is used to tag emitted elements with a marker which is | 1786 * This property is used to tag emitted elements with a marker which is |
1773 * checked by the runtime system to throw an exception if an element is | 1787 * checked by the runtime system to throw an exception if an element is |
1774 * accessed (invoked, get, set) that is not accessible for the reflective | 1788 * accessed (invoked, get, set) that is not accessible for the reflective |
1775 * system. | 1789 * system. |
1776 */ | 1790 */ |
1777 bool isAccessibleByReflection(Element element) { | 1791 bool isAccessibleByReflection(Element element) { |
1778 // TODO(ahe): This isn't sufficient: simply importing dart:mirrors | 1792 if (element.isClass) { |
1779 // causes hasInsufficientMirrorsUsed to become true. | 1793 element = getDartClass(element); |
1780 if (hasInsufficientMirrorsUsed) return true; | 1794 } |
1781 return isNeededForReflection(element); | 1795 // We have to treat closure classes specially here, as they only come into |
1796 // existence after [membersNeededForReflection] has been computed. | |
1797 if (element is SynthesizedCallMethodElementX) { | |
1798 SynthesizedCallMethodElementX closure = element; | |
1799 element = closure.expression; | |
Johnni Winther
2014/06/27 07:43:01
This could also be computed as closure.closureClas
herhut
2014/06/27 12:34:37
I think we have decided not to expose those fields
| |
1800 } else if (element is ClosureClassElement) { | |
1801 ClosureClassElement closure = element; | |
1802 element = closure.methodElement; | |
1803 } | |
1804 return membersNeededForReflection.contains(element); | |
1782 } | 1805 } |
1783 | 1806 |
1784 /** | 1807 /** |
1785 * Returns `true` if the emitter must emit the element even though there | 1808 * Returns true if the element has to be resolved due to a mirrorsUsed |
1786 * is no direct use in the program, but because the reflective system may | 1809 * annotation. If we have insufficient mirrors used annotations, we only |
1787 * need to access it. | 1810 * keep additonal elements if treeshaking has been disabled. |
1788 */ | 1811 */ |
1789 bool isNeededForReflection(Element element) { | 1812 bool requiredByMirrorSystem(Element element) { |
1790 if (!isTreeShakingDisabled) return false; | 1813 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || |
1791 element = getDartClass(element); | 1814 matchesMirrorsMetaTarget(element) || |
1792 if (hasInsufficientMirrorsUsed) return isTreeShakingDisabled; | 1815 targetsUsed.contains(element); |
1793 /// Record the name of [element] in [symbolsUsed]. Return true for | 1816 } |
1794 /// convenience. | |
1795 bool registerNameOf(Element element) { | |
1796 symbolsUsed.add(element.name); | |
1797 if (element.isConstructor) { | |
1798 symbolsUsed.add(element.enclosingClass.name); | |
1799 } | |
1800 return true; | |
1801 } | |
1802 | 1817 |
1803 Element enclosing = element.enclosingElement; | 1818 /** |
1804 if (enclosing != null && isNeededForReflection(enclosing)) { | 1819 * Returns true of the element matches a mirrorsUsed annotation. If |
Johnni Winther
2014/06/27 07:43:01
'of' -> 'if'.
herhut
2014/06/27 12:34:37
Done.
| |
1805 return registerNameOf(element); | 1820 * we have insufficient mirrorsUsed information, this returns true for |
1806 } | 1821 * all elements, as they might all be potentially referenced. |
1822 */ | |
1823 bool referencedFromMirrorSystem(Element element, [recursive = true]) { | |
1824 Element enclosing = recursive ? element.enclosingElement : null; | |
1807 | 1825 |
1808 if (isNeededThroughMetaTarget(element)) { | 1826 return hasInsufficientMirrorsUsed || |
1809 return registerNameOf(element); | 1827 matchesMirrorsMetaTarget(element) || |
1810 } | 1828 targetsUsed.contains(element) || |
1811 | 1829 (enclosing != null && referencedFromMirrorSystem(enclosing)); |
1812 if (!targetsUsed.isEmpty && targetsUsed.contains(element)) { | |
1813 return registerNameOf(element); | |
1814 } | |
1815 | |
1816 // TODO(kasperl): Consider caching this information. It is consulted | |
1817 // multiple times because of the way we deal with the enclosing element. | |
1818 return false; | |
1819 } | 1830 } |
1820 | 1831 |
1821 /** | 1832 /** |
1822 * Returns `true` if the element is needed because it has an annotation | 1833 * Returns `true` if the element is needed because it has an annotation |
1823 * of a type that is used as a meta target for reflection. | 1834 * of a type that is used as a meta target for reflection. |
1824 */ | 1835 */ |
1825 bool isNeededThroughMetaTarget(Element element) { | 1836 bool matchesMirrorsMetaTarget(Element element) { |
1826 if (metaTargetsUsed.isEmpty) return false; | 1837 if (metaTargetsUsed.isEmpty) return false; |
1827 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { | 1838 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { |
1828 MetadataAnnotation metadata = link.head; | 1839 MetadataAnnotation metadata = link.head; |
1829 // TODO(kasperl): It would be nice if we didn't have to resolve | 1840 // TODO(kasperl): It would be nice if we didn't have to resolve |
1830 // all metadata but only stuff that potentially would match one | 1841 // all metadata but only stuff that potentially would match one |
1831 // of the used meta targets. | 1842 // of the used meta targets. |
1832 metadata.ensureResolved(compiler); | 1843 metadata.ensureResolved(compiler); |
1833 Constant value = metadata.value; | 1844 Constant value = metadata.value; |
1834 if (value == null) continue; | 1845 if (value == null) continue; |
1835 DartType type = value.computeType(compiler); | 1846 DartType type = value.computeType(compiler); |
1836 if (metaTargetsUsed.contains(type.element)) return true; | 1847 if (metaTargetsUsed.contains(type.element)) return true; |
1837 } | 1848 } |
1838 return false; | 1849 return false; |
1839 } | 1850 } |
1840 | 1851 |
1852 /** | |
1853 * Visits all classes and computes whether its members are needed for | |
1854 * reflection. | |
1855 * | |
1856 * We have to precompute this set as we cannot easily answer the need for | |
1857 * reflection locally when looking at the member: We lack the information by | |
1858 * which classes a member is inherited. Called after resolution is complete. | |
1859 * | |
1860 * We filter out private libraries here, as their elements should not | |
1861 * be visible by reflection unless some other interfaces makes them | |
1862 * accessible. | |
1863 */ | |
1864 computeMembersNeededForReflection() { | |
1865 if (_membersNeededForReflection != null) return; | |
1866 if (compiler.mirrorsLibrary == null) { | |
1867 _membersNeededForReflection = const []; | |
1868 } | |
1869 // Compute a mapping from class to the closures it contains, so we | |
1870 // can include include the correct ones when including the class. | |
Johnni Winther
2014/06/27 07:43:01
'include include' -> 'include'.
herhut
2014/06/27 12:34:37
Done.
| |
1871 Map<ClassElement, List<Element>> closureMap = | |
1872 new Map<ClassElement, List<Element>>(); | |
1873 for (Element clos in compiler.resolverWorld.allClosures) { | |
Johnni Winther
2014/06/27 07:43:01
'Element clos' -> 'FunctionElement closure'.
herhut
2014/06/27 12:34:37
Done.
| |
1874 closureMap.putIfAbsent(clos.enclosingClass, () => []).add(clos); | |
1875 } | |
1876 Set<Element> reflectableMembers = new Set<Element>(); | |
1877 ResolutionEnqueuer resolution = compiler.enqueuer.resolution; | |
1878 for (ClassElement cls in resolution.universe.instantiatedClasses) { | |
1879 // Do not process internal classes. | |
1880 if (cls.library.isInternalLibrary) continue; | |
1881 if (cls.isInjected) continue; | |
Johnni Winther
2014/06/27 07:43:01
Merge conditions.
herhut
2014/06/27 12:34:37
Done.
| |
1882 if (referencedFromMirrorSystem(cls)) { | |
1883 Set<Name> memberNames = new LinkedHashSet<Name>( | |
karlklose
2014/06/27 07:45:57
Consider moving this logic to its own method.
herhut
2014/06/27 12:34:37
It has side effects on reflectableMembers and I'd
| |
1884 equals: (Name a, Name b) => a.isSimilarTo(b), | |
1885 hashCode: (Name a) => a.similarHashCode); | |
1886 // 1) the class (should be life) | |
Johnni Winther
2014/06/27 07:43:01
'life' -> 'live' here and more below.
karlklose
2014/06/27 07:45:57
'life' -> 'live'. (Also below.)
herhut
2014/06/27 12:34:37
Done.
herhut
2014/06/27 12:34:37
Done.
| |
1887 assert(invariant(cls, resolution.isLive(cls))); | |
1888 reflectableMembers.add(cls); | |
1889 // 2) its constructors (if life) | |
1890 cls.constructors.forEach((Element constructor) { | |
karlklose
2014/06/27 07:45:57
How about:
cls.constructors
.where(resolut
herhut
2014/06/27 12:34:37
constructors is a Link<Element> and has no filter
| |
1891 if (resolution.isLive(constructor)) { | |
1892 reflectableMembers.add(constructor); | |
1893 } | |
1894 }); | |
1895 // 3) all members, including fields via getter/setters (if life) | |
1896 cls.forEachClassMember((Member member) { | |
1897 if (resolution.isLive(member.element)) { | |
1898 memberNames.add(member.name); | |
1899 reflectableMembers.add(member.element); | |
1900 } | |
1901 }); | |
1902 // 4) all overriding members of subclasses/subtypes (should be life) | |
1903 if (compiler.world.hasAnySubtype(cls)) { | |
1904 for (ClassElement subcls in compiler.world.subtypesOf(cls)) { | |
1905 subcls.forEachClassMember((Member member) { | |
1906 if (memberNames.contains(member.name)) { | |
1907 assert(invariant(member.element, | |
1908 resolution.isLive(member.element))); | |
1909 reflectableMembers.add(member.element); | |
1910 } | |
1911 }); | |
1912 } | |
1913 } | |
1914 // 5) all its closures | |
1915 List<Element> closures = closureMap[cls]; | |
1916 if (closures != null) { | |
1917 reflectableMembers.addAll(closures); | |
1918 } | |
1919 } else { | |
1920 // check members themselves | |
1921 cls.constructors.forEach((ConstructorElement element) { | |
karlklose
2014/06/27 07:45:57
Could you share the code of this closure with the
herhut
2014/06/27 12:34:37
I would need an adapter anyway from member to memb
| |
1922 if (!compiler.enqueuer.resolution.isLive(element)) return; | |
Johnni Winther
2014/06/27 07:43:01
[cls] should be live if the constructor is.
herhut
2014/06/27 12:34:37
Yes, but [cls] is not reflectable. This handles th
| |
1923 if (referencedFromMirrorSystem(element, false)) { | |
1924 reflectableMembers.add(element); | |
1925 } | |
1926 }); | |
1927 cls.forEachClassMember((Member member) { | |
1928 if (!compiler.enqueuer.resolution.isLive(member.element)) return; | |
1929 if (referencedFromMirrorSystem(member.element, false)) { | |
1930 reflectableMembers.add(member.element); | |
1931 } | |
1932 }); | |
1933 // Also add in closures | |
1934 List<Element> closures = closureMap[cls]; | |
1935 if (closures != null) { | |
1936 for (Element closure in closures) { | |
1937 if (referencedFromMirrorSystem(closure.enclosingMember, false)) { | |
1938 reflectableMembers.add(closure); | |
1939 } | |
1940 } | |
1941 } | |
1942 } | |
1943 } | |
1944 // We also need top-level non-class elements like static functions and | |
1945 // global fields. We use the resolution queue to decide which elements are | |
1946 // part of the live world. | |
1947 for (LibraryElement lib in compiler.libraries.values) { | |
1948 if (lib.isInternalLibrary) continue; | |
1949 lib.forEachLocalMember((Element member) { | |
1950 if (!member.isClass && | |
1951 compiler.enqueuer.resolution.isLive(member) && | |
1952 referencedFromMirrorSystem(member)) { | |
1953 reflectableMembers.add(member); | |
1954 } | |
1955 }); | |
1956 } | |
1957 // Lastly, we add in all the closures found if they match. | |
1958 for (Element clos in compiler.resolverWorld.allClosures) { | |
Johnni Winther
2014/06/27 07:43:01
'Element clos' -> 'FunctionElement closure'.
herhut
2014/06/27 12:34:37
Done.
| |
1959 if (clos.enclosingMember == null || | |
1960 referencedFromMirrorSystem(clos.enclosingMember)) { | |
1961 reflectableMembers.add(clos); | |
1962 } | |
1963 } | |
1964 // And their superclasses. | |
1965 reflectableMembers.add(compiler.closureClass); | |
Johnni Winther
2014/06/27 07:43:01
Only if 'allClosures' is non-empty?
herhut
2014/06/27 12:34:37
The [Closure] class could still be part of a Mirro
| |
1966 reflectableMembers.add(compiler.boundClosureClass); | |
Johnni Winther
2014/06/27 07:43:01
Only if we have tear-offs?
herhut
2014/06/27 12:34:37
See above.
| |
1967 // Register all symbols of reflectable elements | |
1968 for (Element element in reflectableMembers) { | |
1969 symbolsUsed.add(element.name); | |
1970 } | |
1971 _membersNeededForReflection = reflectableMembers; | |
1972 } | |
1973 | |
1841 jsAst.Call generateIsJsIndexableCall(jsAst.Expression use1, | 1974 jsAst.Call generateIsJsIndexableCall(jsAst.Expression use1, |
1842 jsAst.Expression use2) { | 1975 jsAst.Expression use2) { |
1843 String dispatchPropertyName = 'init.dispatchPropertyName'; | 1976 String dispatchPropertyName = 'init.dispatchPropertyName'; |
1844 | 1977 |
1845 // We pass the dispatch property record to the isJsIndexable | 1978 // We pass the dispatch property record to the isJsIndexable |
1846 // helper rather than reading it inside the helper to increase the | 1979 // helper rather than reading it inside the helper to increase the |
1847 // chance of making the dispatch record access monomorphic. | 1980 // chance of making the dispatch record access monomorphic. |
1848 jsAst.PropertyAccess record = new jsAst.PropertyAccess( | 1981 jsAst.PropertyAccess record = new jsAst.PropertyAccess( |
1849 use2, js(dispatchPropertyName)); | 1982 use2, js(dispatchPropertyName)); |
1850 | 1983 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1893 if (target.isField) { | 2026 if (target.isField) { |
1894 staticFields.add(target); | 2027 staticFields.add(target); |
1895 } else if (target.isLibrary || target.isClass) { | 2028 } else if (target.isLibrary || target.isClass) { |
1896 addFieldsInContainer(target); | 2029 addFieldsInContainer(target); |
1897 } | 2030 } |
1898 } | 2031 } |
1899 return staticFields; | 2032 return staticFields; |
1900 } | 2033 } |
1901 | 2034 |
1902 /// Called when [enqueuer] is empty, but before it is closed. | 2035 /// Called when [enqueuer] is empty, but before it is closed. |
1903 void onQueueEmpty(Enqueuer enqueuer) { | 2036 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) { |
1904 // Add elements referenced only via custom elements. Return early if any | 2037 // Add elements referenced only via custom elements. Return early if any |
1905 // elements are added to avoid counting the elements as due to mirrors. | 2038 // elements are added to avoid counting the elements as due to mirrors. |
1906 customElementsAnalysis.onQueueEmpty(enqueuer); | 2039 customElementsAnalysis.onQueueEmpty(enqueuer); |
1907 if (!enqueuer.queueIsEmpty) return; | 2040 if (!enqueuer.queueIsEmpty) return false; |
1908 | 2041 |
1909 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) { | 2042 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) { |
1910 preMirrorsMethodCount = generatedCode.length; | 2043 preMirrorsMethodCount = generatedCode.length; |
1911 } | 2044 } |
1912 | 2045 |
1913 if (isTreeShakingDisabled) { | 2046 if (isTreeShakingDisabled) { |
1914 enqueuer.enqueueEverything(); | 2047 enqueuer.enqueueReflectiveElements(recentClasses); |
1915 } else if (!targetsUsed.isEmpty && enqueuer.isResolutionQueue) { | 2048 } else if (!targetsUsed.isEmpty && enqueuer.isResolutionQueue) { |
1916 // Add all static elements (not classes) that have been requested for | 2049 // Add all static elements (not classes) that have been requested for |
1917 // reflection. If there is no mirror-usage these are probably not | 2050 // reflection. If there is no mirror-usage these are probably not |
1918 // necessary, but the backend relies on them being resolved. | 2051 // necessary, but the backend relies on them being resolved. |
1919 enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets()); | 2052 enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets()); |
1920 } | 2053 } |
1921 | 2054 |
1922 if (mustPreserveNames) compiler.log('Preserving names.'); | 2055 if (mustPreserveNames) compiler.log('Preserving names.'); |
1923 | 2056 |
1924 if (mustRetainMetadata) { | 2057 if (mustRetainMetadata) { |
1925 compiler.log('Retaining metadata.'); | 2058 compiler.log('Retaining metadata.'); |
1926 | 2059 |
1927 compiler.libraries.values.forEach(retainMetadataOf); | 2060 compiler.libraries.values.forEach(retainMetadataOf); |
1928 for (Dependency dependency in metadataConstants) { | 2061 for (Dependency dependency in metadataConstants) { |
1929 registerCompileTimeConstant( | 2062 registerCompileTimeConstant( |
1930 dependency.constant, dependency.registry); | 2063 dependency.constant, dependency.registry); |
1931 } | 2064 } |
1932 metadataConstants.clear(); | 2065 metadataConstants.clear(); |
1933 } | 2066 } |
2067 return true; | |
1934 } | 2068 } |
1935 | 2069 |
1936 void onElementResolved(Element element, TreeElements elements) { | 2070 void onElementResolved(Element element, TreeElements elements) { |
1937 LibraryElement library = element.library; | 2071 LibraryElement library = element.library; |
1938 if (!library.isPlatformLibrary && !library.canUseNative) return; | 2072 if (!library.isPlatformLibrary && !library.canUseNative) return; |
1939 bool hasNoInline = false; | 2073 bool hasNoInline = false; |
1940 bool hasNoThrows = false; | 2074 bool hasNoThrows = false; |
1941 bool hasNoSideEffects = false; | 2075 bool hasNoSideEffects = false; |
1942 for (MetadataAnnotation metadata in element.metadata) { | 2076 for (MetadataAnnotation metadata in element.metadata) { |
1943 metadata.ensureResolved(compiler); | 2077 metadata.ensureResolved(compiler); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1993 } | 2127 } |
1994 | 2128 |
1995 /// Records that [constant] is used by the element behind [registry]. | 2129 /// Records that [constant] is used by the element behind [registry]. |
1996 class Dependency { | 2130 class Dependency { |
1997 final Constant constant; | 2131 final Constant constant; |
1998 // TODO(johnniwinther): Change to [Element] when dependency nodes are added. | 2132 // TODO(johnniwinther): Change to [Element] when dependency nodes are added. |
1999 final Registry registry; | 2133 final Registry registry; |
2000 | 2134 |
2001 const Dependency(this.constant, this.registry); | 2135 const Dependency(this.constant, this.registry); |
2002 } | 2136 } |
OLD | NEW |