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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 // Declare a function called "generateAccessor". This is used in | 348 // Declare a function called "generateAccessor". This is used in |
349 // defineClassFunction (it's a local declaration in init()). | 349 // defineClassFunction (it's a local declaration in init()). |
350 List result = <jsAst.Node>[ | 350 List result = <jsAst.Node>[ |
351 generateAccessorFunction, | 351 generateAccessorFunction, |
352 js('$generateAccessorHolder = generateAccessor'), | 352 js('$generateAccessorHolder = generateAccessor'), |
353 new jsAst.FunctionDeclaration( | 353 new jsAst.FunctionDeclaration( |
354 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; | 354 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; |
355 | 355 |
356 if (compiler.hasIncrementalSupport) { | 356 if (compiler.hasIncrementalSupport) { |
357 result.add( | 357 result.add( |
358 js(r'self.$dart_unsafe_eval.defineClass = defineClass')); | 358 js(r'#.defineClass = defineClass', [namer.accessIncrementalHelper])); |
359 } | 359 } |
360 | 360 |
361 if (hasIsolateSupport) { | 361 if (hasIsolateSupport) { |
362 jsAst.Expression classIdExtractorAccess = | 362 jsAst.Expression classIdExtractorAccess = |
363 generateEmbeddedGlobalAccess(embeddedNames.CLASS_ID_EXTRACTOR); | 363 generateEmbeddedGlobalAccess(embeddedNames.CLASS_ID_EXTRACTOR); |
364 var classIdExtractorAssignment = | 364 var classIdExtractorAssignment = |
365 js('# = function(o) { return o.constructor.name; }', | 365 js('# = function(o) { return o.constructor.name; }', |
366 classIdExtractorAccess); | 366 classIdExtractorAccess); |
367 | 367 |
368 jsAst.Expression classFieldsExtractorAccess = | 368 jsAst.Expression classFieldsExtractorAccess = |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 object[member] = properties[member]; | 419 object[member] = properties[member]; |
420 } | 420 } |
421 } | 421 } |
422 object.constructor = constructor; | 422 object.constructor = constructor; |
423 constructor.prototype = object; | 423 constructor.prototype = object; |
424 return object; | 424 return object; |
425 }; | 425 }; |
426 }() | 426 }() |
427 '''); | 427 '''); |
428 if (compiler.hasIncrementalSupport) { | 428 if (compiler.hasIncrementalSupport) { |
429 result = js(r'self.$dart_unsafe_eval.inheritFrom = #', [result]); | 429 result = js( |
| 430 r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]); |
430 } | 431 } |
431 return js(r'var inheritFrom = #', [result]); | 432 return js(r'var inheritFrom = #', [result]); |
432 } | 433 } |
433 | 434 |
434 /// Code that needs to be run before first invocation of | 435 /// Code that needs to be run before first invocation of |
435 /// [finishClassesFunction], but should only be run once. | 436 /// [finishClassesFunction], but should only be run once. |
436 jsAst.Expression get initFinishClasses { | 437 jsAst.Expression get initFinishClasses { |
437 jsAst.Expression allClassesAccess = | 438 jsAst.Expression allClassesAccess = |
438 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); | 439 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
439 jsAst.Expression interceptorsByTagAccess = | 440 jsAst.Expression interceptorsByTagAccess = |
(...skipping 1124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1564 /// following parenthesis looks like a call to the object literal. | 1565 /// following parenthesis looks like a call to the object literal. |
1565 mainBuffer..add( | 1566 mainBuffer..add( |
1566 'self.${deferredInitializers} = self.${deferredInitializers} || ' | 1567 'self.${deferredInitializers} = self.${deferredInitializers} || ' |
1567 'Object.create(null);$n'); | 1568 'Object.create(null);$n'); |
1568 } | 1569 } |
1569 | 1570 |
1570 // Using a named function here produces easier to read stack traces in | 1571 // Using a named function here produces easier to read stack traces in |
1571 // Chrome/V8. | 1572 // Chrome/V8. |
1572 mainBuffer.add('(function(${namer.currentIsolate})$_{\n'); | 1573 mainBuffer.add('(function(${namer.currentIsolate})$_{\n'); |
1573 if (compiler.hasIncrementalSupport) { | 1574 if (compiler.hasIncrementalSupport) { |
1574 mainBuffer.add( | 1575 mainBuffer.add(jsAst.prettyPrint(js.statement( |
1575 'this.\$dart_unsafe_eval =' | 1576 """ |
1576 ' this.\$dart_unsafe_eval || Object.create(null)$N'); | 1577 { |
1577 mainBuffer.add( | 1578 #helper = #helper || Object.create(null); |
1578 'this.\$dart_unsafe_eval.patch = function(a) { eval(a) }$N'); | 1579 #helper.patch = function(a) { eval(a)}; |
1579 String schemaChange = | 1580 #helper.schemaChange = #schemaChange; |
1580 jsAst.prettyPrint(buildSchemaChangeFunction(), compiler).getText(); | 1581 #helper.addMethod = #addMethod; |
1581 String addMethod = | 1582 #helper.extractStubs = function(array, name, isStatic, originalDescriptor) { |
1582 jsAst.prettyPrint(buildIncrementalAddMethod(), compiler).getText(); | 1583 var descriptor = Object.create(null); |
1583 mainBuffer.add( | 1584 this.addStubs(descriptor, array, name, isStatic, originalDescriptor, []); |
1584 'this.\$dart_unsafe_eval.schemaChange$_=$_$schemaChange$N'); | 1585 return descriptor; |
1585 mainBuffer.add( | 1586 }; |
1586 'this.\$dart_unsafe_eval.addMethod$_=$_$addMethod$N'); | 1587 }""", |
| 1588 { 'helper': js('this.#', [namer.incrementalHelperName]), |
| 1589 'schemaChange': buildSchemaChangeFunction(), |
| 1590 'addMethod': buildIncrementalAddMethod() }), compiler)); |
1587 } | 1591 } |
1588 if (isProgramSplit) { | 1592 if (isProgramSplit) { |
1589 /// We collect all the global state of the, so it can be passed to the | 1593 /// We collect all the global state of the, so it can be passed to the |
1590 /// initializer of deferred files. | 1594 /// initializer of deferred files. |
1591 mainBuffer.add('var ${globalsHolder}$_=${_}Object.create(null)$N'); | 1595 mainBuffer.add('var ${globalsHolder}$_=${_}Object.create(null)$N'); |
1592 } | 1596 } |
1593 mainBuffer.add('function dart()$_{$n' | 1597 mainBuffer.add('function dart()$_{$n' |
1594 '${_}${_}this.x$_=${_}0$N' | 1598 '${_}${_}this.x$_=${_}0$N' |
1595 '${_}${_}delete this.x$N' | 1599 '${_}${_}delete this.x$N' |
1596 '}$n'); | 1600 '}$n'); |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1821 /// top-level). [globalFunctionsAccess] is a reference to | 1825 /// top-level). [globalFunctionsAccess] is a reference to |
1822 /// [embeddedNames.GLOBAL_FUNCTIONS]. | 1826 /// [embeddedNames.GLOBAL_FUNCTIONS]. |
1823 jsAst.Fun buildIncrementalAddMethod() { | 1827 jsAst.Fun buildIncrementalAddMethod() { |
1824 return js(r""" | 1828 return js(r""" |
1825 function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { | 1829 function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { |
1826 var arrayOrFunction = originalDescriptor[name]; | 1830 var arrayOrFunction = originalDescriptor[name]; |
1827 var method; | 1831 var method; |
1828 if (arrayOrFunction.constructor === Array) { | 1832 if (arrayOrFunction.constructor === Array) { |
1829 var existing = holder[name]; | 1833 var existing = holder[name]; |
1830 var array = arrayOrFunction; | 1834 var array = arrayOrFunction; |
1831 var descriptor = Object.create(null); | 1835 |
1832 this.addStubs( | 1836 // Each method may have a number of stubs associated. For example, if an |
1833 descriptor, arrayOrFunction, name, isStatic, originalDescriptor, []); | 1837 // instance method supports multiple arguments, a stub for each matching |
| 1838 // selector. There is also a getter stub for tear-off getters. For example, |
| 1839 // an instance method foo([a]) may have the following stubs: foo$0, foo$1, |
| 1840 // and get$foo (here exemplified using unminified names). |
| 1841 // [extractStubs] returns a JavaScript object whose own properties |
| 1842 // corresponds to the stubs. |
| 1843 var descriptor = |
| 1844 this.extractStubs(array, name, isStatic, originalDescriptor); |
1834 method = descriptor[name]; | 1845 method = descriptor[name]; |
| 1846 |
| 1847 // Iterate through the properties of descriptor and copy the stubs to the |
| 1848 // existing holder (for instance methods, a prototype). |
1835 for (var property in descriptor) { | 1849 for (var property in descriptor) { |
1836 if (!Object.prototype.hasOwnProperty.call(descriptor, property)) continue; | 1850 if (!Object.prototype.hasOwnProperty.call(descriptor, property)) continue; |
1837 var stub = descriptor[property]; | 1851 var stub = descriptor[property]; |
1838 var existingStub = holder[property]; | 1852 var existingStub = holder[property]; |
1839 if (stub === method || !existingStub || !stub.$getterStub) { | 1853 if (stub === method || !existingStub || !stub.$getterStub) { |
1840 // Not replacing an existing getter stub. | 1854 // Not replacing an existing getter stub. |
1841 holder[property] = stub; | 1855 holder[property] = stub; |
1842 continue; | 1856 continue; |
1843 } | 1857 } |
1844 if (!stub.$getterStub) { | 1858 if (!stub.$getterStub) { |
1845 var error = new Error('Unexpected stub.'); | 1859 var error = new Error('Unexpected stub.'); |
1846 error.stub = stub; | 1860 error.stub = stub; |
1847 throw error; | 1861 throw error; |
1848 } | 1862 } |
1849 | 1863 |
1850 // Existing getter stubs need special treatment as they may already have | 1864 // Existing getter stubs need special treatment as they may already have |
1851 // been called and produced a closure. | 1865 // been called and produced a closure. |
1852 this.pendingStubs = this.pendingStubs || []; | 1866 this.pendingStubs = this.pendingStubs || []; |
1853 // It isn't safe to invoke the stub yet. | 1867 // It isn't safe to invoke the stub yet. |
1854 this.pendingStubs.push((function(holder, stub, existingStub, existing, | 1868 this.pendingStubs.push((function(holder, stub, existingStub, existing, |
1855 method) { | 1869 method) { |
1856 return function() { | 1870 return function() { |
1857 var receiver = isStatic ? holder : new holder.constructor(); | 1871 var receiver = isStatic ? holder : new holder.constructor(); |
1858 // Invoke the existing stub to obtain the tear-off closure. | 1872 // Invoke the existing stub to obtain the tear-off closure. |
1859 existingStub = existingStub.call(receiver); | 1873 existingStub = existingStub.call(receiver); |
1860 // Invoke the new stub to create a tear-off closure we can use as a | 1874 // Invoke the new stub to create a tear-off closure we can use as a |
1861 // prototype. | 1875 // prototype. |
1862 stub = stub.call(receiver); | 1876 stub = stub.call(receiver); |
1863 | 1877 |
| 1878 // Copy the properties from the new tear-off's prototype to the |
| 1879 // prototype of the existing tear-off. |
1864 var newProto = stub.constructor.prototype; | 1880 var newProto = stub.constructor.prototype; |
1865 var existingProto = existingStub.constructor.prototype; | 1881 var existingProto = existingStub.constructor.prototype; |
1866 for (var stubProperty in newProto) { | 1882 for (var stubProperty in newProto) { |
1867 if (!Object.prototype.hasOwnProperty.call(newProto, stubProperty)) | 1883 if (!Object.prototype.hasOwnProperty.call(newProto, stubProperty)) |
1868 continue; | 1884 continue; |
1869 existingProto[stubProperty] = newProto[stubProperty]; | 1885 existingProto[stubProperty] = newProto[stubProperty]; |
1870 } | 1886 } |
1871 | 1887 |
1872 // Update all the existing stub's references to [existing] to | 1888 // Update all the existing stub's references to [existing] to |
1873 // [method]. Instance tear-offs are call-by-name, so this isn't | 1889 // [method]. Instance tear-offs are call-by-name, so this isn't |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2220 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2236 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
2221 if (element.isInstanceMember) { | 2237 if (element.isInstanceMember) { |
2222 cachedClassBuilders.remove(element.enclosingClass); | 2238 cachedClassBuilders.remove(element.enclosingClass); |
2223 | 2239 |
2224 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2240 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
2225 | 2241 |
2226 } | 2242 } |
2227 } | 2243 } |
2228 } | 2244 } |
2229 } | 2245 } |
OLD | NEW |