Inline generative constructor calls.
R=kasperl@google.com
Review URL: https://codereview.chromium.org//15739005
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@23017 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 1affd60..ae43bed 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -103,10 +103,7 @@
}
HGraph compileConstructor(SsaBuilder builder, CodegenWorkItem work) {
- // The body of the constructor will be generated in a separate function.
- final ClassElement classElement = work.element.getEnclosingClass();
- return builder.buildFactory(classElement.implementation,
- work.element.implementation);
+ return builder.buildFactory(work.element);
}
}
@@ -279,8 +276,7 @@
builder.graph.thisInstruction = thisInstruction;
builder.graph.entry.addAtEntry(thisInstruction);
updateLocal(closureData.closureElement, thisInstruction);
- } else if (element.isInstanceMember()
- || element.isGenerativeConstructor()) {
+ } else if (element.isInstanceMember()) {
// Once closures have been mapped to classes their instance members might
// not have any thisElement if the closure was created inside a static
// context.
@@ -1117,6 +1113,7 @@
}
HParameterValue addParameter(Element element) {
+ assert(inliningStack.isEmpty);
HParameterValue result = new HParameterValue(element);
if (lastAddedParameter == null) {
graph.entry.addBefore(graph.entry.first, result);
@@ -1179,7 +1176,7 @@
// may have an impact on the state of the current method.
InliningState state = new InliningState(
function, returnElement, returnType, elements, stack, localsHandler);
- LocalsHandler newLocalsHandler = new LocalsHandler.from(localsHandler);
+ LocalsHandler newLocalsHandler = new LocalsHandler(this);
newLocalsHandler.closureData =
compiler.closureToClassMapper.computeClosureToClassMapping(
function, function.parseNode(compiler), elements);
@@ -1273,7 +1270,6 @@
if (element is !PartialFunctionElement) return false;
// TODO(ngeoffray): try to inline generative constructors. They
// don't have any body, which make it more difficult.
- if (element.isGenerativeConstructor()) return false;
if (inliningStack.length > MAX_INLINING_DEPTH) return false;
// Don't inline recursive calls. We use the same elements for the inlined
// functions and would thus clobber our local variables.
@@ -1331,7 +1327,9 @@
InliningState state = enterInlinedMethod(
function, selector, argumentsNodes, providedArguments, currentNode);
inlinedFrom(element, () {
- functionExpression.body.accept(this);
+ element.isGenerativeConstructor()
+ ? buildFactory(element)
+ : functionExpression.body.accept(this);
});
leaveInlinedMethod(state);
return true;
@@ -1437,11 +1435,6 @@
ClosureClassMap newClosureData =
compiler.closureToClassMapper.computeClosureToClassMapping(
constructor, node, elements);
- // The [:this:] element now refers to the one in the new closure
- // data, that is the [:this:] of the super constructor. We
- // update the element to refer to the current [:this:].
- localsHandler.updateLocal(newClosureData.thisElement,
- localsHandler.readThis());
localsHandler.closureData = newClosureData;
params.orderedForEachParameter((Element parameterElement) {
@@ -1577,21 +1570,20 @@
* to, starting from the current constructor.
* - Call the the constructor bodies, starting from the constructor(s) in the
* super class(es).
- *
- * Invariant: Both [classElement] and [functionElement] must be
- * implementation elements.
*/
- HGraph buildFactory(ClassElement classElement,
- FunctionElement functionElement) {
- assert(invariant(classElement, classElement.isImplementation));
- assert(invariant(functionElement, functionElement.isImplementation));
+ HGraph buildFactory(FunctionElement functionElement) {
+ functionElement = functionElement.implementation;
+ ClassElement classElement =
+ functionElement.getEnclosingClass().implementation;
FunctionExpression function = functionElement.parseNode(compiler);
// Note that constructors (like any other static function) do not need
// to deal with optional arguments. It is the callers job to provide all
// arguments as if they were positional.
- // The initializer list could contain closures.
- openFunction(functionElement, function);
+ if (inliningStack.isEmpty) {
+ // The initializer list could contain closures.
+ openFunction(functionElement, function);
+ }
Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>();
@@ -1699,8 +1691,13 @@
invoke.sideEffects = compiler.world.getSideEffectsOfElement(constructor);
add(invoke);
}
- closeAndGotoExit(new HReturn(newObject));
- return closeFunction();
+ if (inliningStack.isEmpty) {
+ closeAndGotoExit(new HReturn(newObject));
+ return closeFunction();
+ } else {
+ localsHandler.updateLocal(returnElement, newObject);
+ return null;
+ }
}
void addParameterCheckInstruction(Element element) {
@@ -5058,6 +5055,7 @@
static bool canBeInlined(FunctionExpression functionExpression,
TreeElements elements) {
InlineWeeder weeder = new InlineWeeder(elements);
+ weeder.visit(functionExpression.initializers);
weeder.visit(functionExpression.body);
if (weeder.tooDifficult) return false;
return true;
@@ -5073,7 +5071,7 @@
}
void visit(Node node) {
- node.accept(this);
+ if (node != null) node.accept(this);
}
void visitNode(Node node) {