blob: e88f130373455efb204c7e04d95d04dca3a19f66 [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of ssa;
/**
* This class implements an [IrNodesVisitor] that inlines a function represented
* as IR into an [SsaFromAstBuilder].
*/
class SsaFromIrInliner extends IrNodesVisitor with
SsaBuilderMixin<IrNode>,
SsaFromIrMixin,
SsaBuilderDelegate<IrNode, Node> {
final SsaFromAstBuilder builder;
SsaFromIrInliner.internal(this.builder);
factory SsaFromIrInliner(SsaFromAstBuilder builder,
FunctionElement function,
List<HInstruction> compiledArguments) {
SsaFromIrInliner irInliner = new SsaFromIrInliner.internal(builder);
irInliner.setupStateForInlining(function, compiledArguments);
return irInliner;
}
final List<IrExpression> inlinedCalls = <IrExpression>[];
/**
* This function is invoked when we are currently inlining an IR function
* into an AST builder, and we encounter an infocation that is inlined.
*/
void enterInlinedMethod(FunctionElement function,
IrNode callNode,
List<HInstruction> compiledArguments) {
assert(callNode != null);
inlinedCalls.add(callNode);
builder.enterInlinedMethod(function, null, compiledArguments);
}
void leaveInlinedMethod() {
builder.leaveInlinedMethod();
// [leaveInlinedMethod] pushes the returned value on the builder's stack,
// no matter if the inlined function is represented in AST or IR.
emitted[inlinedCalls.removeLast()] = builder.pop();
}
void doInline(FunctionElement function) {
builder.doInline(function);
}
void emitReturn(HInstruction value, IrReturn node) {
builder.localsHandler.updateLocal(builder.returnElement, value);
}
}
class IrInlineWeeder extends IrNodesVisitor {
static bool canBeInlined(IrFunction irFunction,
int maxInliningNodes,
bool useMaxInliningNodes) {
IrInlineWeeder weeder =
new IrInlineWeeder(maxInliningNodes, useMaxInliningNodes);
weeder.visitAll(irFunction.statements);
return !weeder.tooDifficult;
}
final int maxInliningNodes;
final bool useMaxInliningNodes;
IrInlineWeeder(this.maxInliningNodes, this.useMaxInliningNodes);
bool seenReturn = false;
bool tooDifficult = false;
int nodeCount = 0;
bool registerNode() {
if (!useMaxInliningNodes) return true;
if (nodeCount++ > maxInliningNodes) {
tooDifficult = true;
return false;
} else {
return true;
}
}
void visitIrNode(IrNode node) {
if (!registerNode()) return;
if (seenReturn) {
tooDifficult = true;
}
}
void visitIrReturn(IrReturn node) {
visitIrNode(node);
seenReturn = true;
}
void visitIrFunction(IrFunction node) {
tooDifficult = true;
}
}