Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(724)

Side by Side Diff: pkg/compiler/lib/src/ssa/codegen.dart

Issue 1424923004: Add StaticUse for more precise registration of statically known element use. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | pkg/compiler/lib/src/ssa/ssa.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 ssa; 5 part of ssa;
6 6
7 class SsaCodeGeneratorTask extends CompilerTask { 7 class SsaCodeGeneratorTask extends CompilerTask {
8 8
9 final JavaScriptBackend backend; 9 final JavaScriptBackend backend;
10 final SourceInformationStrategy sourceInformationFactory; 10 final SourceInformationStrategy sourceInformationFactory;
(...skipping 1561 matching lines...) Expand 10 before | Expand all | Expand 10 after
1572 .withSourceInformation(node.sourceInformation)); 1572 .withSourceInformation(node.sourceInformation));
1573 } 1573 }
1574 1574
1575 void visitInvokeConstructorBody(HInvokeConstructorBody node) { 1575 void visitInvokeConstructorBody(HInvokeConstructorBody node) {
1576 use(node.inputs[0]); 1576 use(node.inputs[0]);
1577 js.Expression object = pop(); 1577 js.Expression object = pop();
1578 js.Name methodName = backend.namer.instanceMethodName(node.element); 1578 js.Name methodName = backend.namer.instanceMethodName(node.element);
1579 List<js.Expression> arguments = visitArguments(node.inputs); 1579 List<js.Expression> arguments = visitArguments(node.inputs);
1580 push(js.propertyCall(object, methodName, arguments) 1580 push(js.propertyCall(object, methodName, arguments)
1581 .withSourceInformation(node.sourceInformation)); 1581 .withSourceInformation(node.sourceInformation));
1582 registry.registerStaticUse(node.element); 1582 registry.registerStaticUse(
1583 new StaticUse.constructorBodyInvoke(
1584 node.element, new CallStructure.unnamed(arguments.length)));
1583 } 1585 }
1584 1586
1585 void visitOneShotInterceptor(HOneShotInterceptor node) { 1587 void visitOneShotInterceptor(HOneShotInterceptor node) {
1586 List<js.Expression> arguments = visitArguments(node.inputs); 1588 List<js.Expression> arguments = visitArguments(node.inputs);
1587 var isolate = new js.VariableUse( 1589 var isolate = new js.VariableUse(
1588 backend.namer.globalObjectFor(helpers.interceptorsLibrary)); 1590 backend.namer.globalObjectFor(helpers.interceptorsLibrary));
1589 Selector selector = node.selector; 1591 Selector selector = node.selector;
1590 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); 1592 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
1591 js.Name methodName = backend.registerOneShotInterceptor(selector); 1593 js.Name methodName = backend.registerOneShotInterceptor(selector);
1592 push(js.propertyCall(isolate, methodName, arguments) 1594 push(js.propertyCall(isolate, methodName, arguments)
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1634 1636
1635 // If we don't know what we're calling or if we are calling a getter, 1637 // If we don't know what we're calling or if we are calling a getter,
1636 // we need to register that fact that we may be calling a closure 1638 // we need to register that fact that we may be calling a closure
1637 // with the same arguments. 1639 // with the same arguments.
1638 Element target = node.element; 1640 Element target = node.element;
1639 if (target == null || target.isGetter) { 1641 if (target == null || target.isGetter) {
1640 // TODO(kasperl): If we have a typed selector for the call, we 1642 // TODO(kasperl): If we have a typed selector for the call, we
1641 // may know something about the types of closures that need 1643 // may know something about the types of closures that need
1642 // the specific closure call method. 1644 // the specific closure call method.
1643 Selector call = new Selector.callClosureFrom(selector); 1645 Selector call = new Selector.callClosureFrom(selector);
1644 registry.registerDynamicInvocation( 1646 registry.registerDynamicUse(
1645 new UniverseSelector(call, null)); 1647 new UniverseSelector(call, null));
1646 } 1648 }
1647 registry.registerDynamicInvocation( 1649 registry.registerDynamicUse(
1648 new UniverseSelector(selector, mask)); 1650 new UniverseSelector(selector, mask));
1649 } 1651 }
1650 1652
1651 void registerSetter(HInvokeDynamic node) { 1653 void registerSetter(HInvokeDynamic node) {
1652 Selector selector = node.selector; 1654 Selector selector = node.selector;
1653 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); 1655 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
1654 registry.registerDynamicSetter( 1656 registry.registerDynamicUse(
1655 new UniverseSelector(selector, mask)); 1657 new UniverseSelector(selector, mask));
1656 } 1658 }
1657 1659
1658 void registerGetter(HInvokeDynamic node) { 1660 void registerGetter(HInvokeDynamic node) {
1659 Selector selector = node.selector; 1661 Selector selector = node.selector;
1660 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); 1662 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
1661 registry.registerDynamicGetter( 1663 registry.registerDynamicUse(
1662 new UniverseSelector(selector, mask)); 1664 new UniverseSelector(selector, mask));
1663 } 1665 }
1664 1666
1665 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 1667 visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
1666 use(node.receiver); 1668 use(node.receiver);
1667 js.Name name = backend.namer.invocationName(node.selector); 1669 js.Name name = backend.namer.invocationName(node.selector);
1668 push(js.propertyCall(pop(), name, visitArguments(node.inputs)) 1670 push(js.propertyCall(pop(), name, visitArguments(node.inputs))
1669 .withSourceInformation(node.sourceInformation)); 1671 .withSourceInformation(node.sourceInformation));
1670 registerSetter(node); 1672 registerSetter(node);
1671 } 1673 }
1672 1674
1673 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { 1675 visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
1674 use(node.receiver); 1676 use(node.receiver);
1675 js.Name name = backend.namer.invocationName(node.selector); 1677 js.Name name = backend.namer.invocationName(node.selector);
1676 push(js.propertyCall(pop(), name, visitArguments(node.inputs)) 1678 push(js.propertyCall(pop(), name, visitArguments(node.inputs))
1677 .withSourceInformation(node.sourceInformation)); 1679 .withSourceInformation(node.sourceInformation));
1678 registerGetter(node); 1680 registerGetter(node);
1679 } 1681 }
1680 1682
1681 visitInvokeClosure(HInvokeClosure node) { 1683 visitInvokeClosure(HInvokeClosure node) {
1682 Selector call = new Selector.callClosureFrom(node.selector); 1684 Selector call = new Selector.callClosureFrom(node.selector);
1683 use(node.receiver); 1685 use(node.receiver);
1684 push(js.propertyCall(pop(), 1686 push(js.propertyCall(pop(),
1685 backend.namer.invocationName(call), 1687 backend.namer.invocationName(call),
1686 visitArguments(node.inputs)) 1688 visitArguments(node.inputs))
1687 .withSourceInformation(node.sourceInformation)); 1689 .withSourceInformation(node.sourceInformation));
1688 registry.registerDynamicInvocation( 1690 registry.registerDynamicUse(
1689 new UniverseSelector(call, null)); 1691 new UniverseSelector(call, null));
1690 } 1692 }
1691 1693
1692 visitInvokeStatic(HInvokeStatic node) { 1694 visitInvokeStatic(HInvokeStatic node) {
1693 Element element = node.element; 1695 Element element = node.element;
1694 List<DartType> instantiatedTypes = node.instantiatedTypes; 1696 List<DartType> instantiatedTypes = node.instantiatedTypes;
1695 1697
1696 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) { 1698 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) {
1697 instantiatedTypes.forEach((type) { 1699 instantiatedTypes.forEach((type) {
1698 registry.registerInstantiatedType(type); 1700 registry.registerInstantiation(type);
1699 }); 1701 });
1700 } 1702 }
1701 1703
1702 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); 1704 List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
1703 1705
1704 if (element == backend.helpers.checkConcurrentModificationError) { 1706 if (element == backend.helpers.checkConcurrentModificationError) {
1705 // Manually inline the [checkConcurrentModificationError] function. This 1707 // Manually inline the [checkConcurrentModificationError] function. This
1706 // function is only called from a for-loop update. Ideally we would just 1708 // function is only called from a for-loop update. Ideally we would just
1707 // generate the conditionalcontrol flow in the builder but it adds basic 1709 // generate the conditionalcontrol flow in the builder but it adds basic
1708 // blocks in the loop update that interfere with other optimizations and 1710 // blocks in the loop update that interfere with other optimizations and
1709 // confuses loop recognition. 1711 // confuses loop recognition.
1710 1712
1711 assert(arguments.length == 2); 1713 assert(arguments.length == 2);
1712 Element throwFunction = backend.helpers.throwConcurrentModificationError; 1714 Element throwFunction = backend.helpers.throwConcurrentModificationError;
1713 registry.registerStaticInvocation(throwFunction); 1715 registry.registerStaticUse(
1716 new StaticUse.staticInvoke(throwFunction, CallStructure.ONE_ARG));
1714 1717
1715 // Calling using `(0, #)(#)` instead of `#(#)` separates the property load 1718 // Calling using `(0, #)(#)` instead of `#(#)` separates the property load
1716 // of the static function access from the call. For some reason this 1719 // of the static function access from the call. For some reason this
1717 // helps V8 see that the call never happens so V8 makes the call a 1720 // helps V8 see that the call never happens so V8 makes the call a
1718 // deoptimization. This removes the call from the optimized loop, making 1721 // deoptimization. This removes the call from the optimized loop, making
1719 // more optimizations available to the loop. This form is 50% faster on 1722 // more optimizations available to the loop. This form is 50% faster on
1720 // some small loop, almost as fast as loops with no concurrent 1723 // some small loop, almost as fast as loops with no concurrent
1721 // modification check. 1724 // modification check.
1722 push(js.js('# || (0, #)(#)',[ 1725 push(js.js('# || (0, #)(#)',[
1723 arguments[0], 1726 arguments[0],
1724 backend.emitter.staticFunctionAccess(throwFunction), 1727 backend.emitter.staticFunctionAccess(throwFunction),
1725 arguments[1]])); 1728 arguments[1]]));
1726 } else { 1729 } else {
1727 registry.registerStaticInvocation(element); 1730 CallStructure callStructure = new CallStructure.unnamed(arguments.length);
1731 registry.registerStaticUse(
1732 element.isConstructor
1733 ? new StaticUse.constructorInvoke(element, callStructure)
1734 : new StaticUse.staticInvoke(element, callStructure));
1728 push(backend.emitter.staticFunctionAccess(element)); 1735 push(backend.emitter.staticFunctionAccess(element));
1729 push(new js.Call(pop(), arguments, 1736 push(new js.Call(pop(), arguments,
1730 sourceInformation: node.sourceInformation)); 1737 sourceInformation: node.sourceInformation));
1731 } 1738 }
1732 1739
1733 } 1740 }
1734 1741
1735 visitInvokeSuper(HInvokeSuper node) { 1742 visitInvokeSuper(HInvokeSuper node) {
1736 Element superMethod = node.element; 1743 Element superElement = node.element;
1737 registry.registerSuperInvocation(superMethod); 1744 ClassElement superClass = superElement.enclosingClass;
1738 ClassElement superClass = superMethod.enclosingClass; 1745 if (superElement.isField) {
1739 if (superMethod.kind == ElementKind.FIELD) {
1740 js.Name fieldName = 1746 js.Name fieldName =
1741 backend.namer.instanceFieldPropertyName(superMethod); 1747 backend.namer.instanceFieldPropertyName(superElement);
1742 use(node.inputs[0]); 1748 use(node.inputs[0]);
1743 js.PropertyAccess access = 1749 js.PropertyAccess access =
1744 new js.PropertyAccess(pop(), fieldName) 1750 new js.PropertyAccess(pop(), fieldName)
1745 .withSourceInformation(node.sourceInformation); 1751 .withSourceInformation(node.sourceInformation);
1746 if (node.isSetter) { 1752 if (node.isSetter) {
1753 registry.registerStaticUse(
1754 new StaticUse.superSet(superElement));
1747 use(node.value); 1755 use(node.value);
1748 push(new js.Assignment(access, pop()) 1756 push(new js.Assignment(access, pop())
1749 .withSourceInformation(node.sourceInformation)); 1757 .withSourceInformation(node.sourceInformation));
1750 } else { 1758 } else {
1759 registry.registerStaticUse(new StaticUse.superGet(superElement));
1751 push(access); 1760 push(access);
1752 } 1761 }
1753 } else { 1762 } else {
1754 Selector selector = node.selector; 1763 Selector selector = node.selector;
1755 1764 if (!backend.maybeRegisterAliasedSuperMember(superElement, selector)) {
1756 if (!backend.maybeRegisterAliasedSuperMember(superMethod, selector)) {
1757 js.Name methodName; 1765 js.Name methodName;
1758 if (selector.isGetter) { 1766 if (selector.isGetter) {
1759 // If the selector we need to register a typed getter to the 1767 // If the selector we need to register a typed getter to the
1760 // [world]. The emitter needs to know if it needs to emit a 1768 // [world]. The emitter needs to know if it needs to emit a
1761 // bound closure for a method. 1769 // bound closure for a method.
1762 1770
1763 // If [superMethod] is mixed in, [superClass] might not be live. 1771 // If [superMethod] is mixed in, [superClass] might not be live.
1764 // We use the superclass of the access instead. 1772 // We use the superclass of the access instead.
1765 TypeMask receiverType = 1773 TypeMask receiverType =
1766 new TypeMask.nonNullExact(node.caller.superclass, compiler.world); 1774 new TypeMask.nonNullExact(node.caller.superclass, compiler.world);
1767 // TODO(floitsch): we know the target. We shouldn't register a 1775 // TODO(floitsch): we know the target. We shouldn't register a
1768 // dynamic getter. 1776 // dynamic getter.
1769 registry.registerDynamicGetter( 1777 registry.registerDynamicUse(
1770 new UniverseSelector(selector, receiverType)); 1778 new UniverseSelector(selector, receiverType));
1771 registry.registerGetterForSuperMethod(node.element); 1779 if (superElement.isFunction) {
1780 registry.registerStaticUse(
1781 new StaticUse.superTearOff(superElement));
1782 }
1772 methodName = backend.namer.invocationName(selector); 1783 methodName = backend.namer.invocationName(selector);
1773 } else { 1784 } else {
1774 assert(invariant(node, compiler.hasIncrementalSupport)); 1785 assert(invariant(node, compiler.hasIncrementalSupport));
1775 methodName = backend.namer.instanceMethodName(superMethod); 1786 methodName = backend.namer.instanceMethodName(superElement);
1776 } 1787 }
1788 registry.registerStaticUse(
1789 new StaticUse.superInvoke(
1790 superElement,
1791 new CallStructure.unnamed(node.inputs.length)));
1777 push(js.js('#.#.call(#)', 1792 push(js.js('#.#.call(#)',
1778 [backend.emitter.prototypeAccess(superClass, 1793 [backend.emitter.prototypeAccess(superClass,
1779 hasBeenInstantiated: true), 1794 hasBeenInstantiated: true),
1780 methodName, visitArguments(node.inputs, start: 0)]) 1795 methodName, visitArguments(node.inputs, start: 0)])
1781 .withSourceInformation(node.sourceInformation)); 1796 .withSourceInformation(node.sourceInformation));
1782 } else { 1797 } else {
1783 use(node.receiver); 1798 use(node.receiver);
1799 registry.registerStaticUse(
1800 new StaticUse.superInvoke(
1801 superElement,
1802 new CallStructure.unnamed(node.inputs.length - 1)));
1784 push( 1803 push(
1785 js.js('#.#(#)', [ 1804 js.js('#.#(#)', [
1786 pop(), backend.namer.aliasedSuperMemberPropertyName(superMethod), 1805 pop(), backend.namer.aliasedSuperMemberPropertyName(superElement),
1787 visitArguments(node.inputs, start: 1)]) // Skip receiver argument. 1806 visitArguments(node.inputs, start: 1)]) // Skip receiver argument.
1788 .withSourceInformation(node.sourceInformation)); 1807 .withSourceInformation(node.sourceInformation));
1789 } 1808 }
1790 } 1809 }
1791 } 1810 }
1792 1811
1793 visitFieldGet(HFieldGet node) { 1812 visitFieldGet(HFieldGet node) {
1794 use(node.receiver); 1813 use(node.receiver);
1795 Element element = node.element; 1814 Element element = node.element;
1796 if (node.isNullCheck) { 1815 if (node.isNullCheck) {
1797 // We access a JavaScript member we know all objects besides 1816 // We access a JavaScript member we know all objects besides
1798 // null and undefined have: V8 does not like accessing a member 1817 // null and undefined have: V8 does not like accessing a member
1799 // that does not exist. 1818 // that does not exist.
1800 push(new js.PropertyAccess.field(pop(), 'toString') 1819 push(new js.PropertyAccess.field(pop(), 'toString')
1801 .withSourceInformation(node.sourceInformation)); 1820 .withSourceInformation(node.sourceInformation));
1802 } else if (element == helpers.jsIndexableLength) { 1821 } else if (element == helpers.jsIndexableLength) {
1803 // We're accessing a native JavaScript property called 'length' 1822 // We're accessing a native JavaScript property called 'length'
1804 // on a JS String or a JS array. Therefore, the name of that 1823 // on a JS String or a JS array. Therefore, the name of that
1805 // property should not be mangled. 1824 // property should not be mangled.
1806 push(new js.PropertyAccess.field(pop(), 'length') 1825 push(new js.PropertyAccess.field(pop(), 'length')
1807 .withSourceInformation(node.sourceInformation)); 1826 .withSourceInformation(node.sourceInformation));
1808 } else { 1827 } else {
1809 js.Name name = backend.namer.instanceFieldPropertyName(element); 1828 js.Name name = backend.namer.instanceFieldPropertyName(element);
1810 push(new js.PropertyAccess(pop(), name) 1829 push(new js.PropertyAccess(pop(), name)
1811 .withSourceInformation(node.sourceInformation)); 1830 .withSourceInformation(node.sourceInformation));
1812 registry.registerFieldGetter(element); 1831 registry.registerStaticUse(new StaticUse.fieldGet(element));
1813 } 1832 }
1814 } 1833 }
1815 1834
1816 visitFieldSet(HFieldSet node) { 1835 visitFieldSet(HFieldSet node) {
1817 Element element = node.element; 1836 Element element = node.element;
1818 registry.registerFieldSetter(element); 1837 registry.registerStaticUse(new StaticUse.fieldSet(element));
1819 js.Name name = backend.namer.instanceFieldPropertyName(element); 1838 js.Name name = backend.namer.instanceFieldPropertyName(element);
1820 use(node.receiver); 1839 use(node.receiver);
1821 js.Expression receiver = pop(); 1840 js.Expression receiver = pop();
1822 use(node.value); 1841 use(node.value);
1823 push(new js.Assignment(new js.PropertyAccess(receiver, name), pop()) 1842 push(new js.Assignment(new js.PropertyAccess(receiver, name), pop())
1824 .withSourceInformation(node.sourceInformation)); 1843 .withSourceInformation(node.sourceInformation));
1825 } 1844 }
1826 1845
1827 visitReadModifyWrite(HReadModifyWrite node) { 1846 visitReadModifyWrite(HReadModifyWrite node) {
1828 Element element = node.element; 1847 Element element = node.element;
1829 registry.registerFieldSetter(element); 1848 registry.registerStaticUse(new StaticUse.fieldGet(element));
1849 registry.registerStaticUse(new StaticUse.fieldSet(element));
1830 js.Name name = backend.namer.instanceFieldPropertyName(element); 1850 js.Name name = backend.namer.instanceFieldPropertyName(element);
1831 use(node.receiver); 1851 use(node.receiver);
1832 js.Expression fieldReference = new js.PropertyAccess(pop(), name); 1852 js.Expression fieldReference = new js.PropertyAccess(pop(), name);
1833 if (node.isPreOp) { 1853 if (node.isPreOp) {
1834 push(new js.Prefix(node.jsOp, fieldReference) 1854 push(new js.Prefix(node.jsOp, fieldReference)
1835 .withSourceInformation(node.sourceInformation)); 1855 .withSourceInformation(node.sourceInformation));
1836 } else if (node.isPostOp) { 1856 } else if (node.isPostOp) {
1837 push(new js.Postfix(node.jsOp, fieldReference) 1857 push(new js.Postfix(node.jsOp, fieldReference)
1838 .withSourceInformation(node.sourceInformation)); 1858 .withSourceInformation(node.sourceInformation));
1839 } else { 1859 } else {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1894 // We also use ForeignNew to instantiate closure classes that belong to 1914 // We also use ForeignNew to instantiate closure classes that belong to
1895 // function expressions. We have to register their use here, as otherwise 1915 // function expressions. We have to register their use here, as otherwise
1896 // code for them might not be emitted. 1916 // code for them might not be emitted.
1897 if (node.element.isClosure) { 1917 if (node.element.isClosure) {
1898 registry.registerInstantiatedClass(node.element); 1918 registry.registerInstantiatedClass(node.element);
1899 } 1919 }
1900 if (node.instantiatedTypes == null) { 1920 if (node.instantiatedTypes == null) {
1901 return; 1921 return;
1902 } 1922 }
1903 node.instantiatedTypes.forEach((type) { 1923 node.instantiatedTypes.forEach((type) {
1904 registry.registerInstantiatedType(type); 1924 registry.registerInstantiation(type);
1905 }); 1925 });
1906 } 1926 }
1907 1927
1908 js.Expression newLiteralBool(bool value, 1928 js.Expression newLiteralBool(bool value,
1909 SourceInformation sourceInformation) { 1929 SourceInformation sourceInformation) {
1910 if (compiler.enableMinification) { 1930 if (compiler.enableMinification) {
1911 // Use !0 for true, !1 for false. 1931 // Use !0 for true, !1 for false.
1912 return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1")) 1932 return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1"))
1913 .withSourceInformation(sourceInformation); 1933 .withSourceInformation(sourceInformation);
1914 } else { 1934 } else {
1915 return new js.LiteralBool(value) 1935 return new js.LiteralBool(value)
1916 .withSourceInformation(sourceInformation); 1936 .withSourceInformation(sourceInformation);
1917 } 1937 }
1918 } 1938 }
1919 1939
1920 void generateConstant(ConstantValue constant, 1940 void generateConstant(ConstantValue constant,
1921 SourceInformation sourceInformation) { 1941 SourceInformation sourceInformation) {
1922 if (constant.isFunction) { 1942 if (constant.isFunction) {
1923 FunctionConstantValue function = constant; 1943 FunctionConstantValue function = constant;
1924 registry.registerStaticUse(function.element); 1944 registry.registerStaticUse(
1945 new StaticUse.staticTearOff(function.element));
1925 } 1946 }
1926 if (constant.isType) { 1947 if (constant.isType) {
1927 // If the type is a web component, we need to ensure the constructors are 1948 // If the type is a web component, we need to ensure the constructors are
1928 // available to 'upgrade' the native object. 1949 // available to 'upgrade' the native object.
1929 TypeConstantValue type = constant; 1950 TypeConstantValue type = constant;
1930 Element element = type.representedType.element; 1951 Element element = type.representedType.element;
1931 if (element != null && element.isClass) { 1952 if (element != null && element.isClass) {
1932 registry.registerTypeConstant(element); 1953 registry.registerTypeConstant(element);
1933 } 1954 }
1934 } 1955 }
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
2150 pushStatement(new js.If.noElse(underOver, thenBody) 2171 pushStatement(new js.If.noElse(underOver, thenBody)
2151 .withSourceInformation(node.sourceInformation)); 2172 .withSourceInformation(node.sourceInformation));
2152 } else { 2173 } else {
2153 generateThrowWithHelper(helpers.throwIndexOutOfRangeException, 2174 generateThrowWithHelper(helpers.throwIndexOutOfRangeException,
2154 [node.array, node.index]); 2175 [node.array, node.index]);
2155 } 2176 }
2156 } 2177 }
2157 2178
2158 void generateThrowWithHelper(Element helper, argument, 2179 void generateThrowWithHelper(Element helper, argument,
2159 {SourceInformation sourceInformation}) { 2180 {SourceInformation sourceInformation}) {
2160 registry.registerStaticUse(helper);
2161 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper); 2181 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
2162 List arguments = []; 2182 List arguments = [];
2163 var location; 2183 var location;
2164 if (argument is List) { 2184 if (argument is List) {
2165 location = argument[0]; 2185 location = argument[0];
2166 argument.forEach((instruction) { 2186 argument.forEach((instruction) {
2167 use(instruction); 2187 use(instruction);
2168 arguments.add(pop()); 2188 arguments.add(pop());
2169 }); 2189 });
2170 } else { 2190 } else {
2171 location = argument; 2191 location = argument;
2172 use(argument); 2192 use(argument);
2173 arguments.add(pop()); 2193 arguments.add(pop());
2174 } 2194 }
2195 registry.registerStaticUse(
2196 new StaticUse.staticInvoke(
2197 helper, new CallStructure.unnamed(arguments.length)));
2175 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false), 2198 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false),
2176 sourceInformation: sourceInformation); 2199 sourceInformation: sourceInformation);
2177 // BUG(4906): Using throw/return here adds to the size of the generated code 2200 // BUG(4906): Using throw/return here adds to the size of the generated code
2178 // but it has the advantage of explicitly telling the JS engine that 2201 // but it has the advantage of explicitly telling the JS engine that
2179 // this code path will terminate abruptly. Needs more work. 2202 // this code path will terminate abruptly. Needs more work.
2180 if (helper == helpers.wrapExceptionHelper) { 2203 if (helper == helpers.wrapExceptionHelper) {
2181 pushStatement(new js.Throw(value) 2204 pushStatement(new js.Throw(value)
2182 .withSourceInformation(sourceInformation)); 2205 .withSourceInformation(sourceInformation));
2183 } else { 2206 } else {
2184 Element element = work.element; 2207 Element element = work.element;
2185 if (element is FunctionElement && element.asyncMarker.isYielding) { 2208 if (element is FunctionElement && element.asyncMarker.isYielding) {
2186 // `return <expr>;` is illegal in a sync* or async* function. 2209 // `return <expr>;` is illegal in a sync* or async* function.
2187 // To have the the async-translator working, we avoid introducing 2210 // To have the the async-translator working, we avoid introducing
2188 // `return` nodes. 2211 // `return` nodes.
2189 pushStatement(new js.ExpressionStatement(value) 2212 pushStatement(new js.ExpressionStatement(value)
2190 .withSourceInformation(sourceInformation)); 2213 .withSourceInformation(sourceInformation));
2191 } else { 2214 } else {
2192 pushStatement(new js.Return(value) 2215 pushStatement(new js.Return(value)
2193 .withSourceInformation(sourceInformation)); 2216 .withSourceInformation(sourceInformation));
2194 } 2217 }
2195 } 2218 }
2196 } 2219 }
2197 2220
2198 visitThrowExpression(HThrowExpression node) { 2221 visitThrowExpression(HThrowExpression node) {
2199 HInstruction argument = node.inputs[0]; 2222 HInstruction argument = node.inputs[0];
2200 use(argument); 2223 use(argument);
2201 2224
2202 Element helper = helpers.throwExpressionHelper; 2225 Element helper = helpers.throwExpressionHelper;
2203 registry.registerStaticUse(helper); 2226 registry.registerStaticUse(
2227 new StaticUse.staticInvoke(helper, CallStructure.ONE_ARG));
2204 2228
2205 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper); 2229 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
2206 js.Call value = new js.Call(jsHelper, [pop()]) 2230 js.Call value = new js.Call(jsHelper, [pop()])
2207 .withSourceInformation(node.sourceInformation); 2231 .withSourceInformation(node.sourceInformation);
2208 push(value); 2232 push(value);
2209 } 2233 }
2210 2234
2211 void visitSwitch(HSwitch node) { 2235 void visitSwitch(HSwitch node) {
2212 // Switches are handled using [visitSwitchInfo]. 2236 // Switches are handled using [visitSwitchInfo].
2213 } 2237 }
2214 2238
2215 void visitStatic(HStatic node) { 2239 void visitStatic(HStatic node) {
2216 Element element = node.element; 2240 Element element = node.element;
2217 assert(element.isFunction || element.isField); 2241 assert(element.isFunction || element.isField);
2218 if (element.isFunction) { 2242 if (element.isFunction) {
2219 push(backend.emitter.isolateStaticClosureAccess(element) 2243 push(backend.emitter.isolateStaticClosureAccess(element)
2220 .withSourceInformation(node.sourceInformation)); 2244 .withSourceInformation(node.sourceInformation));
2221 registry.registerGetOfStaticFunction(element); 2245 registry.registerStaticUse(
2246 new StaticUse.staticTearOff(element));
2222 } else { 2247 } else {
2223 push(backend.emitter.staticFieldAccess(element) 2248 push(backend.emitter.staticFieldAccess(element)
2224 .withSourceInformation(node.sourceInformation)); 2249 .withSourceInformation(node.sourceInformation));
2250 registry.registerStaticUse(
2251 new StaticUse.staticGet(element));
2225 } 2252 }
2226 registry.registerStaticUse(element);
2227 } 2253 }
2228 2254
2229 void visitLazyStatic(HLazyStatic node) { 2255 void visitLazyStatic(HLazyStatic node) {
2230 Element element = node.element; 2256 Element element = node.element;
2231 registry.registerStaticUse(element); 2257 registry.registerStaticUse(
2258 new StaticUse.staticInit(element));
2232 js.Expression lazyGetter = 2259 js.Expression lazyGetter =
2233 backend.emitter.isolateLazyInitializerAccess(element); 2260 backend.emitter.isolateLazyInitializerAccess(element);
2234 js.Call call = new js.Call(lazyGetter, <js.Expression>[], 2261 js.Call call = new js.Call(lazyGetter, <js.Expression>[],
2235 sourceInformation: node.sourceInformation); 2262 sourceInformation: node.sourceInformation);
2236 push(call); 2263 push(call);
2237 } 2264 }
2238 2265
2239 void visitStaticStore(HStaticStore node) { 2266 void visitStaticStore(HStaticStore node) {
2240 registry.registerStaticUse(node.element); 2267 registry.registerStaticUse(
2268 new StaticUse.staticSet(node.element));
2241 js.Node variable = backend.emitter.staticFieldAccess(node.element); 2269 js.Node variable = backend.emitter.staticFieldAccess(node.element);
2242 use(node.inputs[0]); 2270 use(node.inputs[0]);
2243 push(new js.Assignment(variable, pop()) 2271 push(new js.Assignment(variable, pop())
2244 .withSourceInformation(node.sourceInformation)); 2272 .withSourceInformation(node.sourceInformation));
2245 } 2273 }
2246 2274
2247 void visitStringConcat(HStringConcat node) { 2275 void visitStringConcat(HStringConcat node) {
2248 use(node.left); 2276 use(node.left);
2249 js.Expression jsLeft = pop(); 2277 js.Expression jsLeft = pop();
2250 use(node.right); 2278 use(node.right);
(...skipping 13 matching lines...) Expand all
2264 && node.usedBy[0] is HStringConcat 2292 && node.usedBy[0] is HStringConcat
2265 && node.usedBy[0].inputs[1] == node) { 2293 && node.usedBy[0].inputs[1] == node) {
2266 // The context is already <string> + value. 2294 // The context is already <string> + value.
2267 } else { 2295 } else {
2268 // Force an empty string for the first operand. 2296 // Force an empty string for the first operand.
2269 push(new js.Binary('+', js.string(""), pop()) 2297 push(new js.Binary('+', js.string(""), pop())
2270 .withSourceInformation(node.sourceInformation)); 2298 .withSourceInformation(node.sourceInformation));
2271 } 2299 }
2272 } else { 2300 } else {
2273 Element convertToString = backend.helpers.stringInterpolationHelper; 2301 Element convertToString = backend.helpers.stringInterpolationHelper;
2274 registry.registerStaticUse(convertToString); 2302 registry.registerStaticUse(
2303 new StaticUse.staticInvoke(convertToString, CallStructure.ONE_ARG));
2275 js.Expression jsHelper = 2304 js.Expression jsHelper =
2276 backend.emitter.staticFunctionAccess(convertToString); 2305 backend.emitter.staticFunctionAccess(convertToString);
2277 use(input); 2306 use(input);
2278 push(new js.Call(jsHelper, <js.Expression>[pop()], 2307 push(new js.Call(jsHelper, <js.Expression>[pop()],
2279 sourceInformation: node.sourceInformation)); 2308 sourceInformation: node.sourceInformation));
2280 } 2309 }
2281 } 2310 }
2282 2311
2283 void visitLiteralList(HLiteralList node) { 2312 void visitLiteralList(HLiteralList node) {
2284 registry.registerInstantiatedClass(coreClasses.listClass); 2313 registry.registerInstantiatedClass(coreClasses.listClass);
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
2499 use(input); 2528 use(input);
2500 2529
2501 js.Expression jsClassReference = 2530 js.Expression jsClassReference =
2502 backend.emitter.constructorAccess(type.element); 2531 backend.emitter.constructorAccess(type.element);
2503 push(js.js('# instanceof #', [pop(), jsClassReference]) 2532 push(js.js('# instanceof #', [pop(), jsClassReference])
2504 .withSourceInformation(sourceInformation)); 2533 .withSourceInformation(sourceInformation));
2505 if (negative) { 2534 if (negative) {
2506 push(new js.Prefix('!', pop()) 2535 push(new js.Prefix('!', pop())
2507 .withSourceInformation(sourceInformation)); 2536 .withSourceInformation(sourceInformation));
2508 } 2537 }
2509 registry.registerInstantiatedType(type); 2538 registry.registerInstantiation(type);
2510 } 2539 }
2511 2540
2512 void handleNumberOrStringSupertypeCheck(HInstruction input, 2541 void handleNumberOrStringSupertypeCheck(HInstruction input,
2513 HInstruction interceptor, 2542 HInstruction interceptor,
2514 DartType type, 2543 DartType type,
2515 SourceInformation sourceInformation, 2544 SourceInformation sourceInformation,
2516 {bool negative: false}) { 2545 {bool negative: false}) {
2517 assert(!identical(type.element, coreClasses.listClass) && 2546 assert(!identical(type.element, coreClasses.listClass) &&
2518 !Elements.isListSupertype(type.element, compiler) && 2547 !Elements.isListSupertype(type.element, compiler) &&
2519 !Elements.isStringOnlySupertype(type.element, compiler)); 2548 !Elements.isStringOnlySupertype(type.element, compiler));
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
2824 returnType, 2853 returnType,
2825 new js.ArrayInitializer(parameterTypes), 2854 new js.ArrayInitializer(parameterTypes),
2826 new js.ObjectInitializer(namedParameters)]; 2855 new js.ObjectInitializer(namedParameters)];
2827 push(js.js('#(#)', [accessHelper('buildNamedFunctionType'), arguments])); 2856 push(js.js('#(#)', [accessHelper('buildNamedFunctionType'), arguments]));
2828 } 2857 }
2829 } 2858 }
2830 2859
2831 void visitReadTypeVariable(HReadTypeVariable node) { 2860 void visitReadTypeVariable(HReadTypeVariable node) {
2832 TypeVariableElement element = node.dartType.element; 2861 TypeVariableElement element = node.dartType.element;
2833 Element helperElement = helpers.convertRtiToRuntimeType; 2862 Element helperElement = helpers.convertRtiToRuntimeType;
2834 registry.registerStaticUse(helperElement); 2863 registry.registerStaticUse(
2864 new StaticUse.staticInvoke(helperElement, CallStructure.ONE_ARG));
2835 2865
2836 use(node.inputs[0]); 2866 use(node.inputs[0]);
2837 if (node.hasReceiver) { 2867 if (node.hasReceiver) {
2838 if (backend.isInterceptorClass(element.enclosingClass)) { 2868 if (backend.isInterceptorClass(element.enclosingClass)) {
2839 int index = element.index; 2869 int index = element.index;
2840 js.Expression receiver = pop(); 2870 js.Expression receiver = pop();
2841 js.Expression helper = backend.emitter 2871 js.Expression helper = backend.emitter
2842 .staticFunctionAccess(helperElement); 2872 .staticFunctionAccess(helperElement);
2843 push(js.js(r'#(#.$builtinTypeInfo && #.$builtinTypeInfo[#])', 2873 push(js.js(r'#(#.$builtinTypeInfo && #.$builtinTypeInfo[#])',
2844 [helper, receiver, receiver, js.js.number(index)])); 2874 [helper, receiver, receiver, js.js.number(index)]));
(...skipping 14 matching lines...) Expand all
2859 for (HInstruction type in node.inputs) { 2889 for (HInstruction type in node.inputs) {
2860 use(type); 2890 use(type);
2861 typeArguments.add(pop()); 2891 typeArguments.add(pop());
2862 } 2892 }
2863 2893
2864 ClassElement cls = node.dartType.element; 2894 ClassElement cls = node.dartType.element;
2865 var arguments = [backend.emitter.typeAccess(cls)]; 2895 var arguments = [backend.emitter.typeAccess(cls)];
2866 if (!typeArguments.isEmpty) { 2896 if (!typeArguments.isEmpty) {
2867 arguments.add(new js.ArrayInitializer(typeArguments)); 2897 arguments.add(new js.ArrayInitializer(typeArguments));
2868 } 2898 }
2869 push(js.js('#(#)', [accessHelper('buildInterfaceType'), arguments])); 2899 push(js.js('#(#)',
2900 [accessHelper('buildInterfaceType', arguments.length), arguments]));
2870 } 2901 }
2871 2902
2872 void visitVoidType(HVoidType node) { 2903 void visitVoidType(HVoidType node) {
2873 push(js.js('#()', accessHelper('getVoidRuntimeType'))); 2904 push(js.js('#()', accessHelper('getVoidRuntimeType')));
2874 } 2905 }
2875 2906
2876 void visitDynamicType(HDynamicType node) { 2907 void visitDynamicType(HDynamicType node) {
2877 push(js.js('#()', accessHelper('getDynamicRuntimeType'))); 2908 push(js.js('#()', accessHelper('getDynamicRuntimeType')));
2878 } 2909 }
2879 2910
2880 js.PropertyAccess accessHelper(String name) { 2911 js.PropertyAccess accessHelper(String name, [int argumentCount = 0]) {
2881 Element helper = helpers.findHelper(name); 2912 Element helper = helpers.findHelper(name);
2882 if (helper == null) { 2913 if (helper == null) {
2883 // For mocked-up tests. 2914 // For mocked-up tests.
2884 return js.js('(void 0).$name'); 2915 return js.js('(void 0).$name');
2885 } 2916 }
2886 registry.registerStaticUse(helper); 2917 registry.registerStaticUse(
2918 new StaticUse.staticInvoke(helper,
2919 new CallStructure.unnamed(argumentCount)));
2887 return backend.emitter.staticFunctionAccess(helper); 2920 return backend.emitter.staticFunctionAccess(helper);
2888 } 2921 }
2889 2922
2890 @override 2923 @override
2891 void visitRef(HRef node) { 2924 void visitRef(HRef node) {
2892 visit(node.value); 2925 visit(node.value);
2893 } 2926 }
2894 } 2927 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | pkg/compiler/lib/src/ssa/ssa.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698