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 32c5a63c9cf6aec66feb5e54b41d750a1bbc2e13..50b174fc62282e2c6eb6dec9e003e08fe5a36fa2 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 |
| @@ -68,6 +68,11 @@ class ModelEmitter { |
| return js.js("init.$global"); |
| } |
| + String generateEmbeddedGlobalAccessString(String global) { |
| + // TODO(floitsch): We should not use "init" for globals. |
| + return "init.$global"; |
| + } |
| + |
| bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { |
| if (constant.isFunction) return true; // Already emitted. |
| if (constant.isPrimitive) return true; // Inlined. |
| @@ -132,7 +137,9 @@ class ModelEmitter { |
| // deferred hash (which depends on the output) when emitting the main |
| // fragment. |
| fragments.skip(1).forEach((DeferredFragment deferredUnit) { |
| - js.Expression ast = emitDeferredFragment(deferredUnit, program.holders); |
| + List<String> types = program.metadataTypes[deferredUnit.outputUnit]; |
| + js.Expression ast = emitDeferredFragment(types, deferredUnit, |
| + program.holders); |
| String code = js.prettyPrint(ast, compiler).getText(); |
| totalSize += code.length; |
| compiler.outputProvider(deferredUnit.outputFileName, deferredExtension) |
| @@ -384,14 +391,18 @@ class ModelEmitter { |
| globals.add(new js.Property(js.string(IS_HUNK_INITIALIZED), |
| isHunkInitializedFunction)); |
| + String typesAccess = generateEmbeddedGlobalAccessString(TYPES); |
| + |
| /// See [emitEmbeddedGlobalsForDeferredLoading] for the format of the |
| /// deferred hunk. |
| js.Expression initializeLoadedHunkFunction = |
| js.js(""" |
| function(hash) { |
| var hunk = $deferredInitializersGlobal[hash]; |
| - $setupProgramName(hunk[0]); |
| + $setupProgramName(hunk[0], ${typesAccess}.length); |
|
sigurdm
2015/04/09 13:00:15
Why not
$setupProgramName(hunk[0], #typesAcces
zarah
2015/04/10 10:56:03
Done.
|
| eval(hunk[1]); |
| + var deferredTypes = eval(hunk[2]); |
| + ${typesAccess}.push.apply(${typesAccess}, deferredTypes); |
| }"""); |
| globals.add(new js.Property(js.string(INITIALIZE_LOADED_HUNK), |
| @@ -420,12 +431,16 @@ class ModelEmitter { |
| } |
| metadataGlobals.add(createGlobal(program.metadata, METADATA)); |
| - metadataGlobals.add(createGlobal(program.metadataTypes, TYPES)); |
| + List<String> types = |
| + program.metadataTypes[program.fragments.first.outputUnit]; |
| + if (types == null) types = <String>[]; |
| + metadataGlobals.add(createGlobal(types, TYPES)); |
| return metadataGlobals; |
| } |
| - js.Expression emitDeferredFragment(DeferredFragment fragment, |
| + js.Expression emitDeferredFragment(List<String> types, |
| + DeferredFragment fragment, |
| List<Holder> holders) { |
| // TODO(floitsch): initialize eager classes. |
| // TODO(floitsch): the hash must depend on the output. |
| @@ -447,8 +462,14 @@ class ModelEmitter { |
| emitEagerClassInitializations(fragment.libraries); |
| js.LiteralString immediateString = unparse(compiler, immediateCode); |
| + |
| + js.Expression deferredTypes = types == null |
| + ? js.string("[]") |
| + : js.string("[${types.join(",")}]"); |
| + |
| js.ArrayInitializer hunk = |
| - new js.ArrayInitializer([deferredArray, immediateString]); |
| + new js.ArrayInitializer([deferredArray, immediateString, |
| + deferredTypes]); |
| return js.js("$deferredInitializersGlobal[$hash] = #", hunk); |
| } |
| @@ -663,7 +684,7 @@ class ModelEmitter { |
| /// * [DartMethod.optionalParameterDefaultValues] |
| static final String parseFunctionDescriptorBoilerplate = r""" |
| -function parseFunctionDescriptor(proto, name, descriptor) { |
| +function parseFunctionDescriptor(proto, name, descriptor, typesOffset) { |
| if (descriptor instanceof Array) { |
| // 'pos' points to the last read entry. |
| var f, pos = -1; |
| @@ -685,6 +706,9 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| isIntercepted = descriptor[++pos]; |
| tearOffName = descriptor[++pos]; |
| reflectionInfo = descriptor[++pos]; |
| + if (typeof reflectionInfo == "number") { |
| + reflectionInfo = reflectionInfo + typesOffset; |
| + } |
| } |
| // We iterate in blocks of 3 but have to stop before we reach the (optional) |
| @@ -839,19 +863,20 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| // Counter to generate unique names for tear offs. |
| var functionCounter = 0; |
| - function $setupProgramName(program) { |
| + function $setupProgramName(program, typesOffset) { |
| for (var i = 0; i < program.length - 2; i++) { |
| - setupLibrary(program[i]); |
| + setupLibrary(program[i], typesOffset); |
| } |
| setupLazyStatics(program[i]); |
| setupConstants(program[i + 1]); |
| } |
| - function setupLibrary(library) { |
| + function setupLibrary(library, typesOffset) { |
| 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]); |
| + setupStatic(statics[i], holders[holderIndex], statics[i + 2], |
| + typesOffset); |
| } |
| var classes = library[1]; |
| @@ -876,7 +901,7 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| } |
| holdersMap[name] = holders[holderIndex]; |
| - setupClass(name, holders[holderIndex], cls); |
| + setupClass(name, holders[holderIndex], cls, typesOffset); |
| } |
| } |
| @@ -902,7 +927,7 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| } |
| } |
| - function setupStatic(name, holder, descriptor) { |
| + function setupStatic(name, holder, descriptor, typesOffset) { |
| if (typeof descriptor == 'string') { |
| holder[name] = function() { |
| if (descriptor == null) { |
| @@ -918,7 +943,7 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| } else { |
| // Parse the tear off information and generate compile handlers. |
| // TODO(herhut): Share parser with instance methods. |
| - function compileAllStubs() { |
| + function compileAllStubs(typesOffset) { |
| var funs; |
| var fun = compile(name, descriptor[0]); |
| fun[#callName] = descriptor[1]; |
| @@ -936,8 +961,12 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| } |
| if (descriptor[2] != null) { // tear-off name. |
| // functions, reflectionInfo, isStatic, name, isIntercepted. |
| + var reflectionInfo = descriptor[3]; |
| + if (typeof reflectionInfo == "number") { |
| + reflectionInfo = reflectionInfo + typesOffset; |
| + } |
| holder[descriptor[2]] = |
| - tearOff(funs, descriptor[3], true, name, false); |
| + tearOff(funs, reflectionInfo, true, name, false); |
| } |
| if (pos < descriptor.length) { |
| fun[#argumentCount] = descriptor[pos]; |
| @@ -945,25 +974,25 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| } |
| } |
| - function setupCompileAllAndDelegateStub(name) { |
| + function setupCompileAllAndDelegateStub(name, typesOffset) { |
| holder[name] = function() { |
| // The descriptor is null if we already compiled this function. This |
| // happens when we have calls to the static as arguments to the |
| // static: `foo(foo(499))`; |
| if (descriptor != null) { |
| - compileAllStubs(); |
| + compileAllStubs(typesOffset); |
| descriptor = null; // GC the descriptor. |
| } |
| return holder[name].apply(this, arguments); |
| }; |
| } |
| - setupCompileAllAndDelegateStub(name); |
| + setupCompileAllAndDelegateStub(name, typesOffset); |
| for (var pos = 4; pos < descriptor.length; pos += 3) { |
| - setupCompileAllAndDelegateStub(descriptor[pos]); |
| + setupCompileAllAndDelegateStub(descriptor[pos], typesOffset); |
| } |
| if (descriptor[2] != null) { // tear-off name. |
| - setupCompileAllAndDelegateStub(descriptor[2]) |
| + setupCompileAllAndDelegateStub(descriptor[2], typesOffset) |
| } |
| } |
| } |
| @@ -1006,11 +1035,11 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| }; |
| } |
| - function setupClass(name, holder, descriptor) { |
| + function setupClass(name, holder, descriptor, typesOffset) { |
| var patch = function() { |
| if (patch.ensureResolved == patch) { |
| // We have not yet been compiled. |
| - var constructor = compileConstructor(name, descriptor); |
| + var constructor = compileConstructor(name, descriptor, typesOffset); |
| holder[name] = constructor; |
| name = holder = descriptor = null; // GC the captured arguments. |
| // Make sure we can invoke 'ensureResolved' multiple times on the patch |
| @@ -1039,7 +1068,7 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| #parseFunctionDescriptor; |
| - function compileConstructor(name, descriptor) { |
| + function compileConstructor(name, descriptor, typesOffset) { |
| descriptor = compile(name, descriptor); |
| var prototype = determinePrototype(descriptor); |
| var constructor; |
| @@ -1062,7 +1091,8 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| } |
| for (var i = functionsIndex; i < descriptor.length; i += 2) { |
| - parseFunctionDescriptor(prototype, descriptor[i], descriptor[i + 1]); |
| + parseFunctionDescriptor(prototype, descriptor[i], descriptor[i + 1], |
| + typesOffset); |
| } |
| constructor.builtin\$cls = name; // Needed for RTI. |
| @@ -1126,7 +1156,7 @@ function parseFunctionDescriptor(proto, name, descriptor) { |
| } |
| } |
| - $setupProgramName(program); |
| + $setupProgramName(program, 0); |
| // Initialize globals. |
| #embeddedGlobals; |