OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 | 7 |
8 class OldEmitter implements Emitter { | 8 class OldEmitter implements Emitter { |
9 final Compiler compiler; | 9 final Compiler compiler; |
10 final CodeEmitterTask task; | 10 final CodeEmitterTask task; |
(...skipping 1780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1791 } | 1791 } |
1792 | 1792 |
1793 /// Used by incremental compilation to patch up an object ([holder]) with a | 1793 /// Used by incremental compilation to patch up an object ([holder]) with a |
1794 /// new (or updated) method. [arrayOrFunction] is either the new method, or | 1794 /// new (or updated) method. [arrayOrFunction] is either the new method, or |
1795 /// an array containing the method (see | 1795 /// an array containing the method (see |
1796 /// [ContainerBuilder.addMemberMethodFromInfo]). [name] is the name of the | 1796 /// [ContainerBuilder.addMemberMethodFromInfo]). [name] is the name of the |
1797 /// new method. [isStatic] tells if method is static (or | 1797 /// new method. [isStatic] tells if method is static (or |
1798 /// top-level). [globalFunctionsAccess] is a reference to | 1798 /// top-level). [globalFunctionsAccess] is a reference to |
1799 /// [embeddedNames.GLOBAL_FUNCTIONS]. | 1799 /// [embeddedNames.GLOBAL_FUNCTIONS]. |
1800 jsAst.Fun buildIncrementalAddMethod() { | 1800 jsAst.Fun buildIncrementalAddMethod() { |
1801 return js(r''' | 1801 return js(r""" |
1802 function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { | 1802 function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { |
1803 var arrayOrFunction = originalDescriptor[name]; | 1803 var arrayOrFunction = originalDescriptor[name]; |
1804 var method; | 1804 var method; |
1805 if (arrayOrFunction.constructor === Array) { | 1805 if (arrayOrFunction.constructor === Array) { |
1806 var existing = holder[name]; | 1806 var existing = holder[name]; |
1807 var array = arrayOrFunction; | 1807 var array = arrayOrFunction; |
1808 var descriptor = Object.create(null); | 1808 var descriptor = Object.create(null); |
1809 this.addStubs( | 1809 this.addStubs( |
1810 descriptor, arrayOrFunction, name, isStatic, originalDescriptor, []); | 1810 descriptor, arrayOrFunction, name, isStatic, originalDescriptor, []); |
1811 method = descriptor[name]; | 1811 method = descriptor[name]; |
1812 for (var property in descriptor) { | 1812 for (var property in descriptor) { |
1813 if (!Object.prototype.hasOwnProperty.call(descriptor, property)) continue; | 1813 if (!Object.prototype.hasOwnProperty.call(descriptor, property)) continue; |
1814 var stub = descriptor[property]; | 1814 var stub = descriptor[property]; |
1815 var existingStub = holder[property]; | 1815 var existingStub = holder[property]; |
1816 if (stub === method || !existingStub) { | 1816 if (stub === method || !existingStub || !stub.$getterStub) { |
1817 // Not replacing an existing stub. | 1817 // Not replacing an existing getter stub. |
1818 holder[property] = method; | 1818 holder[property] = stub; |
1819 continue; | 1819 continue; |
1820 } | 1820 } |
1821 if (!stub.$getterStub) { | 1821 if (!stub.$getterStub) { |
1822 var error = new Error("Unexpected stub."); | 1822 var error = new Error('Unexpected stub.'); |
1823 error.stub = stub; | 1823 error.stub = stub; |
1824 throw error; | 1824 throw error; |
1825 } | 1825 } |
1826 // Invoke the existing stub to obtain the tear-off closure. | 1826 |
1827 existingStub = existingStub(); | 1827 // Existing getter stubs need special treatment as they may already have |
1828 // A stub already exist. Update all its references to [existing] to | 1828 // been called and produced a closure. |
1829 // [method]. | 1829 this.pendingStubs = this.pendingStubs || []; |
1830 for (var reference in existingStub) { | 1830 // It isn't safe to invoke the stub yet. |
1831 if (existingStub[reference] === existing) { | 1831 this.pendingStubs.push((function(holder, stub, existingStub, existing, |
1832 existingStub[reference] = method; | 1832 method) { |
| 1833 return function() { |
| 1834 var receiver = isStatic ? holder : new holder.constructor(); |
| 1835 // Invoke the existing stub to obtain the tear-off closure. |
| 1836 existingStub = existingStub.call(receiver); |
| 1837 // Invoke the new stub to create a tear-off closure we can use as a |
| 1838 // prototype. |
| 1839 stub = stub.call(receiver); |
| 1840 |
| 1841 var newProto = stub.constructor.prototype; |
| 1842 var existingProto = existingStub.constructor.prototype; |
| 1843 for (var stubProperty in newProto) { |
| 1844 if (!Object.prototype.hasOwnProperty.call(newProto, stubProperty)) |
| 1845 continue; |
| 1846 existingProto[stubProperty] = newProto[stubProperty]; |
| 1847 } |
| 1848 |
| 1849 // Update all the existing stub's references to [existing] to |
| 1850 // [method]. Instance tear-offs are call-by-name, so this isn't |
| 1851 // necessary for those. |
| 1852 if (!isStatic) return; |
| 1853 for (var reference in existingStub) { |
| 1854 if (existingStub[reference] === existing) { |
| 1855 existingStub[reference] = method; |
| 1856 } |
| 1857 } |
1833 } | 1858 } |
1834 } | 1859 })(holder, stub, existingStub, existing, method)); |
1835 } | 1860 } |
1836 } else { | 1861 } else { |
1837 method = arrayOrFunction; | 1862 method = arrayOrFunction; |
1838 holder[name] = method; | 1863 holder[name] = method; |
1839 } | 1864 } |
1840 if (isStatic) globalFunctionsAccess[name] = method; | 1865 if (isStatic) globalFunctionsAccess[name] = method; |
1841 }'''); | 1866 }"""); |
1842 } | 1867 } |
1843 | 1868 |
1844 /// Returns a map from OutputUnit to a hash of its content. The hash uniquely | 1869 /// Returns a map from OutputUnit to a hash of its content. The hash uniquely |
1845 /// identifies the code of the output-unit. It does not include | 1870 /// identifies the code of the output-unit. It does not include |
1846 /// boilerplate JS code, like the sourcemap directives or the hash | 1871 /// boilerplate JS code, like the sourcemap directives or the hash |
1847 /// itself. | 1872 /// itself. |
1848 Map<OutputUnit, String> emitDeferredOutputUnits() { | 1873 Map<OutputUnit, String> emitDeferredOutputUnits() { |
1849 if (!compiler.deferredLoadTask.isProgramSplit) return const {}; | 1874 if (!compiler.deferredLoadTask.isProgramSplit) return const {}; |
1850 | 1875 |
1851 Map<OutputUnit, CodeBuffer> outputBuffers = | 1876 Map<OutputUnit, CodeBuffer> outputBuffers = |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2172 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2197 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
2173 if (element.isInstanceMember) { | 2198 if (element.isInstanceMember) { |
2174 cachedClassBuilders.remove(element.enclosingClass); | 2199 cachedClassBuilders.remove(element.enclosingClass); |
2175 | 2200 |
2176 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2201 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
2177 | 2202 |
2178 } | 2203 } |
2179 } | 2204 } |
2180 } | 2205 } |
2181 } | 2206 } |
OLD | NEW |