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

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: Rename blob to info. 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 '../../js/js.dart' as js; 8 import '../../js/js.dart' as js;
9 import '../../js_backend/js_backend.dart' show 9 import '../../js_backend/js_backend.dart' show
10 JavaScriptBackend, 10 JavaScriptBackend,
11 Namer, 11 Namer,
12 ConstantEmitter; 12 ConstantEmitter;
13 13
14 import '../js_emitter.dart' show
15 NativeEmitter;
16
14 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show 17 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show
15 DEFERRED_LIBRARY_URIS, 18 DEFERRED_LIBRARY_URIS,
16 DEFERRED_LIBRARY_HASHES, 19 DEFERRED_LIBRARY_HASHES,
17 GET_TYPE_FROM_NAME, 20 GET_TYPE_FROM_NAME,
18 INITIALIZE_LOADED_HUNK, 21 INITIALIZE_LOADED_HUNK,
22 INTERCEPTORS_BY_TAG,
19 IS_HUNK_INITIALIZED, 23 IS_HUNK_INITIALIZED,
20 IS_HUNK_LOADED, 24 IS_HUNK_LOADED,
25 LEAF_TAGS,
21 TYPE_TO_INTERCEPTOR_MAP; 26 TYPE_TO_INTERCEPTOR_MAP;
22 27
23 import '../js_emitter.dart' show NativeGenerator; 28 import '../js_emitter.dart' show NativeGenerator;
24 import '../model.dart'; 29 import '../model.dart';
25 30
26 class ModelEmitter { 31 class ModelEmitter {
27 final Compiler compiler; 32 final Compiler compiler;
28 final Namer namer; 33 final Namer namer;
29 final ConstantEmitter constantEmitter; 34 final ConstantEmitter constantEmitter;
35 final NativeEmitter nativeEmitter;
30 36
31 JavaScriptBackend get backend => compiler.backend; 37 JavaScriptBackend get backend => compiler.backend;
32 38
33 /// For deferred loading we communicate the initializers via this global var. 39 /// For deferred loading we communicate the initializers via this global var.
34 static const String deferredInitializersGlobal = 40 static const String deferredInitializersGlobal =
35 r"$__dart_deferred_initializers__"; 41 r"$__dart_deferred_initializers__";
36 42
37 static const String deferredExtension = "part.js"; 43 static const String deferredExtension = "part.js";
38 44
39 ModelEmitter(Compiler compiler, Namer namer) 45 ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter)
40 : this.compiler = compiler, 46 : this.compiler = compiler,
41 this.namer = namer, 47 this.namer = namer,
42 constantEmitter = 48 constantEmitter =
43 new ConstantEmitter(compiler, namer, makeConstantListTemplate); 49 new ConstantEmitter(compiler, namer, makeConstantListTemplate);
44 50
45 js.Expression generateEmbeddedGlobalAccess(String global) { 51 js.Expression generateEmbeddedGlobalAccess(String global) {
46 // TODO(floitsch): We should not use "init" for globals. 52 // TODO(floitsch): We should not use "init" for globals.
47 return js.js("init.$global"); 53 return js.js("init.$global");
48 } 54 }
49 55
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; 87 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
82 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n'; 88 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n';
83 } 89 }
84 90
85 js.Statement emitMainFragment(Program program) { 91 js.Statement emitMainFragment(Program program) {
86 MainFragment fragment = program.fragments.first; 92 MainFragment fragment = program.fragments.first;
87 List<js.Expression> elements = fragment.libraries.map(emitLibrary).toList(); 93 List<js.Expression> elements = fragment.libraries.map(emitLibrary).toList();
88 elements.add( 94 elements.add(
89 emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields)); 95 emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields));
90 96
91 js.Statement nativeBoilerplate; 97 js.Expression code = new js.ArrayInitializer(elements);
98
99 Map<String, dynamic> holes =
100 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
101 'holders': emitHolders(fragment.holders),
102 'cyclicThrow':
103 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()),
104 'outputContainsConstantList': program.outputContainsConstantList,
105 'embeddedGlobals': emitEmbeddedGlobals(program),
106 'constants': emitConstants(fragment.constants),
107 'staticNonFinals':
108 emitStaticNonFinalFields(fragment.staticNonFinalFields),
109 'eagerClasses': emitEagerClassInitializations(fragment.libraries),
110 'main': fragment.main,
111 'code': code};
112
113 holes.addAll(nativeHoles(program));
114
115 return js.js.statement(boilerplate, holes);
116 }
117
118 Map<String, dynamic> nativeHoles(Program program) {
119 Map<String, dynamic> nativeHoles = <String, dynamic>{};
120
121 js.Statement nativeIsolateAffinityTagInitialization;
92 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { 122 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) {
93 nativeBoilerplate = 123 nativeIsolateAffinityTagInitialization =
94 NativeGenerator.generateIsolateAffinityTagInitialization( 124 NativeGenerator.generateIsolateAffinityTagInitialization(
95 backend, 125 backend,
96 generateEmbeddedGlobalAccess, 126 generateEmbeddedGlobalAccess,
97 // TODO(floitsch): convertToFastObject. 127 // TODO(floitsch): convertToFastObject.
98 js.js("(function(x) { return x; })", [])); 128 js.js("(function(x) { return x; })", []));
99 } else { 129 } else {
100 nativeBoilerplate = js.js.statement(";"); 130 nativeIsolateAffinityTagInitialization = js.js.statement(";");
101 } 131 }
132 nativeHoles['nativeIsolateAffinityTagInitialization'] =
133 nativeIsolateAffinityTagInitialization;
102 134
103 js.Expression code = new js.ArrayInitializer(elements);
104 135
105 return js.js.statement( 136 js.Expression nativeInfoAccess = js.js('nativeInfo', []);
106 boilerplate, 137 js.Expression constructorAccess = js.js('constructor', []);
107 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), 138 Function subclassReadGenerator = (js.Expression subclass) {
108 'holders': emitHolders(fragment.holders), 139 return js.js('holdersMap[#][#].ensureResolved()', [subclass, subclass]);
109 'cyclicThrow': 140 };
110 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), 141 js.Expression interceptorsByTagAccess =
111 'outputContainsConstantList': program.outputContainsConstantList, 142 generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG);
112 'embeddedGlobals': emitEmbeddedGlobals(program), 143 js.Expression leafTagsAccess =
113 'constants': emitConstants(fragment.constants), 144 generateEmbeddedGlobalAccess(LEAF_TAGS);
114 'staticNonFinals': emitStaticNonFinalFields(fragment.staticNonFinalFiel ds), 145 js.Statement nativeInfoHandler = nativeEmitter.buildNativeInfoHandler(
115 'nativeBoilerplate': nativeBoilerplate, 146 nativeInfoAccess,
116 'eagerClasses': emitEagerClassInitializations(fragment.libraries), 147 constructorAccess,
117 'main': fragment.main, 148 subclassReadGenerator,
118 'code': code}); 149 interceptorsByTagAccess,
150 leafTagsAccess);
151
152 nativeHoles['hasNativeClasses'] = program.outputContainsNativeClasses;
153 nativeHoles['hasNotNativeClasses'] = !program.outputContainsNativeClasses;
154 nativeHoles['nativeInfoHandler'] = nativeInfoHandler;
155
156 return nativeHoles;
119 } 157 }
120 158
121 js.Block emitHolders(List<Holder> holders) { 159 js.Block emitHolders(List<Holder> holders) {
122 // The top-level variables for holders must *not* be renamed by the 160 // The top-level variables for holders must *not* be renamed by the
123 // JavaScript pretty printer because a lot of code already uses the 161 // JavaScript pretty printer because a lot of code already uses the
124 // non-renamed names. The generated code looks like this: 162 // non-renamed names. The generated code looks like this:
125 // 163 //
126 // var H = {}, ..., G = {}; 164 // var H = {}, ..., G = {};
127 // var holders = [ H, ..., G ]; 165 // var holders = [ H, ..., G ];
128 // 166 //
(...skipping 29 matching lines...) Expand all
158 globals.add(emitInitializeLoadedHunk()); 196 globals.add(emitInitializeLoadedHunk());
159 } 197 }
160 198
161 globals.add(emitGetTypeFromName()); 199 globals.add(emitGetTypeFromName());
162 200
163 if (program.typeToInterceptorMap != null) { 201 if (program.typeToInterceptorMap != null) {
164 globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP), 202 globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP),
165 program.typeToInterceptorMap)); 203 program.typeToInterceptorMap));
166 } 204 }
167 205
206 if (program.outputContainsNativeClasses) {
207 globals.add(new js.Property(js.string(INTERCEPTORS_BY_TAG),
208 js.js('Object.create(null)', [])));
209 globals.add(new js.Property(js.string(LEAF_TAGS),
210 js.js('Object.create(null)', [])));
211 }
212
168 js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals); 213 js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals);
169 214
170 List<js.Statement> statements = 215 List<js.Statement> statements =
171 [new js.ExpressionStatement( 216 [new js.ExpressionStatement(
172 new js.VariableDeclarationList( 217 new js.VariableDeclarationList(
173 [new js.VariableInitialization( 218 [new js.VariableInitialization(
174 new js.VariableDeclaration("init", allowRename: false), 219 new js.VariableDeclaration("init", allowRename: false),
175 globalsObject)]))]; 220 globalsObject)]))];
176 return new js.Block(statements); 221 return new js.Block(statements);
177 } 222 }
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 } 326 }
282 327
283 List<js.Statement> instantiations = 328 List<js.Statement> instantiations =
284 libraries.expand((Library library) => library.classes) 329 libraries.expand((Library library) => library.classes)
285 .where((Class cls) => cls.isEager) 330 .where((Class cls) => cls.isEager)
286 .map(createInstantiation) 331 .map(createInstantiation)
287 .toList(growable: false); 332 .toList(growable: false);
288 return new js.Block(instantiations); 333 return new js.Block(instantiations);
289 } 334 }
290 335
336 // This string should be referenced wherever JavaScript code makes assumptions
337 // on the mixin format.
338 static final String nativeInfoDescription =
339 "A class is encoded as follows:"
340 " [name, class-code, holder-index], or "
341 " [name, class-code, native-info, holder-index].";
342
291 js.Expression emitLibrary(Library library) { 343 js.Expression emitLibrary(Library library) {
292 Iterable staticDescriptors = library.statics.expand((e) => 344 Iterable staticDescriptors = library.statics.expand((StaticMethod m) =>
293 [ js.string(e.name), js.number(e.holder.index), emitStaticMethod(e) ]); 345 [js.string(m.name), js.number(m.holder.index), emitStaticMethod(m)]);
294 Iterable classDescriptors = library.classes.expand((e) => 346
295 [ js.string(e.name), js.number(e.holder.index), emitClass(e) ]); 347 Iterable classDescriptors = library.classes.expand((Class cls) {
348 js.LiteralString name = js.string(cls.name);
349 js.LiteralNumber holderIndex = js.number(cls.holder.index);
350 js.Expression emittedClass = emitClass(cls);
351 if (cls.nativeInfo == null) {
352 return [name, emittedClass, holderIndex];
353 } else {
354 return [name, emittedClass, js.string(cls.nativeInfo), holderIndex];
355 }
356 });
296 357
297 js.Expression staticArray = 358 js.Expression staticArray =
298 new js.ArrayInitializer(staticDescriptors.toList(growable: false)); 359 new js.ArrayInitializer(staticDescriptors.toList(growable: false));
299 js.Expression classArray = 360 js.Expression classArray =
300 new js.ArrayInitializer(classDescriptors.toList(growable: false)); 361 new js.ArrayInitializer(classDescriptors.toList(growable: false));
301 362
302 return new js.ArrayInitializer([staticArray, classArray]); 363 return new js.ArrayInitializer([staticArray, classArray]);
303 } 364 }
304 365
305 js.Expression _generateConstructor(Class cls) { 366 js.Expression _generateConstructor(Class cls) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 460
400 static final String boilerplate = """ 461 static final String boilerplate = """
401 { 462 {
402 // Declare deferred-initializer global. 463 // Declare deferred-initializer global.
403 #deferredInitializer; 464 #deferredInitializer;
404 465
405 !function(start, program) { 466 !function(start, program) {
406 467
407 // Initialize holder objects. 468 // Initialize holder objects.
408 #holders; 469 #holders;
470 var nativeInfos = Object.create(null);
409 471
410 function setupProgram() { 472 function setupProgram() {
411 for (var i = 0; i < program.length - 1; i++) { 473 for (var i = 0; i < program.length - 1; i++) {
412 setupLibrary(program[i]); 474 setupLibrary(program[i]);
413 } 475 }
414 setupLazyStatics(program[i]); 476 setupLazyStatics(program[i]);
415 } 477 }
416 478
417 function setupLibrary(library) { 479 function setupLibrary(library) {
418 var statics = library[0]; 480 var statics = library[0];
419 for (var i = 0; i < statics.length; i += 3) { 481 for (var i = 0; i < statics.length; i += 3) {
420 var holderIndex = statics[i + 1]; 482 var holderIndex = statics[i + 1];
421 setupStatic(statics[i], holders[holderIndex], statics[i + 2]); 483 setupStatic(statics[i], holders[holderIndex], statics[i + 2]);
422 } 484 }
423 485
424 var classes = library[1]; 486 var classes = library[1];
425 for (var i = 0; i < classes.length; i += 3) { 487 for (var i = 0; i < classes.length; i += 3) {
426 var holderIndex = classes[i + 1]; 488 var name = classes[i];
427 holdersMap[classes[i]] = holders[holderIndex]; 489 var cls = classes[i + 1];
428 setupClass(classes[i], holders[holderIndex], classes[i + 2]); 490
491 if (#hasNativeClasses) {
492 // $nativeInfoDescription.
493 var indexOrNativeInfo = classes[i + 2];
494 if (typeof indexOrNativeInfo == "number") {
495 var holderIndex = classes[i + 2];
496 } else {
497 nativeInfos[name] = indexOrNativeInfo;
498 holderIndex = classes[i + 3];
499 i++;
500 }
501 }
502
503 if (#hasNotNativeClasses) {
zarah 2015/01/28 10:54:40 hasNoNativeClasses
floitsch 2015/01/28 13:28:27 Done.
504 var holderIndex = classes[i + 2];
505 }
506
507 holdersMap[name] = holders[holderIndex];
508 setupClass(name, holders[holderIndex], cls);
429 } 509 }
430 } 510 }
431 511
432 function setupLazyStatics(statics) { 512 function setupLazyStatics(statics) {
433 for (var i = 0; i < statics.length; i += 4) { 513 for (var i = 0; i < statics.length; i += 4) {
434 var name = statics[i]; 514 var name = statics[i];
435 var getterName = statics[i + 1]; 515 var getterName = statics[i + 1];
436 var holderIndex = statics[i + 2]; 516 var holderIndex = statics[i + 2];
437 var initializer = statics[i + 3]; 517 var initializer = statics[i + 3];
438 setupLazyStatic(name, getterName, holders[holderIndex], initializer); 518 setupLazyStatic(name, getterName, holders[holderIndex], initializer);
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 function makeConstList(list) { 638 function makeConstList(list) {
559 // By assigning a function to the properties they become part of the 639 // By assigning a function to the properties they become part of the
560 // hidden class. The actual values of the fields don't matter, since we 640 // hidden class. The actual values of the fields don't matter, since we
561 // only check if they exist. 641 // only check if they exist.
562 list.immutable\$list = Array; 642 list.immutable\$list = Array;
563 list.fixed\$length = Array; 643 list.fixed\$length = Array;
564 return list; 644 return list;
565 } 645 }
566 } 646 }
567 647
648 if (#hasNativeClasses) {
649 function handleNativeClassInfos() {
650 for (var nativeClass in nativeInfos) {
651 var constructor = holdersMap[nativeClass][nativeClass].ensureResolved();
652 var nativeInfo = nativeInfos[nativeClass];
653 #nativeInfoHandler;
654 }
655 }
656 }
657
568 setupProgram(); 658 setupProgram();
569 659
570 // Initialize constants. 660 // Initialize constants.
571 #constants; 661 #constants;
572 662
573 // Initialize globals. 663 // Initialize globals.
574 #embeddedGlobals; 664 #embeddedGlobals;
575 665
666 // TODO(floitsch): this order means that native classes may not be
667 // referenced from constants. I'm mostly afraid of things like using them as
668 // generic arguments (which should be fine, but maybe there are other
669 // similar things).
670 // Initialize natives.
671 if (#hasNativeClasses) handleNativeClassInfos();
672
576 // Initialize static non-final fields. 673 // Initialize static non-final fields.
577 #staticNonFinals; 674 #staticNonFinals;
578 675
579 // Add native boilerplate code. 676 // Add native boilerplate code.
580 #nativeBoilerplate; 677 #nativeIsolateAffinityTagInitialization;
581 678
582 // Initialize eager classes. 679 // Initialize eager classes.
583 #eagerClasses; 680 #eagerClasses;
584 681
585 var end = Date.now(); 682 var end = Date.now();
586 print('Setup: ' + (end - start) + ' ms.'); 683 print('Setup: ' + (end - start) + ' ms.');
587 684
588 #main(); // Start main. 685 #main(); // Start main.
589 686
590 }(Date.now(), #code) 687 }(Date.now(), #code)
591 }"""; 688 }""";
592 689
593 } 690 }
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