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

Unified Diff: sdk/lib/_internal/compiler/implementation/js_emitter/new_emitter/model_emitter.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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
Index: sdk/lib/_internal/compiler/implementation/js_emitter/new_emitter/model_emitter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/new_emitter/model_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/new_emitter/model_emitter.dart
deleted file mode 100644
index d3d6c1d69a48f9986700726e6e90c9739847e0c8..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/new_emitter/model_emitter.dart
+++ /dev/null
@@ -1,498 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.new_js_emitter.model_emitter;
-
-import '../../dart2jslib.dart' show Compiler;
-import '../../js/js.dart' as js;
-import '../../js_backend/js_backend.dart' show
- JavaScriptBackend,
- Namer,
- ConstantEmitter;
-
-import '../../../js_lib/shared/embedded_names.dart' show
- DEFERRED_LIBRARY_URIS,
- DEFERRED_LIBRARY_HASHES,
- INITIALIZE_LOADED_HUNK,
- IS_HUNK_LOADED;
-
-import '../model.dart';
-
-class ModelEmitter {
- final Compiler compiler;
- final Namer namer;
- final ConstantEmitter constantEmitter;
-
- JavaScriptBackend get backend => compiler.backend;
-
- /// For deferred loading we communicate the initializers via this global var.
- static const String deferredInitializersGlobal =
- r"$__dart_deferred_initializers__";
-
- static const String deferredExtension = ".part.js";
-
- ModelEmitter(Compiler compiler, Namer namer)
- : this.compiler = compiler,
- this.namer = namer,
- constantEmitter =
- new ConstantEmitter(compiler, namer, makeConstantListTemplate);
-
- void emitProgram(Program program) {
- List<Output> outputs = program.outputs;
- MainOutput mainUnit = outputs.first;
- js.Statement mainAst = emitMainUnit(program);
- String mainCode = js.prettyPrint(mainAst, compiler).getText();
- compiler.outputProvider(mainUnit.outputFileName, 'js')
- ..add(buildGeneratedBy(compiler))
- ..add(mainCode)
- ..close();
- compiler.assembledCode = mainCode;
-
- outputs.skip(1).forEach((DeferredOutput deferredUnit) {
- js.Expression ast = emitDeferredUnit(deferredUnit, mainUnit.holders);
- String code = js.prettyPrint(ast, compiler).getText();
- compiler.outputProvider(deferredUnit.outputFileName, deferredExtension)
- ..add(code)
- ..close();
- });
- }
-
- js.LiteralString unparse(Compiler compiler, js.Expression value) {
- String text = js.prettyPrint(value, compiler).getText();
- if (value is js.Fun) text = '($text)';
- return js.js.escapedString(text);
- }
-
- String buildGeneratedBy(compiler) {
- var suffix = '';
- if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
- return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n';
- }
-
- js.Statement emitMainUnit(Program program) {
- MainOutput unit = program.outputs.first;
- List<js.Expression> elements = unit.libraries.map(emitLibrary).toList();
- elements.add(
- emitLazilyInitializedStatics(unit.staticLazilyInitializedFields));
- js.Expression code = new js.ArrayInitializer.from(elements);
- return js.js.statement(
- boilerplate,
- [emitDeferredInitializerGlobal(program.loadMap),
- emitHolders(unit.holders),
- namer.elementAccess(backend.getCyclicThrowHelper()),
- program.outputContainsConstantList,
- emitEmbeddedGlobals(program.loadMap),
- emitConstants(unit.constants),
- emitStaticNonFinalFields(unit.staticNonFinalFields),
- emitEagerClassInitializations(unit.libraries),
- unit.main,
- code]);
- }
-
- js.Block emitHolders(List<Holder> holders) {
- // The top-level variables for holders must *not* be renamed by the
- // JavaScript pretty printer because a lot of code already uses the
- // non-renamed names. The generated code looks like this:
- //
- // var H = {}, ..., G = {};
- // var holders = [ H, ..., G ];
- //
- // and it is inserted at the top of the top-level function expression
- // that covers the entire program.
-
- List<js.Statement> statements = [
- new js.ExpressionStatement(
- new js.VariableDeclarationList(holders.map((e) =>
- new js.VariableInitialization(
- new js.VariableDeclaration(e.name, allowRename: false),
- new js.ObjectInitializer(const []))).toList())),
- js.js.statement('var holders = #', new js.ArrayInitializer.from(
- holders.map((e) => new js.VariableUse(e.name))))
- ];
- return new js.Block(statements);
- }
-
- static js.Template get makeConstantListTemplate {
- // TODO(floitsch): remove hard-coded name.
- // TODO(floitsch): there is no harm in caching the template.
- return js.js.uncachedExpressionTemplate('makeConstList(#)');
- }
-
- js.Block emitEmbeddedGlobals(Map<String, List<Output>> loadMap) {
- List<js.Property> globals = <js.Property>[];
-
- if (loadMap.isNotEmpty) {
- globals.addAll(emitLoadUrisAndHashes(loadMap));
- globals.add(emitIsHunkLoadedFunction());
- globals.add(emitInitializeLoadedHunk());
- }
-
- if (globals.isEmpty) return new js.Block.empty();
-
- js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals);
-
- List<js.Statement> statements =
- [new js.ExpressionStatement(
- new js.VariableDeclarationList(
- [new js.VariableInitialization(
- new js.VariableDeclaration(r"init", allowRename: false),
- globalsObject)]))];
- return new js.Block(statements);
- }
-
- List<js.Property> emitLoadUrisAndHashes(Map<String, List<Output>> loadMap) {
- js.ArrayInitializer outputUris(List<Output> outputs) {
- return js.stringArray(outputs.map((DeferredOutput output) =>
- "${output.outputFileName}$deferredExtension"));
- }
- js.ArrayInitializer outputHashes(List<Output> outputs) {
- // TODO(floitsch): the hash must depend on the generated code.
- return js.numArray(
- outputs.map((DeferredOutput output) => output.hashCode));
- }
-
- List<js.Property> uris = new List<js.Property>(loadMap.length);
- List<js.Property> hashes = new List<js.Property>(loadMap.length);
- int count = 0;
- loadMap.forEach((String loadId, List<Output> outputList) {
- uris[count] = new js.Property(js.string(loadId), outputUris(outputList));
- hashes[count] =
- new js.Property(js.string(loadId), outputHashes(outputList));
- 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))
- ];
- }
-
- 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);""");
- }
-
- js.Property emitIsHunkLoadedFunction() {
- js.Expression function =
- js.js("function(hash) { return !!$deferredInitializersGlobal[hash]; }");
- return new js.Property(js.string(IS_HUNK_LOADED), function);
- }
-
- js.Property emitInitializeLoadedHunk() {
- js.Expression function =
- js.js("function(hash) { eval($deferredInitializersGlobal[hash]); }");
- return new js.Property(js.string(INITIALIZE_LOADED_HUNK), function);
- }
-
- js.Expression emitDeferredUnit(DeferredOutput unit, List<Holder> holders) {
- // TODO(floitsch): initialize eager classes.
- // TODO(floitsch): the hash must depend on the output.
- int hash = this.hashCode;
- if (unit.constants.isNotEmpty) {
- throw new UnimplementedError("constants in deferred units");
- }
- js.ArrayInitializer content =
- new js.ArrayInitializer.from(unit.libraries.map(emitLibrary));
- return js.js("$deferredInitializersGlobal[$hash] = #", content);
- }
-
- js.Block emitConstants(List<Constant> constants) {
- Iterable<js.Statement> statements = constants.map((Constant constant) {
- js.Expression code =
- constantEmitter.initializationExpression(constant.value);
- return js.js.statement("#.# = #;",
- [constant.holder.name, constant.name, code]);
- });
- return new js.Block(statements.toList());
- }
-
- js.Block emitStaticNonFinalFields(List<StaticField> fields) {
- Iterable<js.Statement> statements = fields.map((StaticField field) {
- return js.js.statement("#.# = #;",
- [field.holder.name, field.name, field.code]);
- });
- return new js.Block(statements.toList());
- }
-
- js.Expression emitLazilyInitializedStatics(List<StaticField> fields) {
- Iterable fieldDescriptors = fields.expand((field) =>
- [ js.string(field.name),
- js.string("${namer.getterPrefix}${field.name}"),
- js.number(field.holder.index),
- emitLazyInitializer(field) ]);
- return new js.ArrayInitializer.from(fieldDescriptors);
- }
-
- js.Block emitEagerClassInitializations(List<Library> libraries) {
- js.Statement createInstantiation(Class cls) {
- return js.js.statement('new #.#()', [cls.holder.name, cls.name]);
- }
-
- List<js.Statement> instantiations =
- libraries.expand((Library library) => library.classes)
- .where((Class cls) => cls.isEager)
- .map(createInstantiation)
- .toList(growable: false);
- return new js.Block(instantiations);
- }
-
- js.Expression emitLibrary(Library library) {
- Iterable staticDescriptors = library.statics.expand((e) =>
- [ js.string(e.name), js.number(e.holder.index), emitStaticMethod(e) ]);
- Iterable classDescriptors = library.classes.expand((e) =>
- [ js.string(e.name), js.number(e.holder.index), emitClass(e) ]);
-
- js.Expression staticArray = new js.ArrayInitializer.from(staticDescriptors);
- js.Expression classArray = new js.ArrayInitializer.from(classDescriptors);
-
- return new js.ArrayInitializer.from([staticArray, classArray]);
- }
-
- js.Expression _generateConstructor(Class cls) {
- List<String> allFieldNames = <String>[];
- Class currentClass = cls;
- while (currentClass != null) {
- allFieldNames.addAll(
- currentClass.fields.map((InstanceField field) => field.name));
- currentClass = currentClass.superclass;
- }
- String name = cls.name;
- String parameters = allFieldNames.join(', ');
- String assignments = allFieldNames
- .map((String field) => "this.$field = $field;\n")
- .join();
- String code = 'function $name($parameters) { $assignments }';
- js.Template template = js.js.uncachedExpressionTemplate(code);
- return template.instantiate(const []);
- }
-
- Method _generateGetter(InstanceField field) {
- String getterTemplateFor(int flags) {
- switch (flags) {
- case 1: return "function() { return this[#]; }";
- case 2: return "function(receiver) { return receiver[#]; }";
- case 3: return "function(receiver) { return this[#]; }";
- }
- return null;
- }
-
- js.Expression fieldName = js.string(field.name);
- js.Expression code = js.js(getterTemplateFor(field.getterFlags), fieldName);
- String getterName = "${namer.getterPrefix}${field.name}";
- return new Method(getterName, code);
- }
-
- Method _generateSetter(InstanceField field) {
- String setterTemplateFor(int flags) {
- switch (flags) {
- case 1: return "function(val) { return this[#] = val; }";
- case 2: return "function(receiver, val) { return receiver[#] = val; }";
- case 3: return "function(receiver, val) { return this[#] = val; }";
- }
- return null;
- }
- js.Expression fieldName = js.string(field.name);
- js.Expression code = js.js(setterTemplateFor(field.setterFlags), fieldName);
- String setterName = "${namer.setterPrefix}${field.name}";
- return new Method(setterName, code);
- }
-
- Iterable<Method> _generateGettersSetters(Class cls) {
- Iterable<Method> getters = cls.fields
- .where((InstanceField field) => field.needsGetter)
- .map(_generateGetter);
-
- Iterable<Method> setters = cls.fields
- .where((InstanceField field) => field.needsSetter)
- .map(_generateSetter);
-
- return [getters, setters].expand((x) => x);
- }
-
- js.Expression emitClass(Class cls) {
- List elements = [ js.string(cls.superclassName),
- js.number(cls.superclassHolderIndex),
- _generateConstructor(cls) ];
- Iterable<Method> methods = cls.methods;
- Iterable<Method> gettersSetters = _generateGettersSetters(cls);
- Iterable<Method> allMethods = [methods, gettersSetters].expand((x) => x);
- elements.addAll(allMethods.expand((e) => [ js.string(e.name), e.code ]));
- return unparse(compiler, new js.ArrayInitializer.from(elements));
- }
-
- js.Expression emitLazyInitializer(StaticField field) {
- assert(field.isLazy);
- return unparse(compiler, field.code);
- }
-
- js.Expression emitStaticMethod(StaticMethod method) {
- return unparse(compiler, method.code);
- }
-}
-
-final String boilerplate = r"""
-{
-// Declare deferred-initializer global.
-#;
-
-!function(start, program) {
-
- // Initialize holder objects.
- #;
-
- function setupProgram() {
- for (var i = 0; i < program.length - 1; i++) {
- setupLibrary(program[i]);
- }
- setupLazyStatics(program[i]);
- }
-
- function setupLibrary(library) {
- var statics = library[0];
- for (var i = 0; i < statics.length; i += 3) {
- var holderIndex = statics[i + 1];
- setupStatic(statics[i], holders[holderIndex], statics[i + 2]);
- }
-
- var classes = library[1];
- for (var i = 0; i < classes.length; i += 3) {
- var holderIndex = classes[i + 1];
- setupClass(classes[i], holders[holderIndex], classes[i + 2]);
- }
- }
-
- function setupLazyStatics(statics) {
- for (var i = 0; i < statics.length; i += 4) {
- var name = statics[i];
- var getterName = statics[i + 1];
- var holderIndex = statics[i + 2];
- var initializer = statics[i + 3];
- setupLazyStatic(name, getterName, holders[holderIndex], initializer);
- }
- }
-
- function setupStatic(name, holder, descriptor) {
- holder[name] = function() {
- var method = compile(name, descriptor);
- holder[name] = method;
- return method.apply(this, arguments);
- };
- }
-
- function setupLazyStatic(name, getterName, holder, descriptor) {
- holder[name] = null;
- holder[getterName] = function() {
- var initializer = compile(name, descriptor);
- holder[getterName] = function() { #(name) }; // cyclicThrowHelper
- var result;
- var sentinelInProgress = descriptor;
- try {
- result = holder[name] = sentinelInProgress;
- result = holder[name] = initializer();
- } finally {
- // Use try-finally, not try-catch/throw as it destroys the stack trace.
- if (result === sentinelInProgress) {
- // The lazy static (holder[name]) might have been set to a different
- // value. According to spec we still have to reset it to null, if the
- // initialization failed.
- holder[name] = null;
- }
- holder[getterName] = function() { return this[name]; };
- }
- return result;
- };
- }
-
- function setupClass(name, holder, descriptor) {
- var resolve = function() {
- var constructor = compileConstructor(name, descriptor);
- holder[name] = constructor;
- return constructor;
- };
-
- var patch = function() {
- var constructor = resolve();
- var object = new constructor();
- constructor.apply(object, arguments);
- return object;
- };
-
- // We store the resolve function on the patch function to make it possible
- // to resolve superclass references without constructing instances. The
- // resolve property also serves as a marker that indicates whether or not
- // a class has been resolved yet.
- patch.resolve = resolve;
- holder[name] = patch;
- }
-
- function compileConstructor(name, descriptor) {
- descriptor = compile(name, descriptor);
- var prototype = determinePrototype(descriptor);
- var constructor = descriptor[2];
- for (var i = 3; i < descriptor.length; i += 2) {
- prototype[descriptor[i]] = descriptor[i + 1];
- }
- constructor.prototype = prototype;
- return constructor;
- }
-
- function determinePrototype(descriptor) {
- var superclassName = descriptor[0];
- if (!superclassName) return { };
-
- // Look up the superclass constructor function in the right holder.
- var holderIndex = descriptor[1];
- var superclass = holders[holderIndex][superclassName];
- if (superclass.resolve) superclass = superclass.resolve();
-
- // Create a new prototype object chained to the superclass prototype.
- var intermediate = function() { };
- intermediate.prototype = superclass.prototype;
- return new intermediate();
- }
-
- function compile(__name__, __s__) {
- 'use strict';
- // TODO(floitsch): evaluate the performance impact of the string
- // concatenations.
- return eval(__s__ + "\n//# sourceURL=" + __name__ + ".js");
- }
-
- if (#) { // outputContainsConstantList
- function makeConstList(list) {
- // By assigning a function to the properties they become part of the
- // hidden class. The actual values of the fields don't matter, since we
- // only check if they exist.
- list.immutable$list = Array;
- list.fixed$length = Array;
- return list;
- }
- }
-
- setupProgram();
-
- // Initialize globals.
- #;
-
- // Initialize constants.
- #;
-
- // Initialize static non-final fields.
- #;
-
- // Initialize eager classes.
- #;
-
- var end = Date.now();
- print('Setup: ' + (end - start) + ' ms.');
-
- if (true) #(); // Start main.
-
-}(Date.now(), #)
-}""";

Powered by Google App Engine
This is Rietveld 408576698