Index: pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart |
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5048fe5f5cb7ea9024cd7c2a60ab652a034bcafa |
--- /dev/null |
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart |
@@ -0,0 +1,130 @@ |
+// Copyright (c) 2015, 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.js_emitter.startup_emitter.model_emitter; |
+ |
+import '../../constants/values.dart' show ConstantValue, FunctionConstantValue; |
+import '../../dart2jslib.dart' show Compiler; |
+import '../../elements/elements.dart' show ClassElement, FunctionElement; |
+import '../../js/js.dart' as js; |
+import '../../js_backend/js_backend.dart' show |
+ JavaScriptBackend, |
+ Namer, |
+ ConstantEmitter; |
+ |
+import '../js_emitter.dart' show AstContainer, NativeEmitter; |
+ |
+import 'package:js_runtime/shared/embedded_names.dart' show |
+ CREATE_NEW_ISOLATE, |
+ DEFERRED_INITIALIZED, |
+ DEFERRED_LIBRARY_URIS, |
+ DEFERRED_LIBRARY_HASHES, |
+ GET_TYPE_FROM_NAME, |
+ INITIALIZE_LOADED_HUNK, |
+ INTERCEPTORS_BY_TAG, |
+ IS_HUNK_INITIALIZED, |
+ IS_HUNK_LOADED, |
+ LEAF_TAGS, |
+ MANGLED_GLOBAL_NAMES, |
+ METADATA, |
+ NATIVE_SUPERCLASS_TAG_NAME, |
+ TYPE_TO_INTERCEPTOR_MAP, |
+ TYPES; |
+ |
+import '../js_emitter.dart' show NativeGenerator, buildTearOffCode; |
+import '../model.dart'; |
+ |
+class ModelEmitter { |
+ final Compiler compiler; |
+ final Namer namer; |
+ ConstantEmitter constantEmitter; |
+ final NativeEmitter nativeEmitter; |
+ |
+ 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"; |
+ |
+ static const String typeNameProperty = r"builtin$cls"; |
+ |
+ ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter) |
+ : this.compiler = compiler, |
+ this.namer = namer { |
+ this.constantEmitter = new ConstantEmitter( |
+ compiler, namer, this.generateConstantReference, |
+ constantListGenerator); |
+ } |
+ |
+ js.Expression constantListGenerator(js.Expression array) { |
+ // TODO(floitsch): remove hard-coded name. |
+ return js.js('makeConstList(#)', [array]); |
+ } |
+ |
+ js.Expression generateEmbeddedGlobalAccess(String global) { |
+ return js.js(generateEmbeddedGlobalAccessString(global)); |
+ } |
+ |
+ String generateEmbeddedGlobalAccessString(String global) { |
+ // TODO(floitsch): don't use 'init' as global embedder storage. |
+ return 'init.$global'; |
+ } |
+ |
+ bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { |
+ if (constant.isFunction) return true; // Already emitted. |
+ if (constant.isPrimitive) return true; // Inlined. |
+ if (constant.isDummy) return true; // Inlined. |
+ return false; |
+ } |
+ |
+ // TODO(floitsch): copied from OldEmitter. Adjust or share. |
+ int compareConstants(ConstantValue a, ConstantValue b) { |
+ // Inlined constants don't affect the order and sometimes don't even have |
+ // names. |
+ int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1; |
+ int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1; |
+ if (cmp1 + cmp2 < 2) return cmp1 - cmp2; |
+ |
+ // Emit constant interceptors first. Constant interceptors for primitives |
+ // might be used by code that builds other constants. See Issue 18173. |
+ if (a.isInterceptor != b.isInterceptor) { |
+ return a.isInterceptor ? -1 : 1; |
+ } |
+ |
+ // Sorting by the long name clusters constants with the same constructor |
+ // which compresses a tiny bit better. |
+ int r = namer.constantLongName(a).compareTo(namer.constantLongName(b)); |
+ if (r != 0) return r; |
+ // Resolve collisions in the long name by using the constant name (i.e. JS |
+ // name) which is unique. |
+ return namer.constantName(a).compareTo(namer.constantName(b)); |
+ } |
+ |
+ js.Expression generateStaticClosureAccess(FunctionElement element) { |
+ return js.js('#.#()', |
+ [namer.globalObjectFor(element), namer.staticClosureName(element)]); |
+ } |
+ |
+ js.Expression generateConstantReference(ConstantValue value) { |
+ if (value.isFunction) { |
+ FunctionConstantValue functionConstant = value; |
+ return generateStaticClosureAccess(functionConstant.element); |
+ } |
+ |
+ // We are only interested in the "isInlined" part, but it does not hurt to |
+ // test for the other predicates. |
+ if (isConstantInlinedOrAlreadyEmitted(value)) { |
+ return constantEmitter.generate(value); |
+ } |
+ return js.js('#.#', [namer.globalObjectForConstant(value), |
+ namer.constantName(value)]); |
+ } |
+ |
+ int emitProgram(Program program) { |
+ // TODO(floitsch): implement. |
+ throw new UnimplementedError("startup-emitter.emitProgram"); |
+ } |
+} |