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

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

Issue 2609063002: Further reduce use of Element in codegen. (Closed)
Patch Set: Created 3 years, 11 months 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
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 import 'dart:math' as math; 5 import 'dart:math' as math;
6 import '../common.dart'; 6 import '../common.dart';
7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
8 import '../common/tasks.dart' show CompilerTask; 8 import '../common/tasks.dart' show CompilerTask;
9 import '../compiler.dart' show Compiler; 9 import '../compiler.dart' show Compiler;
10 import '../constants/constant_system.dart'; 10 import '../constants/constant_system.dart';
11 import '../constants/values.dart'; 11 import '../constants/values.dart';
12 import '../core_types.dart' show CommonElements; 12 import '../core_types.dart' show CommonElements;
13 import '../dart_types.dart'; 13 import '../dart_types.dart';
14 import '../elements/elements.dart'; 14 import '../elements/elements.dart'
15 show
16 Entity,
17 JumpTarget,
18 LabelDefinition,
19 Local,
20 Name,
21 AsyncMarker,
22 ResolvedAst,
23 FunctionElement;
15 import '../elements/entities.dart'; 24 import '../elements/entities.dart';
16 import '../io/source_information.dart'; 25 import '../io/source_information.dart';
17 import '../js/js.dart' as js; 26 import '../js/js.dart' as js;
18 import '../js_backend/backend_helpers.dart' show BackendHelpers; 27 import '../js_backend/backend_helpers.dart' show BackendHelpers;
19 import '../js_backend/js_backend.dart'; 28 import '../js_backend/js_backend.dart';
20 import '../js_emitter/js_emitter.dart' show NativeEmitter; 29 import '../js_emitter/js_emitter.dart' show NativeEmitter;
21 import '../native/native.dart' as native; 30 import '../native/native.dart' as native;
22 import '../types/types.dart'; 31 import '../types/types.dart';
23 import '../universe/call_structure.dart' show CallStructure; 32 import '../universe/call_structure.dart' show CallStructure;
24 import '../universe/selector.dart' show Selector; 33 import '../universe/selector.dart' show Selector;
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 796
788 bool visitAndOrInfo(HAndOrBlockInformation info) { 797 bool visitAndOrInfo(HAndOrBlockInformation info) {
789 return false; 798 return false;
790 } 799 }
791 800
792 bool visitTryInfo(HTryBlockInformation info) { 801 bool visitTryInfo(HTryBlockInformation info) {
793 js.Block body = generateStatementsInNewBlock(info.body); 802 js.Block body = generateStatementsInNewBlock(info.body);
794 js.Catch catchPart = null; 803 js.Catch catchPart = null;
795 js.Block finallyPart = null; 804 js.Block finallyPart = null;
796 if (info.catchBlock != null) { 805 if (info.catchBlock != null) {
797 void register(ClassElement classElement) { 806 void register(ClassEntity classElement) {
798 if (classElement != null) { 807 if (classElement != null) {
799 registry.registerInstantiatedClass(classElement); 808 registry.registerInstantiatedClass(classElement);
800 } 809 }
801 } 810 }
802 811
803 register(helpers.jsPlainJavaScriptObjectClass); 812 register(helpers.jsPlainJavaScriptObjectClass);
804 register(helpers.jsUnknownJavaScriptObjectClass); 813 register(helpers.jsUnknownJavaScriptObjectClass);
805 814
806 HLocalValue exception = info.catchVariable; 815 HLocalValue exception = info.catchVariable;
807 String name = variableNames.getName(exception); 816 String name = variableNames.getName(exception);
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after
1634 .withSourceInformation(node.sourceInformation)); 1643 .withSourceInformation(node.sourceInformation));
1635 registry.registerUseInterceptor(); 1644 registry.registerUseInterceptor();
1636 } 1645 }
1637 } 1646 }
1638 1647
1639 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 1648 visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
1640 use(node.receiver); 1649 use(node.receiver);
1641 js.Expression object = pop(); 1650 js.Expression object = pop();
1642 String methodName; 1651 String methodName;
1643 List<js.Expression> arguments = visitArguments(node.inputs); 1652 List<js.Expression> arguments = visitArguments(node.inputs);
1644 MemberElement target = node.element; 1653 MemberEntity target = node.element;
1645 1654
1646 // TODO(herhut): The namer should return the appropriate backendname here. 1655 // TODO(herhut): The namer should return the appropriate backendname here.
1647 if (target != null && !node.isInterceptedCall) { 1656 if (target != null && !node.isInterceptedCall) {
1648 if (target == helpers.jsArrayAdd) { 1657 if (target == helpers.jsArrayAdd) {
1649 methodName = 'push'; 1658 methodName = 'push';
1650 } else if (target == helpers.jsArrayRemoveLast) { 1659 } else if (target == helpers.jsArrayRemoveLast) {
1651 methodName = 'pop'; 1660 methodName = 'pop';
1652 } else if (target == helpers.jsStringSplit) { 1661 } else if (target == helpers.jsStringSplit) {
1653 methodName = 'split'; 1662 methodName = 'split';
1654 // Split returns a List, so we make sure the backend knows the 1663 // Split returns a List, so we make sure the backend knows the
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1707 registry.registerUseInterceptor(); 1716 registry.registerUseInterceptor();
1708 } 1717 }
1709 1718
1710 TypeMask getOptimizedSelectorFor( 1719 TypeMask getOptimizedSelectorFor(
1711 HInvokeDynamic node, Selector selector, TypeMask mask) { 1720 HInvokeDynamic node, Selector selector, TypeMask mask) {
1712 if (node.element != null) { 1721 if (node.element != null) {
1713 // Create an artificial type mask to make sure only 1722 // Create an artificial type mask to make sure only
1714 // [node.element] will be enqueued. We're not using the receiver 1723 // [node.element] will be enqueued. We're not using the receiver
1715 // type because our optimizations might end up in a state where the 1724 // type because our optimizations might end up in a state where the
1716 // invoke dynamic knows more than the receiver. 1725 // invoke dynamic knows more than the receiver.
1717 ClassElement enclosing = node.element.enclosingClass; 1726 ClassEntity enclosing = node.element.enclosingClass;
1718 if (closedWorld.isInstantiated(enclosing)) { 1727 if (closedWorld.isInstantiated(enclosing)) {
1719 return new TypeMask.nonNullExact(enclosing.declaration, closedWorld); 1728 return closedWorld.commonMasks.createNonNullExact(enclosing);
1720 } else { 1729 } else {
1721 // The element is mixed in so a non-null subtype mask is the most 1730 // The element is mixed in so a non-null subtype mask is the most
1722 // precise we have. 1731 // precise we have.
1723 assert(invariant(node, closedWorld.isUsedAsMixin(enclosing), 1732 assert(invariant(node, closedWorld.isUsedAsMixin(enclosing),
1724 message: "Element ${node.element} from $enclosing expected " 1733 message: "Element ${node.element} from $enclosing expected "
1725 "to be mixed in.")); 1734 "to be mixed in."));
1726 return new TypeMask.nonNullSubtype(enclosing.declaration, closedWorld); 1735 return closedWorld.commonMasks.createNonNullSubtype(enclosing);
1727 } 1736 }
1728 } 1737 }
1729 // If [JSInvocationMirror._invokeOn] is enabled, and this call 1738 // If [JSInvocationMirror._invokeOn] is enabled, and this call
1730 // might hit a `noSuchMethod`, we register an untyped selector. 1739 // might hit a `noSuchMethod`, we register an untyped selector.
1731 return closedWorld.extendMaskIfReachesAll(selector, mask); 1740 return closedWorld.extendMaskIfReachesAll(selector, mask);
1732 } 1741 }
1733 1742
1734 void registerMethodInvoke(HInvokeDynamic node) { 1743 void registerMethodInvoke(HInvokeDynamic node) {
1735 Selector selector = node.selector; 1744 Selector selector = node.selector;
1736 1745
1737 // If we don't know what we're calling or if we are calling a getter, 1746 // If we don't know what we're calling or if we are calling a getter,
1738 // we need to register that fact that we may be calling a closure 1747 // we need to register that fact that we may be calling a closure
1739 // with the same arguments. 1748 // with the same arguments.
1740 MemberElement target = node.element; 1749 MemberEntity target = node.element;
1741 if (target == null || target.isGetter) { 1750 if (target == null || target.isGetter) {
1742 // TODO(kasperl): If we have a typed selector for the call, we 1751 // TODO(kasperl): If we have a typed selector for the call, we
1743 // may know something about the types of closures that need 1752 // may know something about the types of closures that need
1744 // the specific closure call method. 1753 // the specific closure call method.
1745 Selector call = new Selector.callClosureFrom(selector); 1754 Selector call = new Selector.callClosureFrom(selector);
1746 registry.registerDynamicUse(new DynamicUse(call, null)); 1755 registry.registerDynamicUse(new DynamicUse(call, null));
1747 } 1756 }
1748 if (target != null) { 1757 if (target != null) {
1749 // This is a dynamic invocation which we have found to have a single 1758 // This is a dynamic invocation which we have found to have a single
1750 // target but for some reason haven't inlined. We are _still_ accessing 1759 // target but for some reason haven't inlined. We are _still_ accessing
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1812 Selector call = new Selector.callClosureFrom(node.selector); 1821 Selector call = new Selector.callClosureFrom(node.selector);
1813 use(node.receiver); 1822 use(node.receiver);
1814 push(js 1823 push(js
1815 .propertyCall(pop(), backend.namer.invocationName(call), 1824 .propertyCall(pop(), backend.namer.invocationName(call),
1816 visitArguments(node.inputs)) 1825 visitArguments(node.inputs))
1817 .withSourceInformation(node.sourceInformation)); 1826 .withSourceInformation(node.sourceInformation));
1818 registry.registerDynamicUse(new DynamicUse(call, null)); 1827 registry.registerDynamicUse(new DynamicUse(call, null));
1819 } 1828 }
1820 1829
1821 visitInvokeStatic(HInvokeStatic node) { 1830 visitInvokeStatic(HInvokeStatic node) {
1822 MemberElement element = node.element; 1831 MemberEntity element = node.element;
1823 List<DartType> instantiatedTypes = node.instantiatedTypes; 1832 List<DartType> instantiatedTypes = node.instantiatedTypes;
1824 1833
1825 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) { 1834 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) {
1826 instantiatedTypes.forEach((type) { 1835 instantiatedTypes.forEach((type) {
1827 registry.registerInstantiation(type); 1836 registry.registerInstantiation(type);
1828 }); 1837 });
1829 } 1838 }
1830 1839
1831 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); 1840 List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
1832 1841
1833 if (element == backend.helpers.checkConcurrentModificationError) { 1842 if (element == backend.helpers.checkConcurrentModificationError) {
1834 // Manually inline the [checkConcurrentModificationError] function. This 1843 // Manually inline the [checkConcurrentModificationError] function. This
1835 // function is only called from a for-loop update. Ideally we would just 1844 // function is only called from a for-loop update. Ideally we would just
1836 // generate the conditionalcontrol flow in the builder but it adds basic 1845 // generate the conditionalcontrol flow in the builder but it adds basic
1837 // blocks in the loop update that interfere with other optimizations and 1846 // blocks in the loop update that interfere with other optimizations and
1838 // confuses loop recognition. 1847 // confuses loop recognition.
1839 1848
1840 assert(arguments.length == 2); 1849 assert(arguments.length == 2);
1841 Element throwFunction = backend.helpers.throwConcurrentModificationError; 1850 FunctionEntity throwFunction =
1851 backend.helpers.throwConcurrentModificationError;
1842 registry.registerStaticUse( 1852 registry.registerStaticUse(
1843 new StaticUse.staticInvoke(throwFunction, CallStructure.ONE_ARG)); 1853 new StaticUse.staticInvoke(throwFunction, CallStructure.ONE_ARG));
1844 1854
1845 // Calling using `(0, #)(#)` instead of `#(#)` separates the property load 1855 // Calling using `(0, #)(#)` instead of `#(#)` separates the property load
1846 // of the static function access from the call. For some reason this 1856 // of the static function access from the call. For some reason this
1847 // helps V8 see that the call never happens so V8 makes the call a 1857 // helps V8 see that the call never happens so V8 makes the call a
1848 // deoptimization. This removes the call from the optimized loop, making 1858 // deoptimization. This removes the call from the optimized loop, making
1849 // more optimizations available to the loop. This form is 50% faster on 1859 // more optimizations available to the loop. This form is 50% faster on
1850 // some small loop, almost as fast as loops with no concurrent 1860 // some small loop, almost as fast as loops with no concurrent
1851 // modification check. 1861 // modification check.
1852 push(js.js('# || (0, #)(#)', [ 1862 push(js.js('# || (0, #)(#)', [
1853 arguments[0], 1863 arguments[0],
1854 backend.emitter.staticFunctionAccess(throwFunction), 1864 backend.emitter.staticFunctionAccess(throwFunction),
1855 arguments[1] 1865 arguments[1]
1856 ])); 1866 ]));
1857 } else { 1867 } else {
1858 CallStructure callStructure = new CallStructure.unnamed(arguments.length); 1868 CallStructure callStructure = new CallStructure.unnamed(arguments.length);
1859 registry.registerStaticUse(element.isConstructor 1869 registry.registerStaticUse(element.isConstructor
1860 ? new StaticUse.constructorInvoke(element, callStructure) 1870 ? new StaticUse.constructorInvoke(element, callStructure)
1861 : new StaticUse.staticInvoke(element, callStructure)); 1871 : new StaticUse.staticInvoke(element, callStructure));
1862 push(backend.emitter.staticFunctionAccess(element)); 1872 push(backend.emitter.staticFunctionAccess(element));
1863 push(new js.Call(pop(), arguments, 1873 push(new js.Call(pop(), arguments,
1864 sourceInformation: node.sourceInformation)); 1874 sourceInformation: node.sourceInformation));
1865 } 1875 }
1866 } 1876 }
1867 1877
1868 visitInvokeSuper(HInvokeSuper node) { 1878 visitInvokeSuper(HInvokeSuper node) {
1869 MemberElement superElement = node.element; 1879 MemberEntity superElement = node.element;
1870 ClassElement superClass = superElement.enclosingClass; 1880 ClassEntity superClass = superElement.enclosingClass;
1871 if (superElement.isField) { 1881 if (superElement.isField) {
1872 js.Name fieldName = backend.namer.instanceFieldPropertyName(superElement); 1882 js.Name fieldName = backend.namer.instanceFieldPropertyName(superElement);
1873 use(node.inputs[0]); 1883 use(node.inputs[0]);
1874 js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName) 1884 js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName)
1875 .withSourceInformation(node.sourceInformation); 1885 .withSourceInformation(node.sourceInformation);
1876 if (node.isSetter) { 1886 if (node.isSetter) {
1877 registry.registerStaticUse(superElement.isSetter 1887 registry.registerStaticUse(superElement.isSetter
1878 ? new StaticUse.superSetterSet(superElement) 1888 ? new StaticUse.superSetterSet(superElement)
1879 : new StaticUse.superFieldSet(superElement)); 1889 : new StaticUse.superFieldSet(superElement));
1880 use(node.value); 1890 use(node.value);
1881 push(new js.Assignment(access, pop()) 1891 push(new js.Assignment(access, pop())
1882 .withSourceInformation(node.sourceInformation)); 1892 .withSourceInformation(node.sourceInformation));
1883 } else { 1893 } else {
1884 registry.registerStaticUse(new StaticUse.superGet(superElement)); 1894 registry.registerStaticUse(new StaticUse.superGet(superElement));
1885 push(access); 1895 push(access);
1886 } 1896 }
1887 } else { 1897 } else {
1888 Selector selector = node.selector; 1898 Selector selector = node.selector;
1889 if (!backend.maybeRegisterAliasedSuperMember(superElement, selector)) { 1899 if (!backend.maybeRegisterAliasedSuperMember(superElement, selector)) {
1890 js.Name methodName; 1900 js.Name methodName;
1891 if (selector.isGetter && !superElement.isGetter) { 1901 if (selector.isGetter && !superElement.isGetter) {
1892 // If this is a tear-off, register the fact that a tear-off closure 1902 // If this is a tear-off, register the fact that a tear-off closure
1893 // will be created, and that this tear-off must bypass ordinary 1903 // will be created, and that this tear-off must bypass ordinary
1894 // dispatch to ensure the super method is invoked. 1904 // dispatch to ensure the super method is invoked.
1895 FunctionElement helper = backend.helpers.closureFromTearOff; 1905 FunctionEntity helper = backend.helpers.closureFromTearOff;
1896 registry.registerStaticUse(new StaticUse.staticInvoke( 1906 registry.registerStaticUse(new StaticUse.staticInvoke(
1897 helper, new CallStructure.unnamed(helper.parameters.length))); 1907 helper, compiler.codegenWorld.getCallStructureFor(helper)));
1898 registry.registerStaticUse(new StaticUse.superTearOff(node.element)); 1908 registry.registerStaticUse(new StaticUse.superTearOff(node.element));
1899 methodName = backend.namer.invocationName(selector); 1909 methodName = backend.namer.invocationName(selector);
1900 } else { 1910 } else {
1901 methodName = backend.namer.instanceMethodName(superElement); 1911 methodName = backend.namer.instanceMethodName(superElement);
1902 } 1912 }
1903 registry.registerStaticUse(new StaticUse.superInvoke( 1913 registry.registerStaticUse(new StaticUse.superInvoke(
1904 superElement, new CallStructure.unnamed(node.inputs.length))); 1914 superElement, new CallStructure.unnamed(node.inputs.length)));
1905 push(js.js('#.#.call(#)', [ 1915 push(js.js('#.#.call(#)', [
1906 backend.emitter 1916 backend.emitter
1907 .prototypeAccess(superClass, hasBeenInstantiated: true), 1917 .prototypeAccess(superClass, hasBeenInstantiated: true),
1908 methodName, 1918 methodName,
1909 visitArguments(node.inputs, start: 0) 1919 visitArguments(node.inputs, start: 0)
1910 ]).withSourceInformation(node.sourceInformation)); 1920 ]).withSourceInformation(node.sourceInformation));
1911 } else { 1921 } else {
1912 use(node.receiver); 1922 use(node.receiver);
1913 registry.registerStaticUse(new StaticUse.superInvoke( 1923 registry.registerStaticUse(new StaticUse.superInvoke(
1914 superElement, new CallStructure.unnamed(node.inputs.length - 1))); 1924 superElement, new CallStructure.unnamed(node.inputs.length - 1)));
1915 push(js.js('#.#(#)', [ 1925 push(js.js('#.#(#)', [
1916 pop(), 1926 pop(),
1917 backend.namer.aliasedSuperMemberPropertyName(superElement), 1927 backend.namer.aliasedSuperMemberPropertyName(superElement),
1918 visitArguments(node.inputs, start: 1) 1928 visitArguments(node.inputs, start: 1)
1919 ]) // Skip receiver argument. 1929 ]) // Skip receiver argument.
1920 .withSourceInformation(node.sourceInformation)); 1930 .withSourceInformation(node.sourceInformation));
1921 } 1931 }
1922 } 1932 }
1923 } 1933 }
1924 1934
1925 visitFieldGet(HFieldGet node) { 1935 visitFieldGet(HFieldGet node) {
1926 use(node.receiver); 1936 use(node.receiver);
1927 MemberElement element = node.element; 1937 MemberEntity element = node.element;
1928 if (node.isNullCheck) { 1938 if (node.isNullCheck) {
1929 // We access a JavaScript member we know all objects besides 1939 // We access a JavaScript member we know all objects besides
1930 // null and undefined have: V8 does not like accessing a member 1940 // null and undefined have: V8 does not like accessing a member
1931 // that does not exist. 1941 // that does not exist.
1932 push(new js.PropertyAccess.field(pop(), 'toString') 1942 push(new js.PropertyAccess.field(pop(), 'toString')
1933 .withSourceInformation(node.sourceInformation)); 1943 .withSourceInformation(node.sourceInformation));
1934 } else if (element == helpers.jsIndexableLength) { 1944 } else if (element == helpers.jsIndexableLength) {
1935 // We're accessing a native JavaScript property called 'length' 1945 // We're accessing a native JavaScript property called 'length'
1936 // on a JS String or a JS array. Therefore, the name of that 1946 // on a JS String or a JS array. Therefore, the name of that
1937 // property should not be mangled. 1947 // property should not be mangled.
1938 push(new js.PropertyAccess.field(pop(), 'length') 1948 push(new js.PropertyAccess.field(pop(), 'length')
1939 .withSourceInformation(node.sourceInformation)); 1949 .withSourceInformation(node.sourceInformation));
1940 } else { 1950 } else {
1941 js.Name name = backend.namer.instanceFieldPropertyName(element); 1951 FieldEntity field = element;
1952 js.Name name = backend.namer.instanceFieldPropertyName(field);
1942 push(new js.PropertyAccess(pop(), name) 1953 push(new js.PropertyAccess(pop(), name)
1943 .withSourceInformation(node.sourceInformation)); 1954 .withSourceInformation(node.sourceInformation));
1944 registry.registerStaticUse(new StaticUse.fieldGet(element)); 1955 registry.registerStaticUse(new StaticUse.fieldGet(field));
1945 } 1956 }
1946 } 1957 }
1947 1958
1948 visitFieldSet(HFieldSet node) { 1959 visitFieldSet(HFieldSet node) {
1949 MemberElement element = node.element; 1960 MemberEntity element = node.element;
1950 registry.registerStaticUse(new StaticUse.fieldSet(element)); 1961 registry.registerStaticUse(new StaticUse.fieldSet(element));
1951 js.Name name = backend.namer.instanceFieldPropertyName(element); 1962 js.Name name = backend.namer.instanceFieldPropertyName(element);
1952 use(node.receiver); 1963 use(node.receiver);
1953 js.Expression receiver = pop(); 1964 js.Expression receiver = pop();
1954 use(node.value); 1965 use(node.value);
1955 push(new js.Assignment(new js.PropertyAccess(receiver, name), pop()) 1966 push(new js.Assignment(new js.PropertyAccess(receiver, name), pop())
1956 .withSourceInformation(node.sourceInformation)); 1967 .withSourceInformation(node.sourceInformation));
1957 } 1968 }
1958 1969
1959 visitReadModifyWrite(HReadModifyWrite node) { 1970 visitReadModifyWrite(HReadModifyWrite node) {
1960 FieldElement element = node.element; 1971 FieldEntity element = node.element;
1961 registry.registerStaticUse(new StaticUse.fieldGet(element)); 1972 registry.registerStaticUse(new StaticUse.fieldGet(element));
1962 registry.registerStaticUse(new StaticUse.fieldSet(element)); 1973 registry.registerStaticUse(new StaticUse.fieldSet(element));
1963 js.Name name = backend.namer.instanceFieldPropertyName(element); 1974 js.Name name = backend.namer.instanceFieldPropertyName(element);
1964 use(node.receiver); 1975 use(node.receiver);
1965 js.Expression fieldReference = new js.PropertyAccess(pop(), name); 1976 js.Expression fieldReference = new js.PropertyAccess(pop(), name);
1966 if (node.isPreOp) { 1977 if (node.isPreOp) {
1967 push(new js.Prefix(node.jsOp, fieldReference) 1978 push(new js.Prefix(node.jsOp, fieldReference)
1968 .withSourceInformation(node.sourceInformation)); 1979 .withSourceInformation(node.sourceInformation));
1969 } else if (node.isPostOp) { 1980 } else if (node.isPostOp) {
1970 push(new js.Postfix(node.jsOp, fieldReference) 1981 push(new js.Postfix(node.jsOp, fieldReference)
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2048 void generateConstant( 2059 void generateConstant(
2049 ConstantValue constant, SourceInformation sourceInformation) { 2060 ConstantValue constant, SourceInformation sourceInformation) {
2050 if (constant.isFunction) { 2061 if (constant.isFunction) {
2051 FunctionConstantValue function = constant; 2062 FunctionConstantValue function = constant;
2052 registry.registerStaticUse(new StaticUse.staticTearOff(function.element)); 2063 registry.registerStaticUse(new StaticUse.staticTearOff(function.element));
2053 } 2064 }
2054 if (constant.isType) { 2065 if (constant.isType) {
2055 // If the type is a web component, we need to ensure the constructors are 2066 // If the type is a web component, we need to ensure the constructors are
2056 // available to 'upgrade' the native object. 2067 // available to 'upgrade' the native object.
2057 TypeConstantValue type = constant; 2068 TypeConstantValue type = constant;
2058 Element element = type.representedType.element; 2069 if (type.representedType.isInterfaceType) {
2059 if (element != null && element.isClass) { 2070 registry.registerTypeConstant(type.representedType.element);
2060 registry.registerTypeConstant(element);
2061 } 2071 }
2062 } 2072 }
2063 js.Expression expression = backend.emitter.constantReference(constant); 2073 js.Expression expression = backend.emitter.constantReference(constant);
2064 if (!constant.isDummy) { 2074 if (!constant.isDummy) {
2065 // TODO(johnniwinther): Support source information on synthetic constants. 2075 // TODO(johnniwinther): Support source information on synthetic constants.
2066 expression = expression.withSourceInformation(sourceInformation); 2076 expression = expression.withSourceInformation(sourceInformation);
2067 } 2077 }
2068 push(expression); 2078 push(expression);
2069 } 2079 }
2070 2080
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
2274 currentContainer = oldContainer; 2284 currentContainer = oldContainer;
2275 thenBody = unwrapStatement(thenBody); 2285 thenBody = unwrapStatement(thenBody);
2276 pushStatement(new js.If.noElse(underOver, thenBody) 2286 pushStatement(new js.If.noElse(underOver, thenBody)
2277 .withSourceInformation(node.sourceInformation)); 2287 .withSourceInformation(node.sourceInformation));
2278 } else { 2288 } else {
2279 generateThrowWithHelper( 2289 generateThrowWithHelper(
2280 helpers.throwIndexOutOfRangeException, [node.array, node.index]); 2290 helpers.throwIndexOutOfRangeException, [node.array, node.index]);
2281 } 2291 }
2282 } 2292 }
2283 2293
2284 void generateThrowWithHelper(Element helper, argument, 2294 void generateThrowWithHelper(FunctionEntity helper, argument,
2285 {SourceInformation sourceInformation}) { 2295 {SourceInformation sourceInformation}) {
2286 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper); 2296 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
2287 List arguments = []; 2297 List arguments = [];
2288 if (argument is List) { 2298 if (argument is List) {
2289 argument.forEach((instruction) { 2299 argument.forEach((instruction) {
2290 use(instruction); 2300 use(instruction);
2291 arguments.add(pop()); 2301 arguments.add(pop());
2292 }); 2302 });
2293 } else { 2303 } else {
2294 use(argument); 2304 use(argument);
2295 arguments.add(pop()); 2305 arguments.add(pop());
2296 } 2306 }
2297 registry.registerStaticUse(new StaticUse.staticInvoke( 2307 registry.registerStaticUse(new StaticUse.staticInvoke(
2298 helper, new CallStructure.unnamed(arguments.length))); 2308 helper, new CallStructure.unnamed(arguments.length)));
2299 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false), 2309 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false),
2300 sourceInformation: sourceInformation); 2310 sourceInformation: sourceInformation);
2301 // BUG(4906): Using throw/return here adds to the size of the generated code 2311 // BUG(4906): Using throw/return here adds to the size of the generated code
2302 // but it has the advantage of explicitly telling the JS engine that 2312 // but it has the advantage of explicitly telling the JS engine that
2303 // this code path will terminate abruptly. Needs more work. 2313 // this code path will terminate abruptly. Needs more work.
2304 if (helper == helpers.wrapExceptionHelper) { 2314 if (helper == helpers.wrapExceptionHelper) {
2305 pushStatement( 2315 pushStatement(
2306 new js.Throw(value).withSourceInformation(sourceInformation)); 2316 new js.Throw(value).withSourceInformation(sourceInformation));
2307 } else { 2317 } else {
2308 Element element = work.element; 2318 Entity element = work.element;
2309 if (element is FunctionElement && element.asyncMarker.isYielding) { 2319 if (element is FunctionElement && element.asyncMarker.isYielding) {
2310 // `return <expr>;` is illegal in a sync* or async* function. 2320 // `return <expr>;` is illegal in a sync* or async* function.
2311 // To have the async-translator working, we avoid introducing 2321 // To have the async-translator working, we avoid introducing
2312 // `return` nodes. 2322 // `return` nodes.
2313 pushStatement(new js.ExpressionStatement(value) 2323 pushStatement(new js.ExpressionStatement(value)
2314 .withSourceInformation(sourceInformation)); 2324 .withSourceInformation(sourceInformation));
2315 } else { 2325 } else {
2316 pushStatement( 2326 pushStatement(
2317 new js.Return(value).withSourceInformation(sourceInformation)); 2327 new js.Return(value).withSourceInformation(sourceInformation));
2318 } 2328 }
2319 } 2329 }
2320 } 2330 }
2321 2331
2322 visitThrowExpression(HThrowExpression node) { 2332 visitThrowExpression(HThrowExpression node) {
2323 HInstruction argument = node.inputs[0]; 2333 HInstruction argument = node.inputs[0];
2324 use(argument); 2334 use(argument);
2325 2335
2326 Element helper = helpers.throwExpressionHelper; 2336 FunctionEntity helper = helpers.throwExpressionHelper;
2327 registry.registerStaticUse( 2337 registry.registerStaticUse(
2328 new StaticUse.staticInvoke(helper, CallStructure.ONE_ARG)); 2338 new StaticUse.staticInvoke(helper, CallStructure.ONE_ARG));
2329 2339
2330 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper); 2340 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
2331 js.Call value = new js.Call(jsHelper, [pop()]) 2341 js.Call value = new js.Call(jsHelper, [pop()])
2332 .withSourceInformation(node.sourceInformation); 2342 .withSourceInformation(node.sourceInformation);
2333 push(value); 2343 push(value);
2334 } 2344 }
2335 2345
2336 void visitSwitch(HSwitch node) { 2346 void visitSwitch(HSwitch node) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2390 if (node.usedBy.length == 1 && 2400 if (node.usedBy.length == 1 &&
2391 node.usedBy[0] is HStringConcat && 2401 node.usedBy[0] is HStringConcat &&
2392 node.usedBy[0].inputs[1] == node) { 2402 node.usedBy[0].inputs[1] == node) {
2393 // The context is already <string> + value. 2403 // The context is already <string> + value.
2394 } else { 2404 } else {
2395 // Force an empty string for the first operand. 2405 // Force an empty string for the first operand.
2396 push(new js.Binary('+', js.string(""), pop()) 2406 push(new js.Binary('+', js.string(""), pop())
2397 .withSourceInformation(node.sourceInformation)); 2407 .withSourceInformation(node.sourceInformation));
2398 } 2408 }
2399 } else { 2409 } else {
2400 Element convertToString = backend.helpers.stringInterpolationHelper; 2410 FunctionEntity convertToString =
2411 backend.helpers.stringInterpolationHelper;
2401 registry.registerStaticUse( 2412 registry.registerStaticUse(
2402 new StaticUse.staticInvoke(convertToString, CallStructure.ONE_ARG)); 2413 new StaticUse.staticInvoke(convertToString, CallStructure.ONE_ARG));
2403 js.Expression jsHelper = 2414 js.Expression jsHelper =
2404 backend.emitter.staticFunctionAccess(convertToString); 2415 backend.emitter.staticFunctionAccess(convertToString);
2405 use(input); 2416 use(input);
2406 push(new js.Call(jsHelper, <js.Expression>[pop()], 2417 push(new js.Call(jsHelper, <js.Expression>[pop()],
2407 sourceInformation: node.sourceInformation)); 2418 sourceInformation: node.sourceInformation));
2408 } 2419 }
2409 } 2420 }
2410 2421
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
2549 } 2560 }
2550 2561
2551 void checkNonNull(HInstruction input) { 2562 void checkNonNull(HInstruction input) {
2552 use(input); 2563 use(input);
2553 push(new js.Binary('!=', pop(), new js.LiteralNull())); 2564 push(new js.Binary('!=', pop(), new js.LiteralNull()));
2554 } 2565 }
2555 2566
2556 void checkType(HInstruction input, HInstruction interceptor, DartType type, 2567 void checkType(HInstruction input, HInstruction interceptor, DartType type,
2557 SourceInformation sourceInformation, 2568 SourceInformation sourceInformation,
2558 {bool negative: false}) { 2569 {bool negative: false}) {
2559 Element element = type.element; 2570 if (type.isInterfaceType) {
2560 if (element == helpers.jsArrayClass) { 2571 InterfaceType interfaceType = type;
2561 checkArray(input, negative ? '!==' : '==='); 2572 ClassEntity element = interfaceType.element;
2562 return; 2573 if (element == helpers.jsArrayClass) {
2563 } else if (element == helpers.jsMutableArrayClass) { 2574 checkArray(input, negative ? '!==' : '===');
2564 if (negative) { 2575 return;
2565 checkImmutableArray(input); 2576 } else if (element == helpers.jsMutableArrayClass) {
2566 } else { 2577 if (negative) {
2567 checkMutableArray(input); 2578 checkImmutableArray(input);
2579 } else {
2580 checkMutableArray(input);
2581 }
2582 return;
2583 } else if (element == helpers.jsExtendableArrayClass) {
2584 if (negative) {
2585 checkFixedArray(input);
2586 } else {
2587 checkExtendableArray(input);
2588 }
2589 return;
2590 } else if (element == helpers.jsFixedArrayClass) {
2591 if (negative) {
2592 checkExtendableArray(input);
2593 } else {
2594 checkFixedArray(input);
2595 }
2596 return;
2597 } else if (element == helpers.jsUnmodifiableArrayClass) {
2598 if (negative) {
2599 checkMutableArray(input);
2600 } else {
2601 checkImmutableArray(input);
2602 }
2603 return;
2568 } 2604 }
2569 return;
2570 } else if (element == helpers.jsExtendableArrayClass) {
2571 if (negative) {
2572 checkFixedArray(input);
2573 } else {
2574 checkExtendableArray(input);
2575 }
2576 return;
2577 } else if (element == helpers.jsFixedArrayClass) {
2578 if (negative) {
2579 checkExtendableArray(input);
2580 } else {
2581 checkFixedArray(input);
2582 }
2583 return;
2584 } else if (element == helpers.jsUnmodifiableArrayClass) {
2585 if (negative) {
2586 checkMutableArray(input);
2587 } else {
2588 checkImmutableArray(input);
2589 }
2590 return;
2591 } 2605 }
2592 if (interceptor != null) { 2606 if (interceptor != null) {
2593 checkTypeViaProperty(interceptor, type, sourceInformation, 2607 checkTypeViaProperty(interceptor, type, sourceInformation,
2594 negative: negative); 2608 negative: negative);
2595 } else { 2609 } else {
2596 checkTypeViaProperty(input, type, sourceInformation, negative: negative); 2610 checkTypeViaProperty(input, type, sourceInformation, negative: negative);
2597 } 2611 }
2598 } 2612 }
2599 2613
2600 void checkTypeViaProperty( 2614 void checkTypeViaProperty(
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2632 registry.registerInstantiation(type); 2646 registry.registerInstantiation(type);
2633 } 2647 }
2634 2648
2635 void handleNumberOrStringSupertypeCheck( 2649 void handleNumberOrStringSupertypeCheck(
2636 HInstruction input, 2650 HInstruction input,
2637 HInstruction interceptor, 2651 HInstruction interceptor,
2638 DartType type, 2652 DartType type,
2639 SourceInformation sourceInformation, 2653 SourceInformation sourceInformation,
2640 {bool negative: false}) { 2654 {bool negative: false}) {
2641 assert(!identical(type.element, commonElements.listClass) && 2655 assert(!identical(type.element, commonElements.listClass) &&
2642 !Elements.isListSupertype(type.element, commonElements) && 2656 !commonElements.isListSupertype(type.element) &&
2643 !Elements.isStringOnlySupertype(type.element, commonElements)); 2657 !commonElements.isStringOnlySupertype(type.element));
2644 String relation = negative ? '!==' : '==='; 2658 String relation = negative ? '!==' : '===';
2645 checkNum(input, relation, sourceInformation); 2659 checkNum(input, relation, sourceInformation);
2646 js.Expression numberTest = pop(); 2660 js.Expression numberTest = pop();
2647 checkString(input, relation, sourceInformation); 2661 checkString(input, relation, sourceInformation);
2648 js.Expression stringTest = pop(); 2662 js.Expression stringTest = pop();
2649 checkObject(input, relation, sourceInformation); 2663 checkObject(input, relation, sourceInformation);
2650 js.Expression objectTest = pop(); 2664 js.Expression objectTest = pop();
2651 checkType(input, interceptor, type, sourceInformation, negative: negative); 2665 checkType(input, interceptor, type, sourceInformation, negative: negative);
2652 String combiner = negative ? '&&' : '||'; 2666 String combiner = negative ? '&&' : '||';
2653 String combiner2 = negative ? '||' : '&&'; 2667 String combiner2 = negative ? '||' : '&&';
2654 push(new js.Binary( 2668 push(new js.Binary(
2655 combiner, 2669 combiner,
2656 new js.Binary(combiner, numberTest, stringTest) 2670 new js.Binary(combiner, numberTest, stringTest)
2657 .withSourceInformation(sourceInformation), 2671 .withSourceInformation(sourceInformation),
2658 new js.Binary(combiner2, objectTest, pop()) 2672 new js.Binary(combiner2, objectTest, pop())
2659 .withSourceInformation(sourceInformation)) 2673 .withSourceInformation(sourceInformation))
2660 .withSourceInformation(sourceInformation)); 2674 .withSourceInformation(sourceInformation));
2661 } 2675 }
2662 2676
2663 void handleStringSupertypeCheck(HInstruction input, HInstruction interceptor, 2677 void handleStringSupertypeCheck(HInstruction input, HInstruction interceptor,
2664 DartType type, SourceInformation sourceInformation, 2678 DartType type, SourceInformation sourceInformation,
2665 {bool negative: false}) { 2679 {bool negative: false}) {
2666 assert(!identical(type.element, commonElements.listClass) && 2680 assert(!identical(type.element, commonElements.listClass) &&
2667 !Elements.isListSupertype(type.element, commonElements) && 2681 !commonElements.isListSupertype(type.element) &&
2668 !Elements.isNumberOrStringSupertype(type.element, commonElements)); 2682 !commonElements.isNumberOrStringSupertype(type.element));
2669 String relation = negative ? '!==' : '==='; 2683 String relation = negative ? '!==' : '===';
2670 checkString(input, relation, sourceInformation); 2684 checkString(input, relation, sourceInformation);
2671 js.Expression stringTest = pop(); 2685 js.Expression stringTest = pop();
2672 checkObject(input, relation, sourceInformation); 2686 checkObject(input, relation, sourceInformation);
2673 js.Expression objectTest = pop(); 2687 js.Expression objectTest = pop();
2674 checkType(input, interceptor, type, sourceInformation, negative: negative); 2688 checkType(input, interceptor, type, sourceInformation, negative: negative);
2675 String combiner = negative ? '||' : '&&'; 2689 String combiner = negative ? '||' : '&&';
2676 push(new js.Binary(negative ? '&&' : '||', stringTest, 2690 push(new js.Binary(negative ? '&&' : '||', stringTest,
2677 new js.Binary(combiner, objectTest, pop()))); 2691 new js.Binary(combiner, objectTest, pop())));
2678 } 2692 }
2679 2693
2680 void handleListOrSupertypeCheck(HInstruction input, HInstruction interceptor, 2694 void handleListOrSupertypeCheck(HInstruction input, HInstruction interceptor,
2681 DartType type, SourceInformation sourceInformation, 2695 DartType type, SourceInformation sourceInformation,
2682 {bool negative: false}) { 2696 {bool negative: false}) {
2683 assert(!identical(type.element, commonElements.stringClass) && 2697 assert(!identical(type.element, commonElements.stringClass) &&
2684 !Elements.isStringOnlySupertype(type.element, commonElements) && 2698 !commonElements.isStringOnlySupertype(type.element) &&
2685 !Elements.isNumberOrStringSupertype(type.element, commonElements)); 2699 !commonElements.isNumberOrStringSupertype(type.element));
2686 String relation = negative ? '!==' : '==='; 2700 String relation = negative ? '!==' : '===';
2687 checkObject(input, relation, sourceInformation); 2701 checkObject(input, relation, sourceInformation);
2688 js.Expression objectTest = pop(); 2702 js.Expression objectTest = pop();
2689 checkArray(input, relation); 2703 checkArray(input, relation);
2690 js.Expression arrayTest = pop(); 2704 js.Expression arrayTest = pop();
2691 checkType(input, interceptor, type, sourceInformation, negative: negative); 2705 checkType(input, interceptor, type, sourceInformation, negative: negative);
2692 String combiner = negative ? '&&' : '||'; 2706 String combiner = negative ? '&&' : '||';
2693 push(new js.Binary(negative ? '||' : '&&', objectTest, 2707 push(new js.Binary(negative ? '||' : '&&', objectTest,
2694 new js.Binary(combiner, arrayTest, pop())) 2708 new js.Binary(combiner, arrayTest, pop()))
2695 .withSourceInformation(sourceInformation)); 2709 .withSourceInformation(sourceInformation));
(...skipping 16 matching lines...) Expand all
2712 // be changed to match. 2726 // be changed to match.
2713 assert(relation == '===' || relation == '!=='); 2727 assert(relation == '===' || relation == '!==');
2714 bool negative = relation == '!=='; 2728 bool negative = relation == '!==';
2715 2729
2716 if (node.isVariableCheck || node.isCompoundCheck) { 2730 if (node.isVariableCheck || node.isCompoundCheck) {
2717 use(node.checkCall); 2731 use(node.checkCall);
2718 if (negative) push(new js.Prefix('!', pop())); 2732 if (negative) push(new js.Prefix('!', pop()));
2719 } else { 2733 } else {
2720 assert(node.isRawCheck); 2734 assert(node.isRawCheck);
2721 HInstruction interceptor = node.interceptor; 2735 HInstruction interceptor = node.interceptor;
2722 ClassElement objectClass = commonElements.objectClass; 2736 InterfaceType interfaceType = type;
2723 Element element = type.element; 2737 ClassEntity element = interfaceType.element;
2724 if (element == commonElements.nullClass) { 2738 if (element == commonElements.nullClass) {
2725 if (negative) { 2739 if (negative) {
2726 checkNonNull(input); 2740 checkNonNull(input);
2727 } else { 2741 } else {
2728 checkNull(input); 2742 checkNull(input);
2729 } 2743 }
2730 } else if (identical(element, objectClass) || type.treatAsDynamic) { 2744 } else if (element ==
2745 commonElements.objectClass /* || type.treatAsDynamic*/) {
2731 // The constant folder also does this optimization, but we make 2746 // The constant folder also does this optimization, but we make
2732 // it safe by assuming it may have not run. 2747 // it safe by assuming it may have not run.
2733 push(newLiteralBool(!negative, sourceInformation)); 2748 push(newLiteralBool(!negative, sourceInformation));
2734 } else if (element == commonElements.stringClass) { 2749 } else if (element == commonElements.stringClass) {
2735 checkString(input, relation, sourceInformation); 2750 checkString(input, relation, sourceInformation);
2736 } else if (element == commonElements.doubleClass) { 2751 } else if (element == commonElements.doubleClass) {
2737 checkDouble(input, relation, sourceInformation); 2752 checkDouble(input, relation, sourceInformation);
2738 } else if (element == commonElements.numClass) { 2753 } else if (element == commonElements.numClass) {
2739 checkNum(input, relation, sourceInformation); 2754 checkNum(input, relation, sourceInformation);
2740 } else if (element == commonElements.boolClass) { 2755 } else if (element == commonElements.boolClass) {
2741 checkBool(input, relation, sourceInformation); 2756 checkBool(input, relation, sourceInformation);
2742 } else if (element == commonElements.intClass) { 2757 } else if (element == commonElements.intClass) {
2743 // The is check in the code tells us that it might not be an 2758 // The is check in the code tells us that it might not be an
2744 // int. So we do a typeof first to avoid possible 2759 // int. So we do a typeof first to avoid possible
2745 // deoptimizations on the JS engine due to the Math.floor check. 2760 // deoptimizations on the JS engine due to the Math.floor check.
2746 checkNum(input, relation, sourceInformation); 2761 checkNum(input, relation, sourceInformation);
2747 js.Expression numTest = pop(); 2762 js.Expression numTest = pop();
2748 checkBigInt(input, relation, sourceInformation); 2763 checkBigInt(input, relation, sourceInformation);
2749 push(new js.Binary(negative ? '||' : '&&', numTest, pop()) 2764 push(new js.Binary(negative ? '||' : '&&', numTest, pop())
2750 .withSourceInformation(sourceInformation)); 2765 .withSourceInformation(sourceInformation));
2751 } else if (node.useInstanceOf) { 2766 } else if (node.useInstanceOf) {
2752 assert(interceptor == null); 2767 assert(interceptor == null);
2753 checkTypeViaInstanceof(input, type, sourceInformation, 2768 checkTypeViaInstanceof(input, type, sourceInformation,
2754 negative: negative); 2769 negative: negative);
2755 } else if (Elements.isNumberOrStringSupertype(element, commonElements)) { 2770 } else if (commonElements.isNumberOrStringSupertype(element)) {
2756 handleNumberOrStringSupertypeCheck( 2771 handleNumberOrStringSupertypeCheck(
2757 input, interceptor, type, sourceInformation, 2772 input, interceptor, type, sourceInformation,
2758 negative: negative); 2773 negative: negative);
2759 } else if (Elements.isStringOnlySupertype(element, commonElements)) { 2774 } else if (commonElements.isStringOnlySupertype(element)) {
2760 handleStringSupertypeCheck(input, interceptor, type, sourceInformation, 2775 handleStringSupertypeCheck(input, interceptor, type, sourceInformation,
2761 negative: negative); 2776 negative: negative);
2762 } else if (identical(element, commonElements.listClass) || 2777 } else if (element == commonElements.listClass ||
2763 Elements.isListSupertype(element, commonElements)) { 2778 commonElements.isListSupertype(element)) {
2764 handleListOrSupertypeCheck(input, interceptor, type, sourceInformation, 2779 handleListOrSupertypeCheck(input, interceptor, type, sourceInformation,
2765 negative: negative); 2780 negative: negative);
2766 } else if (type.isFunctionType) { 2781 } else if (type.isFunctionType) {
2767 checkType(input, interceptor, type, sourceInformation, 2782 checkType(input, interceptor, type, sourceInformation,
2768 negative: negative); 2783 negative: negative);
2769 } else if ((input.canBePrimitive(closedWorld) && 2784 } else if ((input.canBePrimitive(closedWorld) &&
2770 !input.canBePrimitiveArray(closedWorld)) || 2785 !input.canBePrimitiveArray(closedWorld)) ||
2771 input.canBeNull()) { 2786 input.canBeNull()) {
2772 checkObject(input, relation, node.sourceInformation); 2787 checkObject(input, relation, node.sourceInformation);
2773 js.Expression objectTest = pop(); 2788 js.Expression objectTest = pop();
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2854 } 2869 }
2855 currentContainer = oldContainer; 2870 currentContainer = oldContainer;
2856 body = unwrapStatement(body); 2871 body = unwrapStatement(body);
2857 pushStatement(new js.If.noElse(test, body) 2872 pushStatement(new js.If.noElse(test, body)
2858 .withSourceInformation(node.sourceInformation)); 2873 .withSourceInformation(node.sourceInformation));
2859 return; 2874 return;
2860 } 2875 }
2861 2876
2862 assert(node.isCheckedModeCheck || node.isCastTypeCheck); 2877 assert(node.isCheckedModeCheck || node.isCastTypeCheck);
2863 DartType type = node.typeExpression; 2878 DartType type = node.typeExpression;
2864 assert(type.kind != TypeKind.TYPEDEF); 2879 assert(!type.isTypedef);
2865 if (type.isFunctionType) { 2880 if (type.isFunctionType) {
2866 // TODO(5022): We currently generate $isFunction checks for 2881 // TODO(5022): We currently generate $isFunction checks for
2867 // function types. 2882 // function types.
2868 registry.registerTypeUse( 2883 registry.registerTypeUse(
2869 new TypeUse.isCheck(compiler.commonElements.functionType)); 2884 new TypeUse.isCheck(compiler.commonElements.functionType));
2870 } 2885 }
2871 registry.registerTypeUse(new TypeUse.isCheck(type)); 2886 registry.registerTypeUse(new TypeUse.isCheck(type));
2872 2887
2873 CheckedModeHelper helper; 2888 CheckedModeHelper helper;
2874 if (node.isBooleanConversionCheck) { 2889 if (node.isBooleanConversionCheck) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2951 } 2966 }
2952 } 2967 }
2953 2968
2954 void visitTypeInfoReadRaw(HTypeInfoReadRaw node) { 2969 void visitTypeInfoReadRaw(HTypeInfoReadRaw node) {
2955 use(node.inputs[0]); 2970 use(node.inputs[0]);
2956 js.Expression receiver = pop(); 2971 js.Expression receiver = pop();
2957 push(js.js(r'#.#', [receiver, backend.namer.rtiFieldName])); 2972 push(js.js(r'#.#', [receiver, backend.namer.rtiFieldName]));
2958 } 2973 }
2959 2974
2960 void visitTypeInfoReadVariable(HTypeInfoReadVariable node) { 2975 void visitTypeInfoReadVariable(HTypeInfoReadVariable node) {
2961 TypeVariableElement element = node.variable.element; 2976 TypeVariableEntity element = node.variable.element;
2962 2977
2963 int index = element.index; 2978 int index = element.index;
2964 HInstruction object = node.object; 2979 HInstruction object = node.object;
2965 use(object); 2980 use(object);
2966 js.Expression receiver = pop(); 2981 js.Expression receiver = pop();
2967 2982
2968 if (typeVariableAccessNeedsSubstitution(element, object.instructionType)) { 2983 if (typeVariableAccessNeedsSubstitution(element, object.instructionType)) {
2969 js.Expression typeName = 2984 js.Expression typeName =
2970 js.quoteName(backend.namer.runtimeTypeName(element.enclosingClass)); 2985 js.quoteName(backend.namer.runtimeTypeName(element.typeDeclaration));
2971 Element helperElement = helpers.getRuntimeTypeArgument; 2986 FunctionEntity helperElement = helpers.getRuntimeTypeArgument;
2972 registry.registerStaticUse( 2987 registry.registerStaticUse(
2973 new StaticUse.staticInvoke(helperElement, CallStructure.THREE_ARGS)); 2988 new StaticUse.staticInvoke(helperElement, CallStructure.THREE_ARGS));
2974 js.Expression helper = 2989 js.Expression helper =
2975 backend.emitter.staticFunctionAccess(helperElement); 2990 backend.emitter.staticFunctionAccess(helperElement);
2976 push(js.js( 2991 push(js.js(
2977 r'#(#, #, #)', [helper, receiver, typeName, js.js.number(index)])); 2992 r'#(#, #, #)', [helper, receiver, typeName, js.js.number(index)]));
2978 } else { 2993 } else {
2979 Element helperElement = helpers.getTypeArgumentByIndex; 2994 FunctionEntity helperElement = helpers.getTypeArgumentByIndex;
2980 registry.registerStaticUse( 2995 registry.registerStaticUse(
2981 new StaticUse.staticInvoke(helperElement, CallStructure.TWO_ARGS)); 2996 new StaticUse.staticInvoke(helperElement, CallStructure.TWO_ARGS));
2982 js.Expression helper = 2997 js.Expression helper =
2983 backend.emitter.staticFunctionAccess(helperElement); 2998 backend.emitter.staticFunctionAccess(helperElement);
2984 push(js.js(r'#(#, #)', [helper, receiver, js.js.number(index)])); 2999 push(js.js(r'#(#, #)', [helper, receiver, js.js.number(index)]));
2985 } 3000 }
2986 } 3001 }
2987 3002
2988 void visitTypeInfoExpression(HTypeInfoExpression node) { 3003 void visitTypeInfoExpression(HTypeInfoExpression node) {
2989 List<js.Expression> arguments = <js.Expression>[]; 3004 List<js.Expression> arguments = <js.Expression>[];
(...skipping 15 matching lines...) Expand all
3005 // We expect only flat types for the INSTANCE representation. 3020 // We expect only flat types for the INSTANCE representation.
3006 assert( 3021 assert(
3007 node.dartType == (node.dartType as InterfaceType).element.thisType); 3022 node.dartType == (node.dartType as InterfaceType).element.thisType);
3008 registry.registerInstantiatedClass(commonElements.listClass); 3023 registry.registerInstantiatedClass(commonElements.listClass);
3009 push(new js.ArrayInitializer(arguments) 3024 push(new js.ArrayInitializer(arguments)
3010 .withSourceInformation(node.sourceInformation)); 3025 .withSourceInformation(node.sourceInformation));
3011 } 3026 }
3012 } 3027 }
3013 3028
3014 bool typeVariableAccessNeedsSubstitution( 3029 bool typeVariableAccessNeedsSubstitution(
3015 TypeVariableElement element, TypeMask receiverMask) { 3030 TypeVariableEntity element, TypeMask receiverMask) {
3016 ClassElement cls = element.enclosingClass; 3031 ClassEntity cls = element.typeDeclaration;
3017 3032
3018 // See if the receiver type narrows the set of classes to ones that can be 3033 // See if the receiver type narrows the set of classes to ones that can be
3019 // indexed. 3034 // indexed.
3020 // TODO(sra): Currently the only convenient query is [singleClass]. We 3035 // TODO(sra): Currently the only convenient query is [singleClass]. We
3021 // should iterate over all the concrete classes in [receiverMask]. 3036 // should iterate over all the concrete classes in [receiverMask].
3022 ClassElement receiverClass = receiverMask.singleClass(closedWorld); 3037 ClassEntity receiverClass = receiverMask.singleClass(closedWorld);
3023 if (receiverClass != null) { 3038 if (receiverClass != null) {
3024 if (backend.rti.isTrivialSubstitution(receiverClass, cls)) { 3039 if (backend.rti.isTrivialSubstitution(receiverClass, cls)) {
3025 return false; 3040 return false;
3026 } 3041 }
3027 } 3042 }
3028 3043
3029 if (closedWorld.isUsedAsMixin(cls)) return true; 3044 if (closedWorld.isUsedAsMixin(cls)) return true;
3030 3045
3031 return closedWorld.anyStrictSubclassOf(cls, (ClassElement subclass) { 3046 return closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) {
3032 return !backend.rti.isTrivialSubstitution(subclass, cls); 3047 return !backend.rti.isTrivialSubstitution(subclass, cls);
3033 }); 3048 });
3034 } 3049 }
3035 3050
3036 void visitReadTypeVariable(HReadTypeVariable node) { 3051 void visitReadTypeVariable(HReadTypeVariable node) {
3037 TypeVariableElement element = node.dartType.element; 3052 TypeVariableEntity element = node.dartType.element;
3038 Element helperElement = helpers.convertRtiToRuntimeType; 3053 FunctionEntity helperElement = helpers.convertRtiToRuntimeType;
3039 registry.registerStaticUse( 3054 registry.registerStaticUse(
3040 new StaticUse.staticInvoke(helperElement, CallStructure.ONE_ARG)); 3055 new StaticUse.staticInvoke(helperElement, CallStructure.ONE_ARG));
3041 3056
3042 use(node.inputs[0]); 3057 use(node.inputs[0]);
3043 if (node.hasReceiver) { 3058 if (node.hasReceiver) {
3044 if (backend.isInterceptorClass(element.enclosingClass)) { 3059 if (backend.isInterceptorClass(element.typeDeclaration)) {
3045 int index = element.index; 3060 int index = element.index;
3046 js.Expression receiver = pop(); 3061 js.Expression receiver = pop();
3047 js.Expression helper = 3062 js.Expression helper =
3048 backend.emitter.staticFunctionAccess(helperElement); 3063 backend.emitter.staticFunctionAccess(helperElement);
3049 js.Expression rtiFieldName = backend.namer.rtiFieldName; 3064 js.Expression rtiFieldName = backend.namer.rtiFieldName;
3050 push(js.js(r'#(#.# && #.#[#])', [ 3065 push(js.js(r'#(#.# && #.#[#])', [
3051 helper, 3066 helper,
3052 receiver, 3067 receiver,
3053 rtiFieldName, 3068 rtiFieldName,
3054 receiver, 3069 receiver,
(...skipping 11 matching lines...) Expand all
3066 } 3081 }
3067 } 3082 }
3068 3083
3069 void visitInterfaceType(HInterfaceType node) { 3084 void visitInterfaceType(HInterfaceType node) {
3070 List<js.Expression> typeArguments = <js.Expression>[]; 3085 List<js.Expression> typeArguments = <js.Expression>[];
3071 for (HInstruction type in node.inputs) { 3086 for (HInstruction type in node.inputs) {
3072 use(type); 3087 use(type);
3073 typeArguments.add(pop()); 3088 typeArguments.add(pop());
3074 } 3089 }
3075 InterfaceType type = node.dartType; 3090 InterfaceType type = node.dartType;
3076 ClassElement cls = type.element; 3091 ClassEntity cls = type.element;
3077 var arguments = [backend.emitter.typeAccess(cls)]; 3092 var arguments = [backend.emitter.typeAccess(cls)];
3078 if (!typeArguments.isEmpty) { 3093 if (!typeArguments.isEmpty) {
3079 arguments.add(new js.ArrayInitializer(typeArguments)); 3094 arguments.add(new js.ArrayInitializer(typeArguments));
3080 } 3095 }
3081 push(js.js('#(#)', [ 3096 push(js.js('#(#)', [
3082 accessHelper(helpers.buildInterfaceType, arguments.length), 3097 accessHelper(helpers.buildInterfaceType, arguments.length),
3083 arguments 3098 arguments
3084 ])); 3099 ]));
3085 } 3100 }
3086 3101
(...skipping 14 matching lines...) Expand all
3101 registry.registerStaticUse(new StaticUse.staticInvoke( 3116 registry.registerStaticUse(new StaticUse.staticInvoke(
3102 helper, new CallStructure.unnamed(argumentCount))); 3117 helper, new CallStructure.unnamed(argumentCount)));
3103 return backend.emitter.staticFunctionAccess(helper); 3118 return backend.emitter.staticFunctionAccess(helper);
3104 } 3119 }
3105 3120
3106 @override 3121 @override
3107 void visitRef(HRef node) { 3122 void visitRef(HRef node) {
3108 visit(node.value); 3123 visit(node.value);
3109 } 3124 }
3110 } 3125 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698