dart2js: Construct the entire output as a single AST before printing.

BUG=
R=floitsch@google.com, sra@google.com

Review URL: https://codereview.chromium.org//1140703006
This commit is contained in:
Stephan Herhut 2015-05-20 12:31:31 +02:00
parent 6f6521ccb8
commit 03917ffe4d
9 changed files with 469 additions and 458 deletions

View file

@ -296,11 +296,11 @@ class ConstantEmitter
backend.classNeedsRti(type.element)) {
InterfaceType interface = type;
RuntimeTypes rti = backend.rti;
Iterable<String> arguments = interface.typeArguments
Iterable<jsAst.Expression> arguments = interface.typeArguments
.map((DartType type) =>
rti.getTypeRepresentationWithHashes(type, (_){}));
rti.getTypeRepresentationWithPlaceholders(type, (_){}));
jsAst.Expression argumentList =
new jsAst.LiteralString('[${arguments.join(', ')}]');
new jsAst.ArrayInitializer(arguments.toList());
return new jsAst.Call(getHelperProperty(backend.getSetRuntimeTypeInfo()),
[value, argumentList]);
}

View file

@ -550,15 +550,16 @@ class RuntimeTypes {
}
}
String getTypeRepresentationWithHashes(DartType type,
OnVariableCallback onVariable) {
jsAst.Expression getTypeRepresentationWithPlaceholders(DartType type,
OnVariableCallback onVariable) {
// Create a type representation. For type variables call the original
// callback for side effects and return a template placeholder.
int positions = 0;
jsAst.Expression representation = getTypeRepresentation(type, (variable) {
onVariable(variable);
return new jsAst.LiteralString('#');
return new jsAst.InterpolatedExpression(positions++);
});
return jsAst.prettyPrint(representation, compiler).buffer.toString();
return representation;
}
jsAst.Expression getTypeRepresentation(

File diff suppressed because it is too large Load diff

View file

@ -13,35 +13,40 @@ class InterceptorEmitter extends CodeEmitterHelper {
}
}
void emitGetInterceptorMethod(CodeOutput output,
String key,
Set<ClassElement> classes) {
jsAst.Expression buildGetInterceptorMethod(String key,
Set<ClassElement> classes) {
InterceptorStubGenerator stubGenerator =
new InterceptorStubGenerator(compiler, namer, backend);
jsAst.Expression function =
stubGenerator.generateGetInterceptorMethod(classes);
output.addBuffer(jsAst.prettyPrint(
js('${namer.globalObjectFor(backend.interceptorsLibrary)}.# = #',
[key, function]),
compiler));
output.add(N);
return function;
}
/**
* Emit all versions of the [:getInterceptor:] method.
*/
void emitGetInterceptorMethods(CodeOutput output) {
emitter.addComment('getInterceptor methods', output);
jsAst.Statement buildGetInterceptorMethods() {
List<jsAst.Statement> parts = <jsAst.Statement>[];
parts.add(js.comment('getInterceptor methods'));
Map<String, Set<ClassElement>> specializedGetInterceptors =
backend.specializedGetInterceptors;
for (String name in specializedGetInterceptors.keys.toList()..sort()) {
Set<ClassElement> classes = specializedGetInterceptors[name];
emitGetInterceptorMethod(output, name, classes);
parts.add(
js.statement('#.# = #',
[namer.globalObjectFor(backend.interceptorsLibrary),
name,
buildGetInterceptorMethod(name, classes)]));
}
return new jsAst.Block(parts);
}
void emitOneShotInterceptors(CodeOutput output) {
jsAst.Statement buildOneShotInterceptors() {
List<jsAst.Statement> parts = <jsAst.Statement>[];
List<String> names = backend.oneShotInterceptors.keys.toList();
names.sort();
@ -51,12 +56,10 @@ class InterceptorEmitter extends CodeEmitterHelper {
for (String name in names) {
jsAst.Expression function =
stubGenerator.generateOneShotInterceptor(name);
jsAst.Expression assignment =
js('${globalObject}.# = #', [name, function]);
output.addBuffer(jsAst.prettyPrint(assignment, compiler));
output.add(N);
parts.add(js.statement('${globalObject}.# = #', [name, function]));
}
return new jsAst.Block(parts);
}
/**
@ -87,15 +90,12 @@ class InterceptorEmitter extends CodeEmitterHelper {
* `findInterceptorForType`. See declaration of `typeToInterceptor` in
* `interceptors.dart`.
*/
void emitTypeToInterceptorMap(Program program, CodeOutput output) {
jsAst.Statement buildTypeToInterceptorMap(Program program) {
jsAst.Expression array = program.typeToInterceptorMap;
if (array == null) return;
if (array == null) return js.comment("Empty type-to-interceptor map.");
jsAst.Expression typeToInterceptorMap = emitter
.generateEmbeddedGlobalAccess(embeddedNames.TYPE_TO_INTERCEPTOR_MAP);
jsAst.Expression assignment = js('# = #', [typeToInterceptorMap, array]);
output.addBuffer(jsAst.prettyPrint(assignment, compiler));
output.add(N);
return js.statement('# = #', [typeToInterceptorMap, array]);
}
}

View file

@ -3559,17 +3559,17 @@ class SsaBuilder extends NewResolvedVisitor {
InterfaceType interface = type;
List<HInstruction> inputs = <HInstruction>[];
bool first = true;
List<String> templates = <String>[];
List<js.Expression> templates = <js.Expression>[];
for (DartType argument in interface.typeArguments) {
templates.add(rti.getTypeRepresentationWithHashes(argument, (variable) {
templates.add(rti.getTypeRepresentationWithPlaceholders(argument, (variable) {
HInstruction runtimeType = addTypeVariableReference(variable);
inputs.add(runtimeType);
}));
}
String template = '[${templates.join(', ')}]';
// TODO(sra): This is a fresh template each time. We can't let the
// template manager build them.
js.Template code = js.js.uncachedExpressionTemplate(template);
js.Template code = new js.Template(null,
new js.ArrayInitializer(templates));
HInstruction representation =
new HForeignCode(code, backend.readableArrayType, inputs,
nativeBehavior: native.NativeBehavior.PURE_ALLOCATION);
@ -4618,11 +4618,12 @@ class SsaBuilder extends NewResolvedVisitor {
List<HInstruction> inputs = <HInstruction>[];
String template = rti.getTypeRepresentationWithHashes(argument, (variable) {
inputs.add(addTypeVariableReference(variable));
});
js.Expression template =
rti.getTypeRepresentationWithPlaceholders(argument, (variable) {
inputs.add(addTypeVariableReference(variable));
});
js.Template code = js.js.uncachedExpressionTemplate(template);
js.Template code = new js.Template(null, template);
HInstruction result = new HForeignCode(code, backend.stringType, inputs,
nativeBehavior: native.NativeBehavior.PURE);
add(result);

View file

@ -130,7 +130,6 @@ Future<Compiler> reuseCompiler(
backend.emitter.oldEmitter
..outputBuffers.clear()
..isolateProperties = null
..classesCollector = null
..mangledFieldNames.clear()
..mangledGlobalFieldNames.clear()

View file

@ -329,8 +329,6 @@ class JsBuilder {
/// [escapedString].
LiteralString string(String value) => new LiteralString('"$value"');
LiteralString name(String name) => new LiteralString(name);
LiteralNumber number(num value) => new LiteralNumber('$value');
LiteralBool boolean(bool value) => new LiteralBool(value);

View file

@ -1156,9 +1156,13 @@ class OrderedSet<T> {
// separate pass because JS vars are lifted to the top of the function.
class VarCollector extends BaseVisitor {
bool nested;
bool enableRenaming = true;
final OrderedSet<String> vars;
final OrderedSet<String> params;
static final String disableVariableMinificationPattern = "::norenaming::";
static final String enableVariableMinificationPattern = "::dorenaming::";
VarCollector() : nested = false,
vars = new OrderedSet<String>(),
params = new OrderedSet<String>();
@ -1195,8 +1199,16 @@ class VarCollector extends BaseVisitor {
void visitThis(This node) {}
void visitComment(Comment node) {
if (node.comment.contains(disableVariableMinificationPattern)) {
enableRenaming = false;
} else if (node.comment.contains(enableVariableMinificationPattern)) {
enableRenaming = true;
}
}
void visitVariableDeclaration(VariableDeclaration decl) {
if (decl.allowRename) vars.add(decl.name);
if (enableRenaming && decl.allowRename) vars.add(decl.name);
}
}

View file

@ -56,6 +56,7 @@ class Template {
Template(this.source, this.ast,
{this.isExpression: true, this.forceCopy: false}) {
assert(this.isExpression ? ast is Expression : ast is Statement);
_compile();
}