dart2js: create constants lazily in the new emitter.

R=zarah@google.com

Review URL: https://codereview.chromium.org//952973004

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@44326 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
floitsch@google.com 2015-03-09 16:37:01 +00:00
parent 6e539eab53
commit 028b1d45b7

View file

@ -118,8 +118,8 @@ class ModelEmitter {
if (isConstantInlinedOrAlreadyEmitted(value)) { if (isConstantInlinedOrAlreadyEmitted(value)) {
return constantEmitter.generate(value); return constantEmitter.generate(value);
} }
return js.js('#.#', [namer.globalObjectForConstant(value), return js.js('#.#()', [namer.globalObjectForConstant(value),
namer.constantName(value)]); namer.constantName(value)]);
} }
int emitProgram(Program program) { int emitProgram(Program program) {
@ -154,6 +154,11 @@ class ModelEmitter {
js.LiteralString unparse(Compiler compiler, js.Node value) { js.LiteralString unparse(Compiler compiler, js.Node value) {
String text = js.prettyPrint(value, compiler).getText(); String text = js.prettyPrint(value, compiler).getText();
if (value is js.Fun) text = '($text)'; if (value is js.Fun) text = '($text)';
if (value is js.LiteralExpression &&
(value.template.startsWith("function ") ||
value.template.startsWith("{"))) {
text = '($text)';
}
return js.js.escapedString(text); return js.js.escapedString(text);
} }
@ -168,6 +173,8 @@ class ModelEmitter {
List<js.Expression> elements = fragment.libraries.map(emitLibrary).toList(); List<js.Expression> elements = fragment.libraries.map(emitLibrary).toList();
elements.add( elements.add(
emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields)); emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields));
elements.add(emitConstants(fragment.constants));
js.Expression code = new js.ArrayInitializer(elements); js.Expression code = new js.ArrayInitializer(elements);
@ -185,7 +192,6 @@ class ModelEmitter {
backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()),
'outputContainsConstantList': program.outputContainsConstantList, 'outputContainsConstantList': program.outputContainsConstantList,
'embeddedGlobals': emitEmbeddedGlobals(program), 'embeddedGlobals': emitEmbeddedGlobals(program),
'constants': emitConstants(fragment.constants),
'staticNonFinals': 'staticNonFinals':
emitStaticNonFinalFields(fragment.staticNonFinalFields), emitStaticNonFinalFields(fragment.staticNonFinalFields),
'operatorIsPrefix': js.string(namer.operatorIsPrefix), 'operatorIsPrefix': js.string(namer.operatorIsPrefix),
@ -431,16 +437,14 @@ class ModelEmitter {
deferredCode.add( deferredCode.add(
emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields)); emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields));
deferredCode.add(emitConstants(fragment.constants));
js.ArrayInitializer deferredArray = new js.ArrayInitializer(deferredCode); js.ArrayInitializer deferredArray = new js.ArrayInitializer(deferredCode);
// This is the code that must be evaluated after all deferred classes have // This is the code that must be evaluated after all deferred classes have
// been setup. // been setup.
js.Statement immediateCode = js.js.statement('''{ js.Statement immediateCode =
#constants; emitEagerClassInitializations(fragment.libraries);
#eagerClasses;
}''',
{'constants': emitConstants(fragment.constants),
'eagerClasses': emitEagerClassInitializations(fragment.libraries)});
js.LiteralString immediateString = unparse(compiler, immediateCode); js.LiteralString immediateString = unparse(compiler, immediateCode);
js.ArrayInitializer hunk = js.ArrayInitializer hunk =
@ -449,13 +453,25 @@ class ModelEmitter {
return js.js("$deferredInitializersGlobal[$hash] = #", hunk); return js.js("$deferredInitializersGlobal[$hash] = #", hunk);
} }
js.Block emitConstants(List<Constant> constants) { // This string should be referenced wherever JavaScript code makes assumptions
Iterable<js.Statement> statements = constants.map((Constant constant) { // on the constants format.
js.Expression code = constantEmitter.generate(constant.value); static final String constantsDescription =
return js.js.statement("#.# = #;", "The constants are encoded as a follows:"
[constant.holder.name, constant.name, code]); " [constantsHolderIndex, name, code, name2, code2, ...]."
}); "The array is completely empty if there is no constant at all.";
return new js.Block(statements.toList());
js.ArrayInitializer emitConstants(List<Constant> constants) {
List<js.Expression> data = <js.Expression>[];
if (constants.isNotEmpty) {
int holderIndex = constants.first.holder.index;
data.add(js.number(holderIndex));
data.addAll(constants.expand((Constant constant) {
assert(constant.holder.index == holderIndex);
js.Expression code = constantEmitter.generate(constant.value);
return [js.string(constant.name), unparse(compiler, code)];
}));
}
return new js.ArrayInitializer(data);
} }
js.Block emitStaticNonFinalFields(List<StaticField> fields) { js.Block emitStaticNonFinalFields(List<StaticField> fields) {
@ -824,10 +840,11 @@ function parseFunctionDescriptor(proto, name, descriptor) {
var functionCounter = 0; var functionCounter = 0;
function $setupProgramName(program) { function $setupProgramName(program) {
for (var i = 0; i < program.length - 1; i++) { for (var i = 0; i < program.length - 2; i++) {
setupLibrary(program[i]); setupLibrary(program[i]);
} }
setupLazyStatics(program[i]); setupLazyStatics(program[i]);
setupConstants(program[i + 1]);
} }
function setupLibrary(library) { function setupLibrary(library) {
@ -873,6 +890,18 @@ function parseFunctionDescriptor(proto, name, descriptor) {
} }
} }
function setupConstants(constants) {
// $constantsDescription.
if (constants.length == 0) return;
// We assume that all constants are in the same holder.
var holder = holders[constants[0]];
for (var i = 1; i < constants.length; i += 2) {
var name = constants[i];
var initializer = constants[i + 1];
setupConstant(name, holder, initializer);
}
}
function setupStatic(name, holder, descriptor) { function setupStatic(name, holder, descriptor) {
if (typeof descriptor == 'string') { if (typeof descriptor == 'string') {
holder[name] = function() { holder[name] = function() {
@ -957,12 +986,26 @@ function parseFunctionDescriptor(proto, name, descriptor) {
// initialization failed. // initialization failed.
holder[name] = null; holder[name] = null;
} }
// TODO(floitsch): the function should probably be unique for each
// static.
holder[getterName] = function() { return this[name]; }; holder[getterName] = function() { return this[name]; };
} }
return result; return result;
}; };
} }
function setupConstant(name, holder, descriptor) {
var c;
holder[name] = function() {
if (descriptor !== null) {
c = compile(name, descriptor);
name = null;
descriptor = null;
}
return c;
};
}
function setupClass(name, holder, descriptor) { function setupClass(name, holder, descriptor) {
var patch = function() { var patch = function() {
if (patch.ensureResolved == patch) { if (patch.ensureResolved == patch) {
@ -1085,9 +1128,6 @@ function parseFunctionDescriptor(proto, name, descriptor) {
$setupProgramName(program); $setupProgramName(program);
// Initialize constants.
#constants;
// Initialize globals. // Initialize globals.
#embeddedGlobals; #embeddedGlobals;