Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(348)

Side by Side Diff: pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart

Issue 880773003: dart2js: support native classes in the new emitter. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/new_emitter/emitter.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 '../../js/js.dart' as js; 9 import '../../js/js.dart' as js;
10 import '../../js_backend/js_backend.dart' show 10 import '../../js_backend/js_backend.dart' show
11 JavaScriptBackend, 11 JavaScriptBackend,
12 Namer, 12 Namer,
13 ConstantEmitter; 13 ConstantEmitter;
14 14
15 import '../js_emitter.dart' show
16 NativeEmitter;
17
15 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show 18 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show
16 DEFERRED_LIBRARY_URIS, 19 DEFERRED_LIBRARY_URIS,
17 DEFERRED_LIBRARY_HASHES, 20 DEFERRED_LIBRARY_HASHES,
18 GET_TYPE_FROM_NAME, 21 GET_TYPE_FROM_NAME,
19 INITIALIZE_LOADED_HUNK, 22 INITIALIZE_LOADED_HUNK,
23 INTERCEPTORS_BY_TAG,
20 IS_HUNK_INITIALIZED, 24 IS_HUNK_INITIALIZED,
21 IS_HUNK_LOADED, 25 IS_HUNK_LOADED,
26 LEAF_TAGS,
22 MANGLED_GLOBAL_NAMES, 27 MANGLED_GLOBAL_NAMES,
23 METADATA, 28 METADATA,
24 TYPE_TO_INTERCEPTOR_MAP; 29 TYPE_TO_INTERCEPTOR_MAP;
25 30
26 import '../js_emitter.dart' show NativeGenerator, buildTearOffCode; 31 import '../js_emitter.dart' show NativeGenerator, buildTearOffCode;
27 import '../model.dart'; 32 import '../model.dart';
28 33
29 34
30 class ModelEmitter { 35 class ModelEmitter {
31 final Compiler compiler; 36 final Compiler compiler;
32 final Namer namer; 37 final Namer namer;
33 final ConstantEmitter constantEmitter; 38 final ConstantEmitter constantEmitter;
39 final NativeEmitter nativeEmitter;
34 40
35 JavaScriptBackend get backend => compiler.backend; 41 JavaScriptBackend get backend => compiler.backend;
36 42
37 /// For deferred loading we communicate the initializers via this global var. 43 /// For deferred loading we communicate the initializers via this global var.
38 static const String deferredInitializersGlobal = 44 static const String deferredInitializersGlobal =
39 r"$__dart_deferred_initializers__"; 45 r"$__dart_deferred_initializers__";
40 46
41 static const String deferredExtension = "part.js"; 47 static const String deferredExtension = "part.js";
42 48
43 ModelEmitter(Compiler compiler, Namer namer) 49 ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter)
44 : this.compiler = compiler, 50 : this.compiler = compiler,
45 this.namer = namer, 51 this.namer = namer,
46 constantEmitter = 52 constantEmitter =
47 new ConstantEmitter(compiler, namer, makeConstantListTemplate); 53 new ConstantEmitter(compiler, namer, makeConstantListTemplate);
48 54
49 js.Expression generateEmbeddedGlobalAccess(String global) { 55 js.Expression generateEmbeddedGlobalAccess(String global) {
50 // TODO(floitsch): We should not use "init" for globals. 56 // TODO(floitsch): We should not use "init" for globals.
51 return js.js("init.$global"); 57 return js.js("init.$global");
52 } 58 }
53 59
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; 91 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
86 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n'; 92 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n';
87 } 93 }
88 94
89 js.Statement emitMainFragment(Program program) { 95 js.Statement emitMainFragment(Program program) {
90 MainFragment fragment = program.fragments.first; 96 MainFragment fragment = program.fragments.first;
91 List<js.Expression> elements = fragment.libraries.map(emitLibrary).toList(); 97 List<js.Expression> elements = fragment.libraries.map(emitLibrary).toList();
92 elements.add( 98 elements.add(
93 emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields)); 99 emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields));
94 100
95 js.Statement nativeBoilerplate; 101 js.Expression code = new js.ArrayInitializer(elements);
102
103 Map<String, dynamic> holes =
104 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
105 'holders': emitHolders(fragment.holders),
106 'tearOff': buildTearOffCode(backend),
107 'parseFunctionDescriptor':
108 js.js.statement(parseFunctionDescriptorBoilerplate),
109 'cyclicThrow':
110 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()),
111 'outputContainsConstantList': program.outputContainsConstantList,
112 'embeddedGlobals': emitEmbeddedGlobals(program),
113 'constants': emitConstants(fragment.constants),
114 'staticNonFinals':
115 emitStaticNonFinalFields(fragment.staticNonFinalFields),
116 'operatorIsPrefix': js.string(namer.operatorIsPrefix),
117 'eagerClasses': emitEagerClassInitializations(fragment.libraries),
118 'main': fragment.main,
119 'code': code};
120
121 holes.addAll(nativeHoles(program));
122
123 return js.js.statement(boilerplate, holes);
124 }
125
126 Map<String, dynamic> nativeHoles(Program program) {
127 Map<String, dynamic> nativeHoles = <String, dynamic>{};
128
129 js.Statement nativeIsolateAffinityTagInitialization;
96 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { 130 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) {
97 nativeBoilerplate = 131 nativeIsolateAffinityTagInitialization =
98 NativeGenerator.generateIsolateAffinityTagInitialization( 132 NativeGenerator.generateIsolateAffinityTagInitialization(
99 backend, 133 backend,
100 generateEmbeddedGlobalAccess, 134 generateEmbeddedGlobalAccess,
101 // TODO(floitsch): convertToFastObject. 135 // TODO(floitsch): convertToFastObject.
102 js.js("(function(x) { return x; })", [])); 136 js.js("(function(x) { return x; })", []));
103 } else { 137 } else {
104 nativeBoilerplate = js.js.statement(";"); 138 nativeIsolateAffinityTagInitialization = js.js.statement(";");
105 } 139 }
140 nativeHoles['nativeIsolateAffinityTagInitialization'] =
141 nativeIsolateAffinityTagInitialization;
106 142
107 js.Expression code = new js.ArrayInitializer(elements);
108 143
109 return js.js.statement( 144 js.Expression nativeInfoAccess = js.js('nativeInfo', []);
110 boilerplate, 145 js.Expression constructorAccess = js.js('constructor', []);
111 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), 146 Function subclassReadGenerator = (js.Expression subclass) {
112 'holders': emitHolders(fragment.holders), 147 return js.js('holdersMap[#][#].ensureResolved()', [subclass, subclass]);
113 'tearOff': buildTearOffCode(backend), 148 };
114 'parseFunctionDescriptor': 149 js.Expression interceptorsByTagAccess =
115 js.js.statement(parseFunctionDescriptorBoilerplate), 150 generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG);
116 'cyclicThrow': 151 js.Expression leafTagsAccess =
117 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), 152 generateEmbeddedGlobalAccess(LEAF_TAGS);
118 'outputContainsConstantList': program.outputContainsConstantList, 153 js.Statement nativeInfoHandler = nativeEmitter.buildNativeInfoHandler(
119 'embeddedGlobals': emitEmbeddedGlobals(program), 154 nativeInfoAccess,
120 'constants': emitConstants(fragment.constants), 155 constructorAccess,
121 'staticNonFinals': 156 subclassReadGenerator,
122 emitStaticNonFinalFields(fragment.staticNonFinalFields), 157 interceptorsByTagAccess,
123 'nativeBoilerplate': nativeBoilerplate, 158 leafTagsAccess);
124 'operatorIsPrefix': js.string(namer.operatorIsPrefix), 159
125 'eagerClasses': emitEagerClassInitializations(fragment.libraries), 160 nativeHoles['hasNativeClasses'] = program.outputContainsNativeClasses;
126 'main': fragment.main, 161 nativeHoles['hasNoNativeClasses'] = !program.outputContainsNativeClasses;
127 'code': code}); 162 nativeHoles['nativeInfoHandler'] = nativeInfoHandler;
163
164 return nativeHoles;
128 } 165 }
129 166
130 js.Block emitHolders(List<Holder> holders) { 167 js.Block emitHolders(List<Holder> holders) {
131 // The top-level variables for holders must *not* be renamed by the 168 // The top-level variables for holders must *not* be renamed by the
132 // JavaScript pretty printer because a lot of code already uses the 169 // JavaScript pretty printer because a lot of code already uses the
133 // non-renamed names. The generated code looks like this: 170 // non-renamed names. The generated code looks like this:
134 // 171 //
135 // var H = {}, ..., G = {}; 172 // var H = {}, ..., G = {};
136 // var holders = [ H, ..., G ]; 173 // var holders = [ H, ..., G ];
137 // 174 //
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 program.typeToInterceptorMap)); 209 program.typeToInterceptorMap));
173 } 210 }
174 211
175 globals.add(new js.Property(js.string(MANGLED_GLOBAL_NAMES), 212 globals.add(new js.Property(js.string(MANGLED_GLOBAL_NAMES),
176 js.js('Object.create(null)', []))); 213 js.js('Object.create(null)', [])));
177 214
178 globals.add(emitGetTypeFromName()); 215 globals.add(emitGetTypeFromName());
179 216
180 globals.add(emitMetadata(program)); 217 globals.add(emitMetadata(program));
181 218
219 if (program.outputContainsNativeClasses) {
220 globals.add(new js.Property(js.string(INTERCEPTORS_BY_TAG),
221 js.js('Object.create(null)', [])));
222 globals.add(new js.Property(js.string(LEAF_TAGS),
223 js.js('Object.create(null)', [])));
224 }
225
182 js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals); 226 js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals);
183 227
184 List<js.Statement> statements = 228 List<js.Statement> statements =
185 [new js.ExpressionStatement( 229 [new js.ExpressionStatement(
186 new js.VariableDeclarationList( 230 new js.VariableDeclarationList(
187 [new js.VariableInitialization( 231 [new js.VariableInitialization(
188 new js.VariableDeclaration("init", allowRename: false), 232 new js.VariableDeclaration("init", allowRename: false),
189 globalsObject)]))]; 233 globalsObject)]))];
190 return new js.Block(statements); 234 return new js.Block(statements);
191 } 235 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 } 347 }
304 348
305 List<js.Statement> instantiations = 349 List<js.Statement> instantiations =
306 libraries.expand((Library library) => library.classes) 350 libraries.expand((Library library) => library.classes)
307 .where((Class cls) => cls.isEager) 351 .where((Class cls) => cls.isEager)
308 .map(createInstantiation) 352 .map(createInstantiation)
309 .toList(growable: false); 353 .toList(growable: false);
310 return new js.Block(instantiations); 354 return new js.Block(instantiations);
311 } 355 }
312 356
357 // This string should be referenced wherever JavaScript code makes assumptions
358 // on the mixin format.
359 static final String nativeInfoDescription =
360 "A class is encoded as follows:"
361 " [name, class-code, holder-index], or "
362 " [name, class-code, native-info, holder-index].";
363
313 js.Expression emitLibrary(Library library) { 364 js.Expression emitLibrary(Library library) {
314 Iterable staticDescriptors = library.statics.expand(emitStaticMethod); 365 Iterable staticDescriptors = library.statics.expand(emitStaticMethod);
315 Iterable classDescriptors = library.classes.expand((Class e) => 366
316 [ js.string(e.name), js.number(e.holder.index), emitClass(e) ]); 367 Iterable classDescriptors = library.classes.expand((Class cls) {
368 js.LiteralString name = js.string(cls.name);
369 js.LiteralNumber holderIndex = js.number(cls.holder.index);
370 js.Expression emittedClass = emitClass(cls);
371 if (cls.nativeInfo == null) {
372 return [name, emittedClass, holderIndex];
373 } else {
374 return [name, emittedClass, js.string(cls.nativeInfo), holderIndex];
375 }
376 });
317 377
318 js.Expression staticArray = 378 js.Expression staticArray =
319 new js.ArrayInitializer(staticDescriptors.toList(growable: false)); 379 new js.ArrayInitializer(staticDescriptors.toList(growable: false));
320 js.Expression classArray = 380 js.Expression classArray =
321 new js.ArrayInitializer(classDescriptors.toList(growable: false)); 381 new js.ArrayInitializer(classDescriptors.toList(growable: false));
322 382
323 return new js.ArrayInitializer([staticArray, classArray]); 383 return new js.ArrayInitializer([staticArray, classArray]);
324 } 384 }
325 385
326 js.Expression _generateConstructor(Class cls) { 386 js.Expression _generateConstructor(Class cls) {
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 } 619 }
560 620
561 static final String boilerplate = """ 621 static final String boilerplate = """
562 { 622 {
563 // Declare deferred-initializer global. 623 // Declare deferred-initializer global.
564 #deferredInitializer; 624 #deferredInitializer;
565 625
566 !function(start, program) { 626 !function(start, program) {
567 // Initialize holder objects. 627 // Initialize holder objects.
568 #holders; 628 #holders;
629 var nativeInfos = Object.create(null);
569 630
570 // Counter to generate unique names for tear offs. 631 // Counter to generate unique names for tear offs.
571 var functionCounter = 0; 632 var functionCounter = 0;
572 633
573 function setupProgram() { 634 function setupProgram() {
574 for (var i = 0; i < program.length - 1; i++) { 635 for (var i = 0; i < program.length - 1; i++) {
575 setupLibrary(program[i]); 636 setupLibrary(program[i]);
576 } 637 }
577 setupLazyStatics(program[i]); 638 setupLazyStatics(program[i]);
578 } 639 }
579 640
580 function setupLibrary(library) { 641 function setupLibrary(library) {
581 var statics = library[0]; 642 var statics = library[0];
582 for (var i = 0; i < statics.length; i += 3) { 643 for (var i = 0; i < statics.length; i += 3) {
583 var holderIndex = statics[i + 1]; 644 var holderIndex = statics[i + 1];
584 setupStatic(statics[i], holders[holderIndex], statics[i + 2]); 645 setupStatic(statics[i], holders[holderIndex], statics[i + 2]);
585 } 646 }
586 647
587 var classes = library[1]; 648 var classes = library[1];
588 for (var i = 0; i < classes.length; i += 3) { 649 for (var i = 0; i < classes.length; i += 3) {
589 var holderIndex = classes[i + 1]; 650 var name = classes[i];
590 holdersMap[classes[i]] = holders[holderIndex]; 651 var cls = classes[i + 1];
591 setupClass(classes[i], holders[holderIndex], classes[i + 2]); 652
653 if (#hasNativeClasses) {
654 // $nativeInfoDescription.
655 var indexOrNativeInfo = classes[i + 2];
656 if (typeof indexOrNativeInfo == "number") {
657 var holderIndex = classes[i + 2];
658 } else {
659 nativeInfos[name] = indexOrNativeInfo;
660 holderIndex = classes[i + 3];
661 i++;
662 }
663 }
664
665 if (#hasNoNativeClasses) {
666 var holderIndex = classes[i + 2];
667 }
668
669 holdersMap[name] = holders[holderIndex];
670 setupClass(name, holders[holderIndex], cls);
592 } 671 }
593 } 672 }
594 673
595 function setupLazyStatics(statics) { 674 function setupLazyStatics(statics) {
596 for (var i = 0; i < statics.length; i += 4) { 675 for (var i = 0; i < statics.length; i += 4) {
597 var name = statics[i]; 676 var name = statics[i];
598 var getterName = statics[i + 1]; 677 var getterName = statics[i + 1];
599 var holderIndex = statics[i + 2]; 678 var holderIndex = statics[i + 2];
600 var initializer = statics[i + 3]; 679 var initializer = statics[i + 3];
601 setupLazyStatic(name, getterName, holders[holderIndex], initializer); 680 setupLazyStatic(name, getterName, holders[holderIndex], initializer);
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 function makeConstList(list) { 844 function makeConstList(list) {
766 // By assigning a function to the properties they become part of the 845 // By assigning a function to the properties they become part of the
767 // hidden class. The actual values of the fields don't matter, since we 846 // hidden class. The actual values of the fields don't matter, since we
768 // only check if they exist. 847 // only check if they exist.
769 list.immutable\$list = Array; 848 list.immutable\$list = Array;
770 list.fixed\$length = Array; 849 list.fixed\$length = Array;
771 return list; 850 return list;
772 } 851 }
773 } 852 }
774 853
854 if (#hasNativeClasses) {
855 function handleNativeClassInfos() {
856 for (var nativeClass in nativeInfos) {
857 var constructor = holdersMap[nativeClass][nativeClass].ensureResolved();
858 var nativeInfo = nativeInfos[nativeClass];
859 #nativeInfoHandler;
860 }
861 }
862 }
863
775 setupProgram(); 864 setupProgram();
776 865
777 // Initialize constants. 866 // Initialize constants.
778 #constants; 867 #constants;
779 868
780 // Initialize globals. 869 // Initialize globals.
781 #embeddedGlobals; 870 #embeddedGlobals;
782 871
872 // TODO(floitsch): this order means that native classes may not be
873 // referenced from constants. I'm mostly afraid of things like using them as
874 // generic arguments (which should be fine, but maybe there are other
875 // similar things).
876 // Initialize natives.
877 if (#hasNativeClasses) handleNativeClassInfos();
878
783 // Initialize static non-final fields. 879 // Initialize static non-final fields.
784 #staticNonFinals; 880 #staticNonFinals;
785 881
786 // Add native boilerplate code. 882 // Add native boilerplate code.
787 #nativeBoilerplate; 883 #nativeIsolateAffinityTagInitialization;
788 884
789 // Initialize eager classes. 885 // Initialize eager classes.
790 #eagerClasses; 886 #eagerClasses;
791 887
792 var end = Date.now(); 888 var end = Date.now();
793 print('Setup: ' + (end - start) + ' ms.'); 889 print('Setup: ' + (end - start) + ' ms.');
794 890
795 #main(); // Start main. 891 #main(); // Start main.
796 892
797 }(Date.now(), #code) 893 }(Date.now(), #code)
798 }"""; 894 }""";
799 895
800 } 896 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/new_emitter/emitter.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698