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 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 |