OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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.startup_emitter.model_emitter; | 5 part of dart2js.js_emitter.startup_emitter.model_emitter; |
6 | 6 |
7 /// The name of the property that stores the tear-off getter on a static | 7 /// The name of the property that stores the tear-off getter on a static |
8 /// function. | 8 /// function. |
9 /// | 9 /// |
10 /// This property is only used when isolates are used. | 10 /// This property is only used when isolates are used. |
(...skipping 825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 } | 836 } |
837 | 837 |
838 return properties; | 838 return properties; |
839 } | 839 } |
840 | 840 |
841 /// Emits the inheritance block of the fragment. | 841 /// Emits the inheritance block of the fragment. |
842 /// | 842 /// |
843 /// In this section prototype chains are updated and mixin functions are | 843 /// In this section prototype chains are updated and mixin functions are |
844 /// copied. | 844 /// copied. |
845 js.Statement emitInheritance(Fragment fragment) { | 845 js.Statement emitInheritance(Fragment fragment) { |
846 List<js.Expression> inheritCalls = <js.Expression>[]; | 846 List<js.Statement> inheritCalls = <js.Statement>[]; |
847 List<js.Expression> mixinCalls = <js.Expression>[]; | 847 List<js.Statement> mixinCalls = <js.Statement>[]; |
848 | 848 |
849 Set<Class> classesInFragment = new Set<Class>(); | 849 Set<Class> classesInFragment = new Set<Class>(); |
850 for (Library library in fragment.libraries) { | 850 for (Library library in fragment.libraries) { |
851 classesInFragment.addAll(library.classes); | 851 classesInFragment.addAll(library.classes); |
852 } | 852 } |
853 | 853 |
854 Set<Class> emittedClasses = new Set<Class>(); | 854 Map<Class, List<Class>> subclasses = <Class, List<Class>>{}; |
| 855 Set<Class> seen = new Set<Class>(); |
855 | 856 |
856 void emitInheritanceForClass(cls) { | 857 void collect(cls) { |
857 if (cls == null || emittedClasses.contains(cls)) return; | 858 if (cls == null || seen.contains(cls)) return; |
858 | 859 |
859 Class superclass = cls.superclass; | 860 Class superclass = cls.superclass; |
860 if (classesInFragment.contains(superclass)) { | 861 if (classesInFragment.contains(superclass)) { |
861 emitInheritanceForClass(superclass); | 862 collect(superclass); |
862 } | 863 } |
863 | 864 |
864 js.Expression superclassReference = (superclass == null) | 865 subclasses.putIfAbsent(superclass, () => <Class>[]).add(cls); |
865 ? new js.LiteralNull() | |
866 : classReference(superclass); | |
867 | 866 |
868 inheritCalls.add( | 867 seen.add(cls); |
869 js.js('inherit(#, #)', [classReference(cls), superclassReference])); | |
870 | |
871 emittedClasses.add(cls); | |
872 } | 868 } |
873 | 869 |
874 for (Library library in fragment.libraries) { | 870 for (Library library in fragment.libraries) { |
875 for (Class cls in library.classes) { | 871 for (Class cls in library.classes) { |
876 emitInheritanceForClass(cls); | 872 collect(cls); |
877 | 873 |
878 if (cls.isMixinApplication) { | 874 if (cls.isMixinApplication) { |
879 MixinApplication mixin = cls; | 875 MixinApplication mixin = cls; |
880 mixinCalls.add(js.js('mixin(#, #)', | 876 mixinCalls.add(js.js.statement('mixin(#, #)', |
881 [classReference(cls), classReference(mixin.mixinClass)])); | 877 [classReference(cls), classReference(mixin.mixinClass)])); |
882 } | 878 } |
883 } | 879 } |
884 } | 880 } |
885 | 881 |
| 882 js.Expression temp = null; |
| 883 for (Class superclass in subclasses.keys) { |
| 884 List<Class> list = subclasses[superclass]; |
| 885 js.Expression superclassReference = (superclass == null) |
| 886 ? new js.LiteralNull() |
| 887 : classReference(superclass); |
| 888 if (list.length == 1) { |
| 889 inheritCalls.add(js.js.statement('inherit(#, #)', |
| 890 [classReference(list.single), superclassReference])); |
| 891 } else { |
| 892 // Hold common superclass in temporary for sequence of calls. |
| 893 if (temp == null) { |
| 894 String tempName = '_'; |
| 895 temp = new js.VariableUse(tempName); |
| 896 var declaration = new js.VariableDeclaration(tempName); |
| 897 inheritCalls.add( |
| 898 js.js.statement('var # = #', [declaration, superclassReference])); |
| 899 } else { |
| 900 inheritCalls |
| 901 .add(js.js.statement('# = #', [temp, superclassReference])); |
| 902 } |
| 903 for (Class cls in list) { |
| 904 inheritCalls.add( |
| 905 js.js.statement('inherit(#, #)', [classReference(cls), temp])); |
| 906 } |
| 907 } |
| 908 } |
| 909 |
886 return wrapPhase( | 910 return wrapPhase( |
887 'inheritance', | 911 'inheritance', js.js.statement('{#; #;}', [inheritCalls, mixinCalls])); |
888 js.js.statement('{#; #;}', [ | |
889 inheritCalls.map((e) => new js.ExpressionStatement(e)), | |
890 mixinCalls.map((e) => new js.ExpressionStatement(e)) | |
891 ])); | |
892 } | 912 } |
893 | 913 |
894 /// Emits the setup of method aliases. | 914 /// Emits the setup of method aliases. |
895 /// | 915 /// |
896 /// This step consists of simply copying JavaScript functions to their | 916 /// This step consists of simply copying JavaScript functions to their |
897 /// aliased names so they point to the same function. | 917 /// aliased names so they point to the same function. |
898 js.Statement emitInstanceMethodAliases(Fragment fragment) { | 918 js.Statement emitInstanceMethodAliases(Fragment fragment) { |
899 List<js.Statement> assignments = <js.Statement>[]; | 919 List<js.Statement> assignments = <js.Statement>[]; |
900 | 920 |
901 for (Library library in fragment.libraries) { | 921 for (Library library in fragment.libraries) { |
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1413 } | 1433 } |
1414 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);", | 1434 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);", |
1415 js.objectLiteral(interceptorsByTag))); | 1435 js.objectLiteral(interceptorsByTag))); |
1416 statements.add( | 1436 statements.add( |
1417 js.js.statement("setOrUpdateLeafTags(#);", js.objectLiteral(leafTags))); | 1437 js.js.statement("setOrUpdateLeafTags(#);", js.objectLiteral(leafTags))); |
1418 statements.addAll(subclassAssignments); | 1438 statements.addAll(subclassAssignments); |
1419 | 1439 |
1420 return wrapPhase('nativeSupport', new js.Block(statements)); | 1440 return wrapPhase('nativeSupport', new js.Block(statements)); |
1421 } | 1441 } |
1422 } | 1442 } |
OLD | NEW |