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

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

Issue 903283002: dart2js: fix deferred loading in the new emitter. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase and clean up. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/model.dart ('k') | pkg/compiler/lib/src/js_emitter/program_builder.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
diff --git a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
index 32f48eb31590f1b07174425120a6b7414b0c6af2..ef27416f63320c949cbc17d36ce952fee0a3c55a 100644
--- a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
@@ -17,6 +17,7 @@ import '../js_emitter.dart' show
NativeEmitter;
import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show
+ CREATE_NEW_ISOLATE,
DEFERRED_LIBRARY_URIS,
DEFERRED_LIBRARY_HASHES,
GET_TYPE_FROM_NAME,
@@ -61,14 +62,12 @@ class ModelEmitter {
int emitProgram(Program program) {
List<Fragment> fragments = program.fragments;
MainFragment mainFragment = fragments.first;
- js.Statement mainAst = emitMainFragment(program);
- String mainCode = js.prettyPrint(mainAst, compiler).getText();
- compiler.outputProvider(mainFragment.outputFileName, 'js')
- ..add(buildGeneratedBy(compiler))
- ..add(mainCode)
- ..close();
- int totalSize = mainCode.length;
+ int totalSize = 0;
+
+ // We have to emit the deferred fragments first, since we need their
+ // deferred hash (which depends on the output) when emitting the main
+ // fragment.
fragments.skip(1).forEach((DeferredFragment deferredUnit) {
js.Expression ast =
emitDeferredFragment(deferredUnit, mainFragment.holders);
@@ -78,10 +77,19 @@ class ModelEmitter {
..add(code)
..close();
});
+
+ js.Statement mainAst = emitMainFragment(program);
+ String mainCode = js.prettyPrint(mainAst, compiler).getText();
+ compiler.outputProvider(mainFragment.outputFileName, 'js')
+ ..add(buildGeneratedBy(compiler))
+ ..add(mainCode)
+ ..close();
+ totalSize += mainCode.length;
+
return totalSize;
}
- js.LiteralString unparse(Compiler compiler, js.Expression value) {
+ js.LiteralString unparse(Compiler compiler, js.Node value) {
String text = js.prettyPrint(value, compiler).getText();
if (value is js.Fun) text = '($text)';
return js.js.escapedString(text);
@@ -200,9 +208,7 @@ class ModelEmitter {
List<js.Property> globals = <js.Property>[];
if (program.loadMap.isNotEmpty) {
- globals.addAll(emitLoadUrisAndHashes(program.loadMap));
- globals.add(emitIsHunkLoadedFunction());
- globals.add(emitInitializeLoadedHunk());
+ globals.addAll(emitEmbeddedGlobalsForDeferredLoading(program.loadMap));
}
if (program.typeToInterceptorMap != null) {
@@ -210,6 +216,14 @@ class ModelEmitter {
program.typeToInterceptorMap));
}
+ if (program.hasIsolateSupport) {
+ String isolateName = namer.currentIsolate;
+ globals.add(
+ new js.Property(js.string(CREATE_NEW_ISOLATE),
+ js.js('function () { return $isolateName; }')));
+ // TODO(floitsch): add remaining isolate functions.
+ }
+
globals.add(emitMangledGlobalNames());
globals.add(emitGetTypeFromName());
@@ -252,12 +266,24 @@ class ModelEmitter {
new js.ObjectInitializer(names));
}
- List<js.Property> emitLoadUrisAndHashes(Map<String, List<Fragment>> loadMap) {
- js.ArrayInitializer outputUris(List<Fragment> fragments) {
+ js.Statement emitDeferredInitializerGlobal(Map loadMap) {
+ if (loadMap.isEmpty) return new js.Block.empty();
+
+ return js.js.statement("""
+ if (typeof($deferredInitializersGlobal) === 'undefined')
+ var $deferredInitializersGlobal = Object.create(null);""");
+ }
+
+ Iterable<js.Property> emitEmbeddedGlobalsForDeferredLoading(
+ Map<String, List<Fragment>> loadMap) {
+
+ List<js.Property> globals = <js.Property>[];
+
+ js.ArrayInitializer fragmentUris(List<Fragment> fragments) {
return js.stringArray(fragments.map((DeferredFragment fragment) =>
- "${fragment.outputFileName}$deferredExtension"));
+ "${fragment.outputFileName}.$deferredExtension"));
}
- js.ArrayInitializer outputHashes(List<Fragment> fragments) {
+ js.ArrayInitializer fragmentHashes(List<Fragment> fragments) {
// TODO(floitsch): the hash must depend on the generated code.
return js.numArray(
fragments.map((DeferredFragment fragment) => fragment.hashCode));
@@ -268,38 +294,41 @@ class ModelEmitter {
int count = 0;
loadMap.forEach((String loadId, List<Fragment> fragmentList) {
uris[count] =
- new js.Property(js.string(loadId), outputUris(fragmentList));
+ new js.Property(js.string(loadId), fragmentUris(fragmentList));
hashes[count] =
- new js.Property(js.string(loadId), outputHashes(fragmentList));
+ new js.Property(js.string(loadId), fragmentHashes(fragmentList));
count++;
});
- return <js.Property>[
- new js.Property(js.string(DEFERRED_LIBRARY_URIS),
- new js.ObjectInitializer(uris)),
- new js.Property(js.string(DEFERRED_LIBRARY_HASHES),
- new js.ObjectInitializer(hashes))
- ];
- }
+ globals.add(new js.Property(js.string(DEFERRED_LIBRARY_URIS),
+ new js.ObjectInitializer(uris)));
+ globals.add(new js.Property(js.string(DEFERRED_LIBRARY_HASHES),
+ new js.ObjectInitializer(hashes)));
- js.Statement emitDeferredInitializerGlobal(Map loadMap) {
- if (loadMap.isEmpty) return new js.Block.empty();
+ js.Expression isHunkLoadedFunction =
+ js.js("function(hash) { return !!$deferredInitializersGlobal[hash]; }");
+ globals.add(new js.Property(js.string(IS_HUNK_LOADED),
+ isHunkLoadedFunction));
- return js.js.statement("""
- if (typeof($deferredInitializersGlobal) === 'undefined')
- var $deferredInitializersGlobal = Object.create(null);""");
- }
+ js.Expression isHunkInitializedFunction =
+ js.js("function(hash) { return false; }");
+ globals.add(new js.Property(js.string(IS_HUNK_INITIALIZED),
+ isHunkInitializedFunction));
- js.Property emitIsHunkLoadedFunction() {
- js.Expression function =
- js.js("function(hash) { return !!$deferredInitializersGlobal[hash]; }");
- return new js.Property(js.string(IS_HUNK_LOADED), function);
- }
+ /// See [emitEmbeddedGlobalsForDeferredLoading] for the format of the
+ /// deferred hunk.
+ js.Expression initializeLoadedHunkFunction =
+ js.js("""
+ function(hash) {
+ var hunk = $deferredInitializersGlobal[hash];
+ $setupProgramName(hunk[0]);
+ eval(hunk[1]);
+ }""");
- js.Property emitInitializeLoadedHunk() {
- js.Expression function =
- js.js("function(hash) { eval($deferredInitializersGlobal[hash]); }");
- return new js.Property(js.string(INITIALIZE_LOADED_HUNK), function);
+ globals.add(new js.Property(js.string(INITIALIZE_LOADED_HUNK),
+ initializeLoadedHunkFunction));
+
+ return globals;
}
js.Property emitGetTypeFromName() {
@@ -322,14 +351,30 @@ class ModelEmitter {
List<Holder> holders) {
// TODO(floitsch): initialize eager classes.
// TODO(floitsch): the hash must depend on the output.
- int hash = this.hashCode;
- if (fragment.constants.isNotEmpty) {
- throw new UnimplementedError("constants in deferred units");
- }
- js.ArrayInitializer content =
- new js.ArrayInitializer(fragment.libraries.map(emitLibrary)
- .toList(growable: false));
- return js.js("$deferredInitializersGlobal[$hash] = #", content);
+ int hash = fragment.hashCode;
+
+ List<js.Expression> deferredCode =
+ fragment.libraries.map(emitLibrary).toList();
+
+ deferredCode.add(
+ emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields));
+
+ js.ArrayInitializer deferredArray = new js.ArrayInitializer(deferredCode);
+
+ // This is the code that must be evaluated after all deferred classes have
+ // been setup.
+ js.Statement immediateCode = js.js.statement('''{
+ #constants;
+ #eagerClasses;
+ }''',
+ {'constants': emitConstants(fragment.constants),
+ 'eagerClasses': emitEagerClassInitializations(fragment.libraries)});
+
+ js.LiteralString immediateString = unparse(compiler, immediateCode);
+ js.ArrayInitializer hunk =
+ new js.ArrayInitializer([deferredArray, immediateString]);
+
+ return js.js("$deferredInitializersGlobal[$hash] = #", hunk);
}
js.Block emitConstants(List<Constant> constants) {
@@ -659,6 +704,8 @@ function parseFunctionDescriptor(proto, name, descriptor) {
return output;
}
+ static final String setupProgramName = "setupProgram";
+
static final String boilerplate = """
{
// Declare deferred-initializer global.
@@ -672,7 +719,7 @@ function parseFunctionDescriptor(proto, name, descriptor) {
// Counter to generate unique names for tear offs.
var functionCounter = 0;
- function setupProgram() {
+ function $setupProgramName(program) {
for (var i = 0; i < program.length - 1; i++) {
setupLibrary(program[i]);
}
@@ -905,7 +952,7 @@ function parseFunctionDescriptor(proto, name, descriptor) {
}
}
- setupProgram();
+ $setupProgramName(program);
// Initialize constants.
#constants;
@@ -930,7 +977,7 @@ function parseFunctionDescriptor(proto, name, descriptor) {
#eagerClasses;
var end = Date.now();
- print('Setup: ' + (end - start) + ' ms.');
+ // print('Setup: ' + (end - start) + ' ms.');
zarah 2015/02/10 15:05:24 Why comment it out?
floitsch 2015/02/10 15:13:34 Because it doesn't work in the browser.
#invokeMain; // Start main.
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/model.dart ('k') | pkg/compiler/lib/src/js_emitter/program_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698