Chromium Code Reviews| 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 9139905a587a9a72e45d6a183f8770900c91f520..b2b9d3292697b51105dae16d8384914cd2a535c9 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 |
| @@ -11,13 +11,18 @@ import '../../js_backend/js_backend.dart' show |
| Namer, |
| ConstantEmitter; |
| +import '../js_emitter.dart' show |
| + NativeEmitter; |
| + |
| import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show |
| DEFERRED_LIBRARY_URIS, |
| DEFERRED_LIBRARY_HASHES, |
| GET_TYPE_FROM_NAME, |
| INITIALIZE_LOADED_HUNK, |
| + INTERCEPTORS_BY_TAG, |
| IS_HUNK_INITIALIZED, |
| IS_HUNK_LOADED, |
| + LEAF_TAGS, |
| TYPE_TO_INTERCEPTOR_MAP; |
| import '../js_emitter.dart' show NativeGenerator; |
| @@ -27,6 +32,7 @@ class ModelEmitter { |
| final Compiler compiler; |
| final Namer namer; |
| final ConstantEmitter constantEmitter; |
| + final NativeEmitter nativeEmitter; |
| JavaScriptBackend get backend => compiler.backend; |
| @@ -36,7 +42,7 @@ class ModelEmitter { |
| static const String deferredExtension = "part.js"; |
| - ModelEmitter(Compiler compiler, Namer namer) |
| + ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter) |
| : this.compiler = compiler, |
| this.namer = namer, |
| constantEmitter = |
| @@ -88,34 +94,66 @@ class ModelEmitter { |
| elements.add( |
| emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields)); |
| - js.Statement nativeBoilerplate; |
| + js.Expression code = new js.ArrayInitializer(elements); |
| + |
| + Map<String, dynamic> holes = |
| + {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), |
| + 'holders': emitHolders(fragment.holders), |
| + 'cyclicThrow': |
| + backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), |
| + 'outputContainsConstantList': program.outputContainsConstantList, |
| + 'embeddedGlobals': emitEmbeddedGlobals(program), |
| + 'constants': emitConstants(fragment.constants), |
| + 'staticNonFinals': |
| + emitStaticNonFinalFields(fragment.staticNonFinalFields), |
| + 'eagerClasses': emitEagerClassInitializations(fragment.libraries), |
| + 'main': fragment.main, |
| + 'code': code}; |
| + |
| + holes.addAll(nativeHoles(program)); |
| + |
| + return js.js.statement(boilerplate, holes); |
| + } |
| + |
| + Map<String, dynamic> nativeHoles(Program program) { |
| + Map<String, dynamic> nativeHoles = <String, dynamic>{}; |
| + |
| + js.Statement nativeIsolateAffinityTagInitialization; |
| if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { |
| - nativeBoilerplate = |
| + nativeIsolateAffinityTagInitialization = |
| NativeGenerator.generateIsolateAffinityTagInitialization( |
| backend, |
| generateEmbeddedGlobalAccess, |
| // TODO(floitsch): convertToFastObject. |
| js.js("(function(x) { return x; })", [])); |
| } else { |
| - nativeBoilerplate = js.js.statement(";"); |
| + nativeIsolateAffinityTagInitialization = js.js.statement(";"); |
| } |
| + nativeHoles['nativeIsolateAffinityTagInitialization'] = |
| + nativeIsolateAffinityTagInitialization; |
| - js.Expression code = new js.ArrayInitializer(elements); |
| - return js.js.statement( |
| - boilerplate, |
| - {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), |
| - 'holders': emitHolders(fragment.holders), |
| - 'cyclicThrow': |
| - backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), |
| - 'outputContainsConstantList': program.outputContainsConstantList, |
| - 'embeddedGlobals': emitEmbeddedGlobals(program), |
| - 'constants': emitConstants(fragment.constants), |
| - 'staticNonFinals': emitStaticNonFinalFields(fragment.staticNonFinalFields), |
| - 'nativeBoilerplate': nativeBoilerplate, |
| - 'eagerClasses': emitEagerClassInitializations(fragment.libraries), |
| - 'main': fragment.main, |
| - 'code': code}); |
| + js.Expression nativeInfoAccess = js.js('nativeInfo', []); |
| + js.Expression constructorAccess = js.js('constructor', []); |
| + Function subclassReadGenerator = (js.Expression subclass) { |
| + return js.js('holdersMap[#][#].ensureResolved()', [subclass, subclass]); |
| + }; |
| + js.Expression interceptorsByTagAccess = |
| + generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG); |
| + js.Expression leafTagsAccess = |
| + generateEmbeddedGlobalAccess(LEAF_TAGS); |
| + js.Statement nativeInfoHandler = nativeEmitter.buildNativeInfoHandler( |
| + nativeInfoAccess, |
| + constructorAccess, |
| + subclassReadGenerator, |
| + interceptorsByTagAccess, |
| + leafTagsAccess); |
| + |
| + nativeHoles['hasNativeClasses'] = program.outputContainsNativeClasses; |
| + nativeHoles['hasNotNativeClasses'] = !program.outputContainsNativeClasses; |
| + nativeHoles['nativeInfoHandler'] = nativeInfoHandler; |
| + |
| + return nativeHoles; |
| } |
| js.Block emitHolders(List<Holder> holders) { |
| @@ -165,6 +203,13 @@ class ModelEmitter { |
| program.typeToInterceptorMap)); |
| } |
| + if (program.outputContainsNativeClasses) { |
| + globals.add(new js.Property(js.string(INTERCEPTORS_BY_TAG), |
| + js.js('Object.create(null)', []))); |
| + globals.add(new js.Property(js.string(LEAF_TAGS), |
| + js.js('Object.create(null)', []))); |
| + } |
| + |
| js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals); |
| List<js.Statement> statements = |
| @@ -288,11 +333,27 @@ class ModelEmitter { |
| return new js.Block(instantiations); |
| } |
| + // This string should be referenced wherever JavaScript code makes assumptions |
| + // on the mixin format. |
| + static final String nativeInfoDescription = |
| + "A class is encoded as follows:" |
| + " [name, class-code, holder-index], or " |
| + " [name, class-code, native-info, holder-index]."; |
| + |
| 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) ]); |
| + Iterable staticDescriptors = library.statics.expand((StaticMethod m) => |
| + [js.string(m.name), js.number(m.holder.index), emitStaticMethod(m)]); |
| + |
| + Iterable classDescriptors = library.classes.expand((Class cls) { |
| + js.LiteralString name = js.string(cls.name); |
| + js.LiteralNumber holderIndex = js.number(cls.holder.index); |
| + js.Expression emittedClass = emitClass(cls); |
| + if (cls.nativeInfo == null) { |
| + return [name, emittedClass, holderIndex]; |
| + } else { |
| + return [name, emittedClass, js.string(cls.nativeInfo), holderIndex]; |
| + } |
| + }); |
| js.Expression staticArray = |
| new js.ArrayInitializer(staticDescriptors.toList(growable: false)); |
| @@ -406,6 +467,7 @@ class ModelEmitter { |
| // Initialize holder objects. |
| #holders; |
| + var nativeInfos = Object.create(null); |
| function setupProgram() { |
| for (var i = 0; i < program.length - 1; i++) { |
| @@ -423,9 +485,27 @@ class ModelEmitter { |
| var classes = library[1]; |
| for (var i = 0; i < classes.length; i += 3) { |
| - var holderIndex = classes[i + 1]; |
| - holdersMap[classes[i]] = holders[holderIndex]; |
| - setupClass(classes[i], holders[holderIndex], classes[i + 2]); |
| + var name = classes[i]; |
| + var cls = classes[i + 1]; |
| + |
| + if (#hasNativeClasses) { |
| + // $nativeInfoDescription. |
| + var indexOrNativeInfo = classes[i + 2]; |
| + if (typeof indexOrNativeInfo == "number") { |
| + var holderIndex = classes[i + 2]; |
| + } else { |
| + nativeInfos[name] = indexOrNativeInfo; |
| + holderIndex = classes[i + 3]; |
| + i++; |
| + } |
| + } |
| + |
| + if (#hasNotNativeClasses) { |
|
zarah
2015/01/28 10:54:40
hasNoNativeClasses
floitsch
2015/01/28 13:28:27
Done.
|
| + var holderIndex = classes[i + 2]; |
| + } |
| + |
| + holdersMap[name] = holders[holderIndex]; |
| + setupClass(name, holders[holderIndex], cls); |
| } |
| } |
| @@ -565,6 +645,16 @@ class ModelEmitter { |
| } |
| } |
| + if (#hasNativeClasses) { |
| + function handleNativeClassInfos() { |
| + for (var nativeClass in nativeInfos) { |
| + var constructor = holdersMap[nativeClass][nativeClass].ensureResolved(); |
| + var nativeInfo = nativeInfos[nativeClass]; |
| + #nativeInfoHandler; |
| + } |
| + } |
| + } |
| + |
| setupProgram(); |
| // Initialize constants. |
| @@ -573,11 +663,18 @@ class ModelEmitter { |
| // Initialize globals. |
| #embeddedGlobals; |
| + // TODO(floitsch): this order means that native classes may not be |
| + // referenced from constants. I'm mostly afraid of things like using them as |
| + // generic arguments (which should be fine, but maybe there are other |
| + // similar things). |
| + // Initialize natives. |
| + if (#hasNativeClasses) handleNativeClassInfos(); |
| + |
| // Initialize static non-final fields. |
| #staticNonFinals; |
| // Add native boilerplate code. |
| - #nativeBoilerplate; |
| + #nativeIsolateAffinityTagInitialization; |
| // Initialize eager classes. |
| #eagerClasses; |