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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 static final Uri DART_JS_MIRRORS = | 61 static final Uri DART_JS_MIRRORS = |
62 new Uri(scheme: 'dart', path: '_js_mirrors'); | 62 new Uri(scheme: 'dart', path: '_js_mirrors'); |
63 static final Uri DART_JS_NAMES = | 63 static final Uri DART_JS_NAMES = |
64 new Uri(scheme: 'dart', path: '_js_names'); | 64 new Uri(scheme: 'dart', path: '_js_names'); |
65 static final Uri DART_ISOLATE_HELPER = | 65 static final Uri DART_ISOLATE_HELPER = |
66 new Uri(scheme: 'dart', path: '_isolate_helper'); | 66 new Uri(scheme: 'dart', path: '_isolate_helper'); |
67 | 67 |
68 static const String INVOKE_ON = '_getCachedInvocation'; | 68 static const String INVOKE_ON = '_getCachedInvocation'; |
69 static const String START_ROOT_ISOLATE = 'startRootIsolate'; | 69 static const String START_ROOT_ISOLATE = 'startRootIsolate'; |
70 | 70 |
| 71 /// Set of classes that need to be considered for reflection although not |
| 72 /// otherwise visible during resolution. |
| 73 Iterable<ClassElement> get classesRequiredForReflection { |
| 74 // TODO(herhut): Clean this up when classes needed for rti are tracked. |
| 75 return [closureClass, jsIndexableClass]; |
| 76 } |
| 77 |
71 SsaBuilderTask builder; | 78 SsaBuilderTask builder; |
72 SsaOptimizerTask optimizer; | 79 SsaOptimizerTask optimizer; |
73 SsaCodeGeneratorTask generator; | 80 SsaCodeGeneratorTask generator; |
74 CodeEmitterTask emitter; | 81 CodeEmitterTask emitter; |
75 | 82 |
76 /** | 83 /** |
77 * The generated code as a js AST for compiled methods. | 84 * The generated code as a js AST for compiled methods. |
78 */ | 85 */ |
79 Map<Element, jsAst.Expression> get generatedCode { | 86 Map<Element, jsAst.Expression> get generatedCode { |
80 return compiler.enqueuer.codegen.generatedCode; | 87 return compiler.enqueuer.codegen.generatedCode; |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 /// True if a call to disableTreeShaking has been seen. | 287 /// True if a call to disableTreeShaking has been seen. |
281 bool isTreeShakingDisabled = false; | 288 bool isTreeShakingDisabled = false; |
282 | 289 |
283 /// True if there isn't sufficient @MirrorsUsed data. | 290 /// True if there isn't sufficient @MirrorsUsed data. |
284 bool hasInsufficientMirrorsUsed = false; | 291 bool hasInsufficientMirrorsUsed = false; |
285 | 292 |
286 /// List of constants from metadata. If metadata must be preserved, | 293 /// List of constants from metadata. If metadata must be preserved, |
287 /// these constants must be registered. | 294 /// these constants must be registered. |
288 final List<Dependency> metadataConstants = <Dependency>[]; | 295 final List<Dependency> metadataConstants = <Dependency>[]; |
289 | 296 |
290 /// List of symbols that the user has requested for reflection. | |
291 final Set<String> symbolsUsed = new Set<String>(); | |
292 | |
293 /// List of elements that the user has requested for reflection. | 297 /// List of elements that the user has requested for reflection. |
294 final Set<Element> targetsUsed = new Set<Element>(); | 298 final Set<Element> targetsUsed = new Set<Element>(); |
295 | 299 |
296 /// List of annotations provided by user that indicate that the annotated | 300 /// List of annotations provided by user that indicate that the annotated |
297 /// element must be retained. | 301 /// element must be retained. |
298 final Set<Element> metaTargetsUsed = new Set<Element>(); | 302 final Set<Element> metaTargetsUsed = new Set<Element>(); |
299 | 303 |
| 304 /// Set of methods that are needed by reflection. Computed using |
| 305 /// [computeMembersNeededForReflection] on first use. |
| 306 Iterable<Element> _membersNeededForReflection = null; |
| 307 Iterable<Element> get membersNeededForReflection { |
| 308 assert(_membersNeededForReflection != null); |
| 309 return _membersNeededForReflection; |
| 310 } |
| 311 |
| 312 /// List of symbols that the user has requested for reflection. |
| 313 final Set<String> symbolsUsed = new Set<String>(); |
| 314 |
300 /// List of elements that the backend may use. | 315 /// List of elements that the backend may use. |
301 final Set<Element> helpersUsed = new Set<Element>(); | 316 final Set<Element> helpersUsed = new Set<Element>(); |
302 | 317 |
303 | |
304 /// Set of typedefs that are used as type literals. | 318 /// Set of typedefs that are used as type literals. |
305 final Set<TypedefElement> typedefTypeLiterals = new Set<TypedefElement>(); | 319 final Set<TypedefElement> typedefTypeLiterals = new Set<TypedefElement>(); |
306 | 320 |
307 /// All the checked mode helpers. | 321 /// All the checked mode helpers. |
308 static const checkedModeHelpers = CheckedModeHelper.helpers; | 322 static const checkedModeHelpers = CheckedModeHelper.helpers; |
309 | 323 |
310 // Checked mode helpers indexed by name. | 324 // Checked mode helpers indexed by name. |
311 Map<String, CheckedModeHelper> checkedModeHelperByName = | 325 Map<String, CheckedModeHelper> checkedModeHelperByName = |
312 new Map<String, CheckedModeHelper>.fromIterable( | 326 new Map<String, CheckedModeHelper>.fromIterable( |
313 checkedModeHelpers, | 327 checkedModeHelpers, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 if (invokedReflectively(element.enclosingElement)) return true; | 399 if (invokedReflectively(element.enclosingElement)) return true; |
386 } | 400 } |
387 | 401 |
388 if (element.isField) { | 402 if (element.isField) { |
389 if (Elements.isStaticOrTopLevel(element) | 403 if (Elements.isStaticOrTopLevel(element) |
390 && (element.isFinal || element.isConst)) { | 404 && (element.isFinal || element.isConst)) { |
391 return false; | 405 return false; |
392 } | 406 } |
393 } | 407 } |
394 | 408 |
395 return isNeededForReflection(element.declaration); | 409 return isAccessibleByReflection(element.declaration); |
396 } | 410 } |
397 | 411 |
398 bool canBeUsedForGlobalOptimizations(Element element) { | 412 bool canBeUsedForGlobalOptimizations(Element element) { |
399 return !usedByBackend(element) && !invokedReflectively(element); | 413 return !usedByBackend(element) && !invokedReflectively(element); |
400 } | 414 } |
401 | 415 |
402 bool isInterceptorClass(ClassElement element) { | 416 bool isInterceptorClass(ClassElement element) { |
403 if (element == null) return false; | 417 if (element == null) return false; |
404 if (Elements.isNativeOrExtendsNative(element)) return true; | 418 if (Elements.isNativeOrExtendsNative(element)) return true; |
405 if (interceptedClasses.contains(element)) return true; | 419 if (interceptedClasses.contains(element)) return true; |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 if (e != null) enqueue(world, e, registry); | 804 if (e != null) enqueue(world, e, registry); |
791 } | 805 } |
792 if (TRACE_CALLS) { | 806 if (TRACE_CALLS) { |
793 traceHelper = findHelper('traceHelper'); | 807 traceHelper = findHelper('traceHelper'); |
794 assert(traceHelper != null); | 808 assert(traceHelper != null); |
795 enqueueInResolution(traceHelper, registry); | 809 enqueueInResolution(traceHelper, registry); |
796 } | 810 } |
797 registerCheckedModeHelpers(registry); | 811 registerCheckedModeHelpers(registry); |
798 } | 812 } |
799 | 813 |
800 onResolutionComplete() => rti.computeClassesNeedingRti(); | 814 onResolutionComplete() { |
| 815 computeMembersNeededForReflection(); |
| 816 rti.computeClassesNeedingRti(); |
| 817 } |
801 | 818 |
802 void registerGetRuntimeTypeArgument(Registry registry) { | 819 void registerGetRuntimeTypeArgument(Registry registry) { |
803 enqueueInResolution(getGetRuntimeTypeArgument(), registry); | 820 enqueueInResolution(getGetRuntimeTypeArgument(), registry); |
804 enqueueInResolution(getGetTypeArgumentByIndex(), registry); | 821 enqueueInResolution(getGetTypeArgumentByIndex(), registry); |
805 enqueueInResolution(getCopyTypeArguments(), registry); | 822 enqueueInResolution(getCopyTypeArguments(), registry); |
806 } | 823 } |
807 | 824 |
808 void registerGenericCallMethod(Element callMethod, | 825 void registerGenericCallMethod(Element callMethod, |
809 Enqueuer enqueuer, Registry registry) { | 826 Enqueuer enqueuer, Registry registry) { |
810 if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) { | 827 if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) { |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 symbolsUsed.add(name); | 1455 symbolsUsed.add(name); |
1439 if (name.endsWith('=')) { | 1456 if (name.endsWith('=')) { |
1440 symbolsUsed.add(name.substring(0, name.length - 1)); | 1457 symbolsUsed.add(name.substring(0, name.length - 1)); |
1441 } | 1458 } |
1442 } | 1459 } |
1443 | 1460 |
1444 /// Called when [:new Symbol(...):] is seen. | 1461 /// Called when [:new Symbol(...):] is seen. |
1445 void registerNewSymbol(Registry registry) { | 1462 void registerNewSymbol(Registry registry) { |
1446 } | 1463 } |
1447 | 1464 |
1448 /// Should [element] (a getter) be retained for reflection? | 1465 /// Should [element] (a getter) that would normally not be generated due to |
1449 bool shouldRetainGetter(Element element) => isNeededForReflection(element); | 1466 /// treeshaking be retained for reflection? |
| 1467 bool shouldRetainGetter(Element element) { |
| 1468 return isTreeShakingDisabled && isAccessibleByReflection(element); |
| 1469 } |
1450 | 1470 |
1451 /// Should [element] (a setter) be retained for reflection? | 1471 /// Should [element] (a setter) hat would normally not be generated due to |
1452 bool shouldRetainSetter(Element element) => isNeededForReflection(element); | 1472 /// treeshaking be retained for reflection? |
| 1473 bool shouldRetainSetter(Element element) { |
| 1474 return isTreeShakingDisabled && isAccessibleByReflection(element); |
| 1475 } |
1453 | 1476 |
1454 /// Should [name] be retained for reflection? | 1477 /// Should [name] be retained for reflection? |
1455 bool shouldRetainName(String name) { | 1478 bool shouldRetainName(String name) { |
1456 if (hasInsufficientMirrorsUsed) return mustPreserveNames; | 1479 if (hasInsufficientMirrorsUsed) return mustPreserveNames; |
1457 if (name == '') return false; | 1480 if (name == '') return false; |
1458 return symbolsUsed.contains(name); | 1481 return symbolsUsed.contains(name); |
1459 } | 1482 } |
1460 | 1483 |
1461 bool get rememberLazies => isTreeShakingDisabled; | 1484 bool get rememberLazies => isTreeShakingDisabled; |
1462 | 1485 |
1463 bool retainMetadataOf(Element element) { | 1486 bool retainMetadataOf(Element element) { |
1464 if (mustRetainMetadata) hasRetainedMetadata = true; | 1487 if (mustRetainMetadata) hasRetainedMetadata = true; |
1465 if (mustRetainMetadata && isNeededForReflection(element)) { | 1488 if (mustRetainMetadata && referencedFromMirrorSystem(element)) { |
1466 for (MetadataAnnotation metadata in element.metadata) { | 1489 for (MetadataAnnotation metadata in element.metadata) { |
1467 metadata.ensureResolved(compiler); | 1490 metadata.ensureResolved(compiler); |
1468 Constant constant = constants.getConstantForMetadata(metadata); | 1491 Constant constant = constants.getConstantForMetadata(metadata); |
1469 constants.addCompileTimeConstantForEmission(constant); | 1492 constants.addCompileTimeConstantForEmission(constant); |
1470 } | 1493 } |
1471 return true; | 1494 return true; |
1472 } | 1495 } |
1473 return false; | 1496 return false; |
1474 } | 1497 } |
1475 | 1498 |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1682 /** | 1705 /** |
1683 * Returns `true` if [element] can be accessed through reflection, that is, | 1706 * Returns `true` if [element] can be accessed through reflection, that is, |
1684 * is in the set of elements covered by a `MirrorsUsed` annotation. | 1707 * is in the set of elements covered by a `MirrorsUsed` annotation. |
1685 * | 1708 * |
1686 * This property is used to tag emitted elements with a marker which is | 1709 * This property is used to tag emitted elements with a marker which is |
1687 * checked by the runtime system to throw an exception if an element is | 1710 * checked by the runtime system to throw an exception if an element is |
1688 * accessed (invoked, get, set) that is not accessible for the reflective | 1711 * accessed (invoked, get, set) that is not accessible for the reflective |
1689 * system. | 1712 * system. |
1690 */ | 1713 */ |
1691 bool isAccessibleByReflection(Element element) { | 1714 bool isAccessibleByReflection(Element element) { |
1692 // TODO(ahe): This isn't sufficient: simply importing dart:mirrors | 1715 if (element.isClass) { |
1693 // causes hasInsufficientMirrorsUsed to become true. | 1716 element = getDartClass(element); |
1694 if (hasInsufficientMirrorsUsed) return true; | 1717 } |
1695 return isNeededForReflection(element); | 1718 // We have to treat closure classes specially here, as they only come into |
| 1719 // existence after [membersNeededForReflection] has been computed. |
| 1720 if (element is SynthesizedCallMethodElementX) { |
| 1721 SynthesizedCallMethodElementX closure = element; |
| 1722 element = closure.expression; |
| 1723 } else if (element is ClosureClassElement) { |
| 1724 ClosureClassElement closure = element; |
| 1725 element = closure.methodElement; |
| 1726 } |
| 1727 return membersNeededForReflection.contains(element); |
1696 } | 1728 } |
1697 | 1729 |
1698 /** | 1730 /** |
1699 * Returns `true` if the emitter must emit the element even though there | 1731 * Returns true if the element has to be resolved due to a mirrorsUsed |
1700 * is no direct use in the program, but because the reflective system may | 1732 * annotation. If we have insufficient mirrors used annotations, we only |
1701 * need to access it. | 1733 * keep additonal elements if treeshaking has been disabled. |
1702 */ | 1734 */ |
1703 bool isNeededForReflection(Element element) { | 1735 bool requiredByMirrorSystem(Element element) { |
1704 if (!isTreeShakingDisabled) return false; | 1736 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || |
1705 element = getDartClass(element); | 1737 matchesMirrorsMetaTarget(element) || |
1706 if (hasInsufficientMirrorsUsed) return isTreeShakingDisabled; | 1738 targetsUsed.contains(element); |
1707 /// Record the name of [element] in [symbolsUsed]. Return true for | 1739 } |
1708 /// convenience. | |
1709 bool registerNameOf(Element element) { | |
1710 symbolsUsed.add(element.name); | |
1711 if (element.isConstructor) { | |
1712 symbolsUsed.add(element.enclosingClass.name); | |
1713 } | |
1714 return true; | |
1715 } | |
1716 | 1740 |
1717 Element enclosing = element.enclosingElement; | 1741 /** |
1718 if (enclosing != null && isNeededForReflection(enclosing)) { | 1742 * Returns true if the element matches a mirrorsUsed annotation. If |
1719 return registerNameOf(element); | 1743 * we have insufficient mirrorsUsed information, this returns true for |
1720 } | 1744 * all elements, as they might all be potentially referenced. |
| 1745 */ |
| 1746 bool referencedFromMirrorSystem(Element element, [recursive = true]) { |
| 1747 Element enclosing = recursive ? element.enclosingElement : null; |
1721 | 1748 |
1722 if (isNeededThroughMetaTarget(element)) { | 1749 return hasInsufficientMirrorsUsed || |
1723 return registerNameOf(element); | 1750 matchesMirrorsMetaTarget(element) || |
1724 } | 1751 targetsUsed.contains(element) || |
1725 | 1752 (enclosing != null && referencedFromMirrorSystem(enclosing)); |
1726 if (!targetsUsed.isEmpty && targetsUsed.contains(element)) { | |
1727 return registerNameOf(element); | |
1728 } | |
1729 | |
1730 // TODO(kasperl): Consider caching this information. It is consulted | |
1731 // multiple times because of the way we deal with the enclosing element. | |
1732 return false; | |
1733 } | 1753 } |
1734 | 1754 |
1735 /** | 1755 /** |
1736 * Returns `true` if the element is needed because it has an annotation | 1756 * Returns `true` if the element is needed because it has an annotation |
1737 * of a type that is used as a meta target for reflection. | 1757 * of a type that is used as a meta target for reflection. |
1738 */ | 1758 */ |
1739 bool isNeededThroughMetaTarget(Element element) { | 1759 bool matchesMirrorsMetaTarget(Element element) { |
1740 if (metaTargetsUsed.isEmpty) return false; | 1760 if (metaTargetsUsed.isEmpty) return false; |
1741 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { | 1761 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { |
1742 MetadataAnnotation metadata = link.head; | 1762 MetadataAnnotation metadata = link.head; |
1743 // TODO(kasperl): It would be nice if we didn't have to resolve | 1763 // TODO(kasperl): It would be nice if we didn't have to resolve |
1744 // all metadata but only stuff that potentially would match one | 1764 // all metadata but only stuff that potentially would match one |
1745 // of the used meta targets. | 1765 // of the used meta targets. |
1746 metadata.ensureResolved(compiler); | 1766 metadata.ensureResolved(compiler); |
1747 Constant value = metadata.value; | 1767 Constant value = metadata.value; |
1748 if (value == null) continue; | 1768 if (value == null) continue; |
1749 DartType type = value.computeType(compiler); | 1769 DartType type = value.computeType(compiler); |
1750 if (metaTargetsUsed.contains(type.element)) return true; | 1770 if (metaTargetsUsed.contains(type.element)) return true; |
1751 } | 1771 } |
1752 return false; | 1772 return false; |
1753 } | 1773 } |
1754 | 1774 |
| 1775 /** |
| 1776 * Visits all classes and computes whether its members are needed for |
| 1777 * reflection. |
| 1778 * |
| 1779 * We have to precompute this set as we cannot easily answer the need for |
| 1780 * reflection locally when looking at the member: We lack the information by |
| 1781 * which classes a member is inherited. Called after resolution is complete. |
| 1782 * |
| 1783 * We filter out private libraries here, as their elements should not |
| 1784 * be visible by reflection unless some other interfaces makes them |
| 1785 * accessible. |
| 1786 */ |
| 1787 computeMembersNeededForReflection() { |
| 1788 if (_membersNeededForReflection != null) return; |
| 1789 if (compiler.mirrorsLibrary == null) { |
| 1790 _membersNeededForReflection = const []; |
| 1791 } |
| 1792 // Compute a mapping from class to the closures it contains, so we |
| 1793 // can include the correct ones when including the class. |
| 1794 Map<ClassElement, List<Element>> closureMap = |
| 1795 new Map<ClassElement, List<Element>>(); |
| 1796 for (FunctionElement closure in compiler.resolverWorld.allClosures) { |
| 1797 closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure); |
| 1798 } |
| 1799 bool foundClosure = false; |
| 1800 Set<Element> reflectableMembers = new Set<Element>(); |
| 1801 ResolutionEnqueuer resolution = compiler.enqueuer.resolution; |
| 1802 for (ClassElement cls in resolution.universe.instantiatedClasses) { |
| 1803 // Do not process internal classes. |
| 1804 if (cls.library.isInternalLibrary || cls.isInjected) continue; |
| 1805 if (referencedFromMirrorSystem(cls)) { |
| 1806 Set<Name> memberNames = new LinkedHashSet<Name>( |
| 1807 equals: (Name a, Name b) => a.isSimilarTo(b), |
| 1808 hashCode: (Name a) => a.similarHashCode); |
| 1809 // 1) the class (should be live) |
| 1810 assert(invariant(cls, resolution.isLive(cls))); |
| 1811 reflectableMembers.add(cls); |
| 1812 // 2) its constructors (if live) |
| 1813 cls.constructors.forEach((Element constructor) { |
| 1814 if (resolution.isLive(constructor)) { |
| 1815 reflectableMembers.add(constructor); |
| 1816 } |
| 1817 }); |
| 1818 // 3) all members, including fields via getter/setters (if live) |
| 1819 cls.forEachClassMember((Member member) { |
| 1820 if (resolution.isLive(member.element)) { |
| 1821 memberNames.add(member.name); |
| 1822 reflectableMembers.add(member.element); |
| 1823 } |
| 1824 }); |
| 1825 // 4) all overriding members of subclasses/subtypes (should be live) |
| 1826 if (compiler.world.hasAnySubtype(cls)) { |
| 1827 for (ClassElement subcls in compiler.world.subtypesOf(cls)) { |
| 1828 subcls.forEachClassMember((Member member) { |
| 1829 if (memberNames.contains(member.name)) { |
| 1830 assert(invariant(member.element, |
| 1831 resolution.isLive(member.element))); |
| 1832 reflectableMembers.add(member.element); |
| 1833 } |
| 1834 }); |
| 1835 } |
| 1836 } |
| 1837 // 5) all its closures |
| 1838 List<Element> closures = closureMap[cls]; |
| 1839 if (closures != null) { |
| 1840 reflectableMembers.addAll(closures); |
| 1841 foundClosure = true; |
| 1842 } |
| 1843 } else { |
| 1844 // check members themselves |
| 1845 cls.constructors.forEach((ConstructorElement element) { |
| 1846 if (!compiler.enqueuer.resolution.isLive(element)) return; |
| 1847 if (referencedFromMirrorSystem(element, false)) { |
| 1848 reflectableMembers.add(element); |
| 1849 } |
| 1850 }); |
| 1851 cls.forEachClassMember((Member member) { |
| 1852 if (!compiler.enqueuer.resolution.isLive(member.element)) return; |
| 1853 if (referencedFromMirrorSystem(member.element, false)) { |
| 1854 reflectableMembers.add(member.element); |
| 1855 } |
| 1856 }); |
| 1857 // Also add in closures. Those might be reflectable is their enclosing |
| 1858 // member is. |
| 1859 List<Element> closures = closureMap[cls]; |
| 1860 if (closures != null) { |
| 1861 for (Element closure in closures) { |
| 1862 if (referencedFromMirrorSystem(closure.enclosingMember, false)) { |
| 1863 reflectableMembers.add(closure); |
| 1864 foundClosure = true; |
| 1865 } |
| 1866 } |
| 1867 } |
| 1868 } |
| 1869 } |
| 1870 // We also need top-level non-class elements like static functions and |
| 1871 // global fields. We use the resolution queue to decide which elements are |
| 1872 // part of the live world. |
| 1873 for (LibraryElement lib in compiler.libraryLoader.libraries) { |
| 1874 if (lib.isInternalLibrary) continue; |
| 1875 lib.forEachLocalMember((Element member) { |
| 1876 if (!member.isClass && |
| 1877 compiler.enqueuer.resolution.isLive(member) && |
| 1878 referencedFromMirrorSystem(member)) { |
| 1879 reflectableMembers.add(member); |
| 1880 } |
| 1881 }); |
| 1882 } |
| 1883 // And closures inside top-level elements that do not have a surrounding |
| 1884 // class. These will be in the [:null:] bucket of the [closureMap]. |
| 1885 if (closureMap.containsKey(null)) { |
| 1886 for (Element closure in closureMap[null]) { |
| 1887 if (referencedFromMirrorSystem(closure)) { |
| 1888 reflectableMembers.add(closure); |
| 1889 foundClosure = true; |
| 1890 } |
| 1891 } |
| 1892 } |
| 1893 // As we do not think about closures as classes, yet, we have to make sure |
| 1894 // their superclasses are available for reflection manually. |
| 1895 if (foundClosure) { |
| 1896 reflectableMembers.add(closureClass); |
| 1897 } |
| 1898 // It would be nice to have a better means to select |
| 1899 Set<Element> closurizedMembers = compiler.resolverWorld.closurizedMembers; |
| 1900 if (closurizedMembers.any(reflectableMembers.contains)) { |
| 1901 reflectableMembers.add(boundClosureClass); |
| 1902 } |
| 1903 // Register all symbols of reflectable elements |
| 1904 for (Element element in reflectableMembers) { |
| 1905 symbolsUsed.add(element.name); |
| 1906 } |
| 1907 _membersNeededForReflection = reflectableMembers; |
| 1908 } |
| 1909 |
1755 jsAst.Call generateIsJsIndexableCall(jsAst.Expression use1, | 1910 jsAst.Call generateIsJsIndexableCall(jsAst.Expression use1, |
1756 jsAst.Expression use2) { | 1911 jsAst.Expression use2) { |
1757 String dispatchPropertyName = 'init.dispatchPropertyName'; | 1912 String dispatchPropertyName = 'init.dispatchPropertyName'; |
1758 | 1913 |
1759 // We pass the dispatch property record to the isJsIndexable | 1914 // We pass the dispatch property record to the isJsIndexable |
1760 // helper rather than reading it inside the helper to increase the | 1915 // helper rather than reading it inside the helper to increase the |
1761 // chance of making the dispatch record access monomorphic. | 1916 // chance of making the dispatch record access monomorphic. |
1762 jsAst.PropertyAccess record = new jsAst.PropertyAccess( | 1917 jsAst.PropertyAccess record = new jsAst.PropertyAccess( |
1763 use2, js(dispatchPropertyName)); | 1918 use2, js(dispatchPropertyName)); |
1764 | 1919 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1807 if (target.isField) { | 1962 if (target.isField) { |
1808 staticFields.add(target); | 1963 staticFields.add(target); |
1809 } else if (target.isLibrary || target.isClass) { | 1964 } else if (target.isLibrary || target.isClass) { |
1810 addFieldsInContainer(target); | 1965 addFieldsInContainer(target); |
1811 } | 1966 } |
1812 } | 1967 } |
1813 return staticFields; | 1968 return staticFields; |
1814 } | 1969 } |
1815 | 1970 |
1816 /// Called when [enqueuer] is empty, but before it is closed. | 1971 /// Called when [enqueuer] is empty, but before it is closed. |
1817 void onQueueEmpty(Enqueuer enqueuer) { | 1972 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) { |
1818 // Add elements referenced only via custom elements. Return early if any | 1973 // Add elements referenced only via custom elements. Return early if any |
1819 // elements are added to avoid counting the elements as due to mirrors. | 1974 // elements are added to avoid counting the elements as due to mirrors. |
1820 customElementsAnalysis.onQueueEmpty(enqueuer); | 1975 customElementsAnalysis.onQueueEmpty(enqueuer); |
1821 if (!enqueuer.queueIsEmpty) return; | 1976 if (!enqueuer.queueIsEmpty) return false; |
1822 | 1977 |
1823 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) { | 1978 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) { |
1824 preMirrorsMethodCount = generatedCode.length; | 1979 preMirrorsMethodCount = generatedCode.length; |
1825 } | 1980 } |
1826 | 1981 |
1827 if (isTreeShakingDisabled) { | 1982 if (isTreeShakingDisabled) { |
1828 enqueuer.enqueueEverything(); | 1983 enqueuer.enqueueReflectiveElements(recentClasses); |
1829 } else if (!targetsUsed.isEmpty && enqueuer.isResolutionQueue) { | 1984 } else if (!targetsUsed.isEmpty && enqueuer.isResolutionQueue) { |
1830 // Add all static elements (not classes) that have been requested for | 1985 // Add all static elements (not classes) that have been requested for |
1831 // reflection. If there is no mirror-usage these are probably not | 1986 // reflection. If there is no mirror-usage these are probably not |
1832 // necessary, but the backend relies on them being resolved. | 1987 // necessary, but the backend relies on them being resolved. |
1833 enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets()); | 1988 enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets()); |
1834 } | 1989 } |
1835 | 1990 |
1836 if (mustPreserveNames) compiler.log('Preserving names.'); | 1991 if (mustPreserveNames) compiler.log('Preserving names.'); |
1837 | 1992 |
1838 if (mustRetainMetadata) { | 1993 if (mustRetainMetadata) { |
1839 compiler.log('Retaining metadata.'); | 1994 compiler.log('Retaining metadata.'); |
1840 | 1995 |
1841 compiler.libraryLoader.libraries.forEach(retainMetadataOf); | 1996 compiler.libraryLoader.libraries.forEach(retainMetadataOf); |
1842 for (Dependency dependency in metadataConstants) { | 1997 for (Dependency dependency in metadataConstants) { |
1843 registerCompileTimeConstant( | 1998 registerCompileTimeConstant( |
1844 dependency.constant, dependency.registry); | 1999 dependency.constant, dependency.registry); |
1845 } | 2000 } |
1846 metadataConstants.clear(); | 2001 metadataConstants.clear(); |
1847 } | 2002 } |
| 2003 return true; |
1848 } | 2004 } |
1849 | 2005 |
1850 void onElementResolved(Element element, TreeElements elements) { | 2006 void onElementResolved(Element element, TreeElements elements) { |
1851 LibraryElement library = element.library; | 2007 LibraryElement library = element.library; |
1852 if (!library.isPlatformLibrary && !library.canUseNative) return; | 2008 if (!library.isPlatformLibrary && !library.canUseNative) return; |
1853 bool hasNoInline = false; | 2009 bool hasNoInline = false; |
1854 bool hasNoThrows = false; | 2010 bool hasNoThrows = false; |
1855 bool hasNoSideEffects = false; | 2011 bool hasNoSideEffects = false; |
1856 for (MetadataAnnotation metadata in element.metadata) { | 2012 for (MetadataAnnotation metadata in element.metadata) { |
1857 metadata.ensureResolved(compiler); | 2013 metadata.ensureResolved(compiler); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2104 } | 2260 } |
2105 | 2261 |
2106 /// Records that [constant] is used by the element behind [registry]. | 2262 /// Records that [constant] is used by the element behind [registry]. |
2107 class Dependency { | 2263 class Dependency { |
2108 final Constant constant; | 2264 final Constant constant; |
2109 // TODO(johnniwinther): Change to [Element] when dependency nodes are added. | 2265 // TODO(johnniwinther): Change to [Element] when dependency nodes are added. |
2110 final Registry registry; | 2266 final Registry registry; |
2111 | 2267 |
2112 const Dependency(this.constant, this.registry); | 2268 const Dependency(this.constant, this.registry); |
2113 } | 2269 } |
OLD | NEW |