| 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 library dart2js.new_js_emitter.model_emitter; | 5 library dart2js.new_js_emitter.model_emitter; |
| 6 | 6 |
| 7 import '../../dart2jslib.dart' show Compiler; | 7 import '../../dart2jslib.dart' show Compiler; |
| 8 import '../../dart_types.dart' show DartType; | 8 import '../../dart_types.dart' show DartType; |
| 9 import '../../elements/elements.dart' show ClassElement; | 9 import '../../elements/elements.dart' show ClassElement; |
| 10 import '../../js/js.dart' as js; | 10 import '../../js/js.dart' as js; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 IS_HUNK_LOADED, | 26 IS_HUNK_LOADED, |
| 27 LEAF_TAGS, | 27 LEAF_TAGS, |
| 28 MANGLED_GLOBAL_NAMES, | 28 MANGLED_GLOBAL_NAMES, |
| 29 METADATA, | 29 METADATA, |
| 30 TYPE_TO_INTERCEPTOR_MAP; | 30 TYPE_TO_INTERCEPTOR_MAP; |
| 31 | 31 |
| 32 import '../js_emitter.dart' show NativeGenerator, buildTearOffCode; | 32 import '../js_emitter.dart' show NativeGenerator, buildTearOffCode; |
| 33 import '../model.dart'; | 33 import '../model.dart'; |
| 34 | 34 |
| 35 | 35 |
| 36 | |
| 37 class ModelEmitter { | 36 class ModelEmitter { |
| 38 final Compiler compiler; | 37 final Compiler compiler; |
| 39 final Namer namer; | 38 final Namer namer; |
| 40 final ConstantEmitter constantEmitter; | 39 final ConstantEmitter constantEmitter; |
| 41 final NativeEmitter nativeEmitter; | 40 final NativeEmitter nativeEmitter; |
| 42 | 41 |
| 43 JavaScriptBackend get backend => compiler.backend; | 42 JavaScriptBackend get backend => compiler.backend; |
| 44 | 43 |
| 45 /// For deferred loading we communicate the initializers via this global var. | 44 /// For deferred loading we communicate the initializers via this global var. |
| 46 static const String deferredInitializersGlobal = | 45 static const String deferredInitializersGlobal = |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 Iterable<Method> setters = cls.fields | 458 Iterable<Method> setters = cls.fields |
| 460 .where((Field field) => field.needsUncheckedSetter) | 459 .where((Field field) => field.needsUncheckedSetter) |
| 461 .map(_generateSetter); | 460 .map(_generateSetter); |
| 462 | 461 |
| 463 return [getters, setters].expand((x) => x); | 462 return [getters, setters].expand((x) => x); |
| 464 } | 463 } |
| 465 | 464 |
| 466 // This string should be referenced wherever JavaScript code makes assumptions | 465 // This string should be referenced wherever JavaScript code makes assumptions |
| 467 // on the mixin format. | 466 // on the mixin format. |
| 468 static final String mixinFormatDescription = | 467 static final String mixinFormatDescription = |
| 469 "Mixins have no constructor, but a reference to their mixin class."; | 468 "Mixins have a reference to their mixin class at the place of the usual" |
| 469 "constructor. If they are instantiated the constructor follows the" |
| 470 "reference."; |
| 470 | 471 |
| 471 js.Expression emitClass(Class cls) { | 472 js.Expression emitClass(Class cls) { |
| 472 List elements = [js.string(cls.superclassName), | 473 List elements = [js.string(cls.superclassName), |
| 473 js.number(cls.superclassHolderIndex)]; | 474 js.number(cls.superclassHolderIndex)]; |
| 474 | 475 |
| 475 if (cls.isMixinApplication) { | 476 if (cls.isMixinApplication) { |
| 476 MixinApplication mixin = cls; | 477 MixinApplication mixin = cls; |
| 477 elements.add(js.string(mixin.mixinClass.name)); | 478 elements.add(js.string(mixin.mixinClass.name)); |
| 478 elements.add(js.number(mixin.mixinClass.holder.index)); | 479 elements.add(js.number(mixin.mixinClass.holder.index)); |
| 480 if (cls.isDirectlyInstantiated) { |
| 481 elements.add(_generateConstructor(cls)); |
| 482 } |
| 479 } else { | 483 } else { |
| 480 elements.add(_generateConstructor(cls)); | 484 elements.add(_generateConstructor(cls)); |
| 481 } | 485 } |
| 482 Iterable<Method> methods = cls.methods; | 486 Iterable<Method> methods = cls.methods; |
| 483 Iterable<Method> isChecks = cls.isChecks; | 487 Iterable<Method> isChecks = cls.isChecks; |
| 484 Iterable<Method> callStubs = cls.callStubs; | 488 Iterable<Method> callStubs = cls.callStubs; |
| 485 Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs; | 489 Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs; |
| 486 Iterable<Method> gettersSetters = _generateGettersSetters(cls); | 490 Iterable<Method> gettersSetters = _generateGettersSetters(cls); |
| 487 Iterable<Method> allMethods = | 491 Iterable<Method> allMethods = |
| 488 [methods, isChecks, callStubs, noSuchMethodStubs, gettersSetters] | 492 [methods, isChecks, callStubs, noSuchMethodStubs, gettersSetters] |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 } | 797 } |
| 794 | 798 |
| 795 #tearOff; | 799 #tearOff; |
| 796 | 800 |
| 797 #parseFunctionDescriptor; | 801 #parseFunctionDescriptor; |
| 798 | 802 |
| 799 function compileConstructor(name, descriptor) { | 803 function compileConstructor(name, descriptor) { |
| 800 descriptor = compile(name, descriptor); | 804 descriptor = compile(name, descriptor); |
| 801 var prototype = determinePrototype(descriptor); | 805 var prototype = determinePrototype(descriptor); |
| 802 var constructor; | 806 var constructor; |
| 807 var functionsIndex; |
| 803 // $mixinFormatDescription. | 808 // $mixinFormatDescription. |
| 804 if (typeof descriptor[2] !== 'function') { | 809 if (typeof descriptor[2] !== 'function') { |
| 805 constructor = compileMixinConstructor(name, prototype, descriptor); | 810 fillPrototypeWithMixedIn(descriptor[2], descriptor[3], prototype); |
| 806 for (var i = 4; i < descriptor.length; i += 2) { | 811 // descriptor[4] contains the constructor if the mixin application is |
| 807 parseFunctionDescriptor(prototype, descriptor[i], descriptor[i + 1]); | 812 // directly instantiated. |
| 813 if (typeof descriptor[4] === 'function') { |
| 814 constructor = descriptor[4]; |
| 815 functionsIndex = 5; |
| 816 } else { |
| 817 constructor = function() {}; |
| 818 functionsIndex = 4; |
| 808 } | 819 } |
| 809 } else { | 820 } else { |
| 810 constructor = descriptor[2]; | 821 constructor = descriptor[2]; |
| 811 for (var i = 3; i < descriptor.length; i += 2) { | 822 functionsIndex = 3; |
| 812 parseFunctionDescriptor(prototype, descriptor[i], descriptor[i + 1]); | |
| 813 } | |
| 814 } | 823 } |
| 824 |
| 825 for (var i = functionsIndex; i < descriptor.length; i += 2) { |
| 826 parseFunctionDescriptor(prototype, descriptor[i], descriptor[i + 1]); |
| 827 } |
| 828 |
| 815 constructor.builtin\$cls = name; // Needed for RTI. | 829 constructor.builtin\$cls = name; // Needed for RTI. |
| 816 constructor.prototype = prototype; | 830 constructor.prototype = prototype; |
| 817 prototype[#operatorIsPrefix + name] = constructor; | 831 prototype[#operatorIsPrefix + name] = constructor; |
| 818 prototype.constructor = constructor; | 832 prototype.constructor = constructor; |
| 819 return constructor; | 833 return constructor; |
| 820 } | 834 } |
| 821 | 835 |
| 822 function compileMixinConstructor(name, prototype, descriptor) { | 836 function fillPrototypeWithMixedIn(mixinName, mixinHolderIndex, prototype) { |
| 823 // $mixinFormatDescription. | |
| 824 var mixinName = descriptor[2]; | |
| 825 var mixinHolderIndex = descriptor[3]; | |
| 826 var mixin = holders[mixinHolderIndex][mixinName].ensureResolved(); | 837 var mixin = holders[mixinHolderIndex][mixinName].ensureResolved(); |
| 827 var mixinPrototype = mixin.prototype; | 838 var mixinPrototype = mixin.prototype; |
| 828 | 839 |
| 829 // Fill the prototype with the mixin's properties. | 840 // Fill the prototype with the mixin's properties. |
| 830 var mixinProperties = Object.keys(mixinPrototype); | 841 var mixinProperties = Object.keys(mixinPrototype); |
| 831 for (var i = 0; i < mixinProperties.length; i++) { | 842 for (var i = 0; i < mixinProperties.length; i++) { |
| 832 var p = mixinProperties[i]; | 843 var p = mixinProperties[i]; |
| 833 prototype[p] = mixinPrototype[p]; | 844 prototype[p] = mixinPrototype[p]; |
| 834 } | 845 } |
| 835 // Since this is a mixin application the constructor will actually never | |
| 836 // be invoked. We only use its prototype for the application's subclasses. | |
| 837 var constructor = function() {}; | |
| 838 return constructor; | |
| 839 } | 846 } |
| 840 | 847 |
| 841 function determinePrototype(descriptor) { | 848 function determinePrototype(descriptor) { |
| 842 var superclassName = descriptor[0]; | 849 var superclassName = descriptor[0]; |
| 843 if (!superclassName) return { }; | 850 if (!superclassName) return { }; |
| 844 | 851 |
| 845 // Look up the superclass constructor function in the right holder. | 852 // Look up the superclass constructor function in the right holder. |
| 846 var holderIndex = descriptor[1]; | 853 var holderIndex = descriptor[1]; |
| 847 var superclass = holders[holderIndex][superclassName].ensureResolved(); | 854 var superclass = holders[holderIndex][superclassName].ensureResolved(); |
| 848 | 855 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 | 913 |
| 907 var end = Date.now(); | 914 var end = Date.now(); |
| 908 print('Setup: ' + (end - start) + ' ms.'); | 915 print('Setup: ' + (end - start) + ' ms.'); |
| 909 | 916 |
| 910 #main(); // Start main. | 917 #main(); // Start main. |
| 911 | 918 |
| 912 }(Date.now(), #code) | 919 }(Date.now(), #code) |
| 913 }"""; | 920 }"""; |
| 914 | 921 |
| 915 } | 922 } |
| OLD | NEW |