| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import '../common.dart'; | 5 import '../common.dart'; |
| 6 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 6 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 7 import '../common/tasks.dart' show CompilerTask; | 7 import '../common/tasks.dart' show CompilerTask; |
| 8 import '../compiler.dart' show Compiler; | 8 import '../compiler.dart' show Compiler; |
| 9 import '../constants/constant_system.dart'; | 9 import '../constants/constant_system.dart'; |
| 10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| 11 import '../core_types.dart' show CoreClasses; | 11 import '../core_types.dart' show CoreClasses; |
| 12 import '../dart_types.dart'; | 12 import '../dart_types.dart'; |
| 13 import '../elements/elements.dart'; | 13 import '../elements/elements.dart'; |
| 14 import '../elements/entities.dart'; |
| 14 import '../io/source_information.dart'; | 15 import '../io/source_information.dart'; |
| 15 import '../js/js.dart' as js; | 16 import '../js/js.dart' as js; |
| 16 import '../js_backend/backend_helpers.dart' show BackendHelpers; | 17 import '../js_backend/backend_helpers.dart' show BackendHelpers; |
| 17 import '../js_backend/js_backend.dart'; | 18 import '../js_backend/js_backend.dart'; |
| 18 import '../js_emitter/js_emitter.dart' show NativeEmitter; | 19 import '../js_emitter/js_emitter.dart' show NativeEmitter; |
| 19 import '../native/native.dart' as native; | 20 import '../native/native.dart' as native; |
| 20 import '../types/types.dart'; | 21 import '../types/types.dart'; |
| 21 import '../universe/call_structure.dart' show CallStructure; | 22 import '../universe/call_structure.dart' show CallStructure; |
| 22 import '../universe/selector.dart' show Selector; | 23 import '../universe/selector.dart' show Selector; |
| 23 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse; | 24 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse; |
| (...skipping 1551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1575 .withSourceInformation(node.sourceInformation)); | 1576 .withSourceInformation(node.sourceInformation)); |
| 1576 registry.registerUseInterceptor(); | 1577 registry.registerUseInterceptor(); |
| 1577 } | 1578 } |
| 1578 } | 1579 } |
| 1579 | 1580 |
| 1580 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { | 1581 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { |
| 1581 use(node.receiver); | 1582 use(node.receiver); |
| 1582 js.Expression object = pop(); | 1583 js.Expression object = pop(); |
| 1583 String methodName; | 1584 String methodName; |
| 1584 List<js.Expression> arguments = visitArguments(node.inputs); | 1585 List<js.Expression> arguments = visitArguments(node.inputs); |
| 1585 Element target = node.element; | 1586 MemberElement target = node.element; |
| 1586 | 1587 |
| 1587 // TODO(herhut): The namer should return the appropriate backendname here. | 1588 // TODO(herhut): The namer should return the appropriate backendname here. |
| 1588 if (target != null && !node.isInterceptedCall) { | 1589 if (target != null && !node.isInterceptedCall) { |
| 1589 if (target == helpers.jsArrayAdd) { | 1590 if (target == helpers.jsArrayAdd) { |
| 1590 methodName = 'push'; | 1591 methodName = 'push'; |
| 1591 } else if (target == helpers.jsArrayRemoveLast) { | 1592 } else if (target == helpers.jsArrayRemoveLast) { |
| 1592 methodName = 'pop'; | 1593 methodName = 'pop'; |
| 1593 } else if (target == helpers.jsStringSplit) { | 1594 } else if (target == helpers.jsStringSplit) { |
| 1594 methodName = 'split'; | 1595 methodName = 'split'; |
| 1595 // Split returns a List, so we make sure the backend knows the | 1596 // Split returns a List, so we make sure the backend knows the |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1673 // might hit a `noSuchMethod`, we register an untyped selector. | 1674 // might hit a `noSuchMethod`, we register an untyped selector. |
| 1674 return compiler.closedWorld.extendMaskIfReachesAll(selector, mask); | 1675 return compiler.closedWorld.extendMaskIfReachesAll(selector, mask); |
| 1675 } | 1676 } |
| 1676 | 1677 |
| 1677 void registerMethodInvoke(HInvokeDynamic node) { | 1678 void registerMethodInvoke(HInvokeDynamic node) { |
| 1678 Selector selector = node.selector; | 1679 Selector selector = node.selector; |
| 1679 | 1680 |
| 1680 // If we don't know what we're calling or if we are calling a getter, | 1681 // If we don't know what we're calling or if we are calling a getter, |
| 1681 // we need to register that fact that we may be calling a closure | 1682 // we need to register that fact that we may be calling a closure |
| 1682 // with the same arguments. | 1683 // with the same arguments. |
| 1683 Element target = node.element; | 1684 MemberElement target = node.element; |
| 1684 if (target == null || target.isGetter) { | 1685 if (target == null || target.isGetter) { |
| 1685 // TODO(kasperl): If we have a typed selector for the call, we | 1686 // TODO(kasperl): If we have a typed selector for the call, we |
| 1686 // may know something about the types of closures that need | 1687 // may know something about the types of closures that need |
| 1687 // the specific closure call method. | 1688 // the specific closure call method. |
| 1688 Selector call = new Selector.callClosureFrom(selector); | 1689 Selector call = new Selector.callClosureFrom(selector); |
| 1689 registry.registerDynamicUse(new DynamicUse(call, null)); | 1690 registry.registerDynamicUse(new DynamicUse(call, null)); |
| 1690 } | 1691 } |
| 1691 if (target != null) { | 1692 if (target != null) { |
| 1692 // This is a dynamic invocation which we have found to have a single | 1693 // This is a dynamic invocation which we have found to have a single |
| 1693 // target but for some reason haven't inlined. We are _still_ accessing | 1694 // target but for some reason haven't inlined. We are _still_ accessing |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1755 Selector call = new Selector.callClosureFrom(node.selector); | 1756 Selector call = new Selector.callClosureFrom(node.selector); |
| 1756 use(node.receiver); | 1757 use(node.receiver); |
| 1757 push(js | 1758 push(js |
| 1758 .propertyCall(pop(), backend.namer.invocationName(call), | 1759 .propertyCall(pop(), backend.namer.invocationName(call), |
| 1759 visitArguments(node.inputs)) | 1760 visitArguments(node.inputs)) |
| 1760 .withSourceInformation(node.sourceInformation)); | 1761 .withSourceInformation(node.sourceInformation)); |
| 1761 registry.registerDynamicUse(new DynamicUse(call, null)); | 1762 registry.registerDynamicUse(new DynamicUse(call, null)); |
| 1762 } | 1763 } |
| 1763 | 1764 |
| 1764 visitInvokeStatic(HInvokeStatic node) { | 1765 visitInvokeStatic(HInvokeStatic node) { |
| 1765 Element element = node.element; | 1766 MemberElement element = node.element; |
| 1766 List<DartType> instantiatedTypes = node.instantiatedTypes; | 1767 List<DartType> instantiatedTypes = node.instantiatedTypes; |
| 1767 | 1768 |
| 1768 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) { | 1769 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) { |
| 1769 instantiatedTypes.forEach((type) { | 1770 instantiatedTypes.forEach((type) { |
| 1770 registry.registerInstantiation(type); | 1771 registry.registerInstantiation(type); |
| 1771 }); | 1772 }); |
| 1772 } | 1773 } |
| 1773 | 1774 |
| 1774 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); | 1775 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); |
| 1775 | 1776 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1802 registry.registerStaticUse(element.isConstructor | 1803 registry.registerStaticUse(element.isConstructor |
| 1803 ? new StaticUse.constructorInvoke(element, callStructure) | 1804 ? new StaticUse.constructorInvoke(element, callStructure) |
| 1804 : new StaticUse.staticInvoke(element, callStructure)); | 1805 : new StaticUse.staticInvoke(element, callStructure)); |
| 1805 push(backend.emitter.staticFunctionAccess(element)); | 1806 push(backend.emitter.staticFunctionAccess(element)); |
| 1806 push(new js.Call(pop(), arguments, | 1807 push(new js.Call(pop(), arguments, |
| 1807 sourceInformation: node.sourceInformation)); | 1808 sourceInformation: node.sourceInformation)); |
| 1808 } | 1809 } |
| 1809 } | 1810 } |
| 1810 | 1811 |
| 1811 visitInvokeSuper(HInvokeSuper node) { | 1812 visitInvokeSuper(HInvokeSuper node) { |
| 1812 Element superElement = node.element; | 1813 MemberElement superElement = node.element; |
| 1813 ClassElement superClass = superElement.enclosingClass; | 1814 ClassElement superClass = superElement.enclosingClass; |
| 1814 if (superElement.isField) { | 1815 if (superElement.isField) { |
| 1815 js.Name fieldName = backend.namer.instanceFieldPropertyName(superElement); | 1816 js.Name fieldName = backend.namer.instanceFieldPropertyName(superElement); |
| 1816 use(node.inputs[0]); | 1817 use(node.inputs[0]); |
| 1817 js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName) | 1818 js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName) |
| 1818 .withSourceInformation(node.sourceInformation); | 1819 .withSourceInformation(node.sourceInformation); |
| 1819 if (node.isSetter) { | 1820 if (node.isSetter) { |
| 1820 registry.registerStaticUse(superElement.isSetter | 1821 registry.registerStaticUse(superElement.isSetter |
| 1821 ? new StaticUse.superSetterSet(superElement) | 1822 ? new StaticUse.superSetterSet(superElement) |
| 1822 : new StaticUse.superFieldSet(superElement)); | 1823 : new StaticUse.superFieldSet(superElement)); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1860 backend.namer.aliasedSuperMemberPropertyName(superElement), | 1861 backend.namer.aliasedSuperMemberPropertyName(superElement), |
| 1861 visitArguments(node.inputs, start: 1) | 1862 visitArguments(node.inputs, start: 1) |
| 1862 ]) // Skip receiver argument. | 1863 ]) // Skip receiver argument. |
| 1863 .withSourceInformation(node.sourceInformation)); | 1864 .withSourceInformation(node.sourceInformation)); |
| 1864 } | 1865 } |
| 1865 } | 1866 } |
| 1866 } | 1867 } |
| 1867 | 1868 |
| 1868 visitFieldGet(HFieldGet node) { | 1869 visitFieldGet(HFieldGet node) { |
| 1869 use(node.receiver); | 1870 use(node.receiver); |
| 1870 Element element = node.element; | 1871 MemberElement element = node.element; |
| 1871 if (node.isNullCheck) { | 1872 if (node.isNullCheck) { |
| 1872 // We access a JavaScript member we know all objects besides | 1873 // We access a JavaScript member we know all objects besides |
| 1873 // null and undefined have: V8 does not like accessing a member | 1874 // null and undefined have: V8 does not like accessing a member |
| 1874 // that does not exist. | 1875 // that does not exist. |
| 1875 push(new js.PropertyAccess.field(pop(), 'toString') | 1876 push(new js.PropertyAccess.field(pop(), 'toString') |
| 1876 .withSourceInformation(node.sourceInformation)); | 1877 .withSourceInformation(node.sourceInformation)); |
| 1877 } else if (element == helpers.jsIndexableLength) { | 1878 } else if (element == helpers.jsIndexableLength) { |
| 1878 // We're accessing a native JavaScript property called 'length' | 1879 // We're accessing a native JavaScript property called 'length' |
| 1879 // on a JS String or a JS array. Therefore, the name of that | 1880 // on a JS String or a JS array. Therefore, the name of that |
| 1880 // property should not be mangled. | 1881 // property should not be mangled. |
| 1881 push(new js.PropertyAccess.field(pop(), 'length') | 1882 push(new js.PropertyAccess.field(pop(), 'length') |
| 1882 .withSourceInformation(node.sourceInformation)); | 1883 .withSourceInformation(node.sourceInformation)); |
| 1883 } else { | 1884 } else { |
| 1884 js.Name name = backend.namer.instanceFieldPropertyName(element); | 1885 js.Name name = backend.namer.instanceFieldPropertyName(element); |
| 1885 push(new js.PropertyAccess(pop(), name) | 1886 push(new js.PropertyAccess(pop(), name) |
| 1886 .withSourceInformation(node.sourceInformation)); | 1887 .withSourceInformation(node.sourceInformation)); |
| 1887 registry.registerStaticUse(new StaticUse.fieldGet(element)); | 1888 registry.registerStaticUse(new StaticUse.fieldGet(element)); |
| 1888 } | 1889 } |
| 1889 } | 1890 } |
| 1890 | 1891 |
| 1891 visitFieldSet(HFieldSet node) { | 1892 visitFieldSet(HFieldSet node) { |
| 1892 Element element = node.element; | 1893 MemberElement element = node.element; |
| 1893 registry.registerStaticUse(new StaticUse.fieldSet(element)); | 1894 registry.registerStaticUse(new StaticUse.fieldSet(element)); |
| 1894 js.Name name = backend.namer.instanceFieldPropertyName(element); | 1895 js.Name name = backend.namer.instanceFieldPropertyName(element); |
| 1895 use(node.receiver); | 1896 use(node.receiver); |
| 1896 js.Expression receiver = pop(); | 1897 js.Expression receiver = pop(); |
| 1897 use(node.value); | 1898 use(node.value); |
| 1898 push(new js.Assignment(new js.PropertyAccess(receiver, name), pop()) | 1899 push(new js.Assignment(new js.PropertyAccess(receiver, name), pop()) |
| 1899 .withSourceInformation(node.sourceInformation)); | 1900 .withSourceInformation(node.sourceInformation)); |
| 1900 } | 1901 } |
| 1901 | 1902 |
| 1902 visitReadModifyWrite(HReadModifyWrite node) { | 1903 visitReadModifyWrite(HReadModifyWrite node) { |
| 1903 Element element = node.element; | 1904 FieldElement element = node.element; |
| 1904 registry.registerStaticUse(new StaticUse.fieldGet(element)); | 1905 registry.registerStaticUse(new StaticUse.fieldGet(element)); |
| 1905 registry.registerStaticUse(new StaticUse.fieldSet(element)); | 1906 registry.registerStaticUse(new StaticUse.fieldSet(element)); |
| 1906 js.Name name = backend.namer.instanceFieldPropertyName(element); | 1907 js.Name name = backend.namer.instanceFieldPropertyName(element); |
| 1907 use(node.receiver); | 1908 use(node.receiver); |
| 1908 js.Expression fieldReference = new js.PropertyAccess(pop(), name); | 1909 js.Expression fieldReference = new js.PropertyAccess(pop(), name); |
| 1909 if (node.isPreOp) { | 1910 if (node.isPreOp) { |
| 1910 push(new js.Prefix(node.jsOp, fieldReference) | 1911 push(new js.Prefix(node.jsOp, fieldReference) |
| 1911 .withSourceInformation(node.sourceInformation)); | 1912 .withSourceInformation(node.sourceInformation)); |
| 1912 } else if (node.isPostOp) { | 1913 } else if (node.isPostOp) { |
| 1913 push(new js.Postfix(node.jsOp, fieldReference) | 1914 push(new js.Postfix(node.jsOp, fieldReference) |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2272 js.Call value = new js.Call(jsHelper, [pop()]) | 2273 js.Call value = new js.Call(jsHelper, [pop()]) |
| 2273 .withSourceInformation(node.sourceInformation); | 2274 .withSourceInformation(node.sourceInformation); |
| 2274 push(value); | 2275 push(value); |
| 2275 } | 2276 } |
| 2276 | 2277 |
| 2277 void visitSwitch(HSwitch node) { | 2278 void visitSwitch(HSwitch node) { |
| 2278 // Switches are handled using [visitSwitchInfo]. | 2279 // Switches are handled using [visitSwitchInfo]. |
| 2279 } | 2280 } |
| 2280 | 2281 |
| 2281 void visitStatic(HStatic node) { | 2282 void visitStatic(HStatic node) { |
| 2282 Element element = node.element; | 2283 MemberEntity element = node.element; |
| 2283 assert(element.isFunction || element.isField); | 2284 assert(element.isFunction || element.isField); |
| 2284 if (element.isFunction) { | 2285 if (element.isFunction) { |
| 2285 push(backend.emitter | 2286 push(backend.emitter |
| 2286 .isolateStaticClosureAccess(element) | 2287 .isolateStaticClosureAccess(element) |
| 2287 .withSourceInformation(node.sourceInformation)); | 2288 .withSourceInformation(node.sourceInformation)); |
| 2288 registry.registerStaticUse(new StaticUse.staticTearOff(element)); | 2289 registry.registerStaticUse(new StaticUse.staticTearOff(element)); |
| 2289 } else { | 2290 } else { |
| 2290 push(backend.emitter | 2291 push(backend.emitter |
| 2291 .staticFieldAccess(element) | 2292 .staticFieldAccess(element) |
| 2292 .withSourceInformation(node.sourceInformation)); | 2293 .withSourceInformation(node.sourceInformation)); |
| 2293 registry.registerStaticUse(new StaticUse.staticGet(element)); | 2294 registry.registerStaticUse(new StaticUse.staticGet(element)); |
| 2294 } | 2295 } |
| 2295 } | 2296 } |
| 2296 | 2297 |
| 2297 void visitLazyStatic(HLazyStatic node) { | 2298 void visitLazyStatic(HLazyStatic node) { |
| 2298 Element element = node.element; | 2299 FieldEntity element = node.element; |
| 2299 registry.registerStaticUse(new StaticUse.staticInit(element)); | 2300 registry.registerStaticUse(new StaticUse.staticInit(element)); |
| 2300 js.Expression lazyGetter = | 2301 js.Expression lazyGetter = |
| 2301 backend.emitter.isolateLazyInitializerAccess(element); | 2302 backend.emitter.isolateLazyInitializerAccess(element); |
| 2302 js.Call call = new js.Call(lazyGetter, <js.Expression>[], | 2303 js.Call call = new js.Call(lazyGetter, <js.Expression>[], |
| 2303 sourceInformation: node.sourceInformation); | 2304 sourceInformation: node.sourceInformation); |
| 2304 push(call); | 2305 push(call); |
| 2305 } | 2306 } |
| 2306 | 2307 |
| 2307 void visitStaticStore(HStaticStore node) { | 2308 void visitStaticStore(HStaticStore node) { |
| 2308 registry.registerStaticUse(new StaticUse.staticSet(node.element)); | 2309 registry.registerStaticUse(new StaticUse.staticSet(node.element)); |
| (...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3028 registry.registerStaticUse(new StaticUse.staticInvoke( | 3029 registry.registerStaticUse(new StaticUse.staticInvoke( |
| 3029 helper, new CallStructure.unnamed(argumentCount))); | 3030 helper, new CallStructure.unnamed(argumentCount))); |
| 3030 return backend.emitter.staticFunctionAccess(helper); | 3031 return backend.emitter.staticFunctionAccess(helper); |
| 3031 } | 3032 } |
| 3032 | 3033 |
| 3033 @override | 3034 @override |
| 3034 void visitRef(HRef node) { | 3035 void visitRef(HRef node) { |
| 3035 visit(node.value); | 3036 visit(node.value); |
| 3036 } | 3037 } |
| 3037 } | 3038 } |
| OLD | NEW |