Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
index 05bf6969af85fecc1d26e07c7f5abbc09f1f6fbb..052b8cf53c1c207a7195eb2935917b9f3b59173d 100644 |
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
@@ -885,29 +885,8 @@ class SwitchCaseJumpHandler extends TargetJumpHandler { |
} |
} |
-class SsaBuilder extends ResolvedVisitor implements Visitor { |
- final SsaBuilderTask builder; |
- final JavaScriptBackend backend; |
- final CodegenWorkItem work; |
- final ConstantSystem constantSystem; |
- HGraph graph; |
- LocalsHandler localsHandler; |
- HInstruction rethrowableException; |
- Map<Element, HInstruction> parameters; |
- final RuntimeTypes rti; |
- HParameterValue lastAddedParameter; |
- |
- Map<TargetElement, JumpHandler> jumpTargets; |
- |
- /** |
- * Variables stored in the current activation. These variables are |
- * being updated in try/catch blocks, and should be |
- * accessed indirectly through [HLocalGet] and [HLocalSet]. |
- */ |
- Map<Element, HLocalValue> activationVariables; |
- |
- // We build the Ssa graph by simulating a stack machine. |
- List<HInstruction> stack; |
+class SsaGraphBuilderMixin { |
+ final HGraph graph = new HGraph(); |
/** |
* The current block to add instructions to. Might be null, if we are |
@@ -931,6 +910,88 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
*/ |
bool isReachable = true; |
+ HBasicBlock get current => _current; |
+ void set current(c) { |
+ isReachable = c != null; |
+ _current = c; |
+ } |
+ |
+ HBasicBlock addNewBlock() { |
+ HBasicBlock block = graph.addNewBlock(); |
+ // If adding a new block during building of an expression, it is due to |
+ // conditional expressions or short-circuit logical operators. |
+ return block; |
+ } |
+ |
+ void open(HBasicBlock block) { |
+ block.open(); |
+ current = block; |
+ lastOpenedBlock = block; |
+ } |
+ |
+ HBasicBlock close(HControlFlow end) { |
+ HBasicBlock result = current; |
+ current.close(end); |
+ current = null; |
+ return result; |
+ } |
+ |
+ HBasicBlock closeAndGotoExit(HControlFlow end) { |
+ HBasicBlock result = current; |
+ current.close(end); |
+ current = null; |
+ result.addSuccessor(graph.exit); |
+ return result; |
+ } |
+ |
+ void goto(HBasicBlock from, HBasicBlock to) { |
+ from.close(new HGoto()); |
+ from.addSuccessor(to); |
+ } |
+ |
+ bool isAborted() { |
+ return _current == null; |
+ } |
+ |
+ /** |
+ * Creates a new block, transitions to it from any current block, and |
+ * opens the new block. |
+ */ |
+ HBasicBlock openNewBlock() { |
+ HBasicBlock newBlock = addNewBlock(); |
+ if (!isAborted()) goto(current, newBlock); |
+ open(newBlock); |
+ return newBlock; |
+ } |
+ |
+ void add(HInstruction instruction) { |
+ current.add(instruction); |
+ } |
+} |
+ |
+class SsaBuilder extends ResolvedVisitor with SsaGraphBuilderMixin { |
+ final SsaBuilderTask builder; |
+ final JavaScriptBackend backend; |
+ final CodegenWorkItem work; |
+ final ConstantSystem constantSystem; |
+ LocalsHandler localsHandler; |
+ HInstruction rethrowableException; |
+ Map<Element, HInstruction> parameters; |
+ final RuntimeTypes rti; |
+ HParameterValue lastAddedParameter; |
+ |
+ Map<TargetElement, JumpHandler> jumpTargets; |
+ |
+ /** |
+ * Variables stored in the current activation. These variables are |
+ * being updated in try/catch blocks, and should be |
+ * accessed indirectly through [HLocalGet] and [HLocalSet]. |
+ */ |
+ Map<Element, HLocalValue> activationVariables; |
+ |
+ // We build the Ssa graph by simulating a stack machine. |
+ List<HInstruction> stack; |
+ |
/** |
* True if we are visiting the expression of a throw expression. |
*/ |
@@ -971,7 +1032,6 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
: this.builder = builder, |
this.backend = builder.backend, |
this.work = work, |
- graph = new HGraph(), |
stack = new List<HInstruction>(), |
activationVariables = new Map<Element, HLocalValue>(), |
jumpTargets = new Map<TargetElement, JumpHandler>(), |
@@ -991,12 +1051,6 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
bool inTryStatement = false; |
int loopNesting = 0; |
- HBasicBlock get current => _current; |
- void set current(c) { |
- isReachable = c != null; |
- _current = c; |
- } |
- |
Constant getConstantForNode(Node node) { |
ConstantHandler handler = compiler.constantHandler; |
Constant constant = elements.getConstant(node); |
@@ -1225,9 +1279,15 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
localsHandler, inTryStatement); |
inTryStatement = false; |
LocalsHandler newLocalsHandler = new LocalsHandler(this); |
- newLocalsHandler.closureData = |
- compiler.closureToClassMapper.computeClosureToClassMapping( |
- function, function.parseNode(compiler), elements); |
+ if (function.hasIrNode(compiler)) { |
+ // TODO(lry): handle ir functions with nested closure definitions. |
+ newLocalsHandler.closureData = |
+ new ClosureClassMap(null, null, null, new ThisElement(function)); |
+ } else { |
+ newLocalsHandler.closureData = |
+ compiler.closureToClassMapper.computeClosureToClassMapping( |
+ function, function.parseNode(compiler), elements); |
+ } |
int argumentIndex = 0; |
if (isInstanceMember) { |
newLocalsHandler.updateLocal(newLocalsHandler.closureData.thisElement, |
@@ -1350,7 +1410,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
return true; |
} |
- bool heuristicSayGoodToGo(FunctionExpression functionExpression) { |
+ bool heuristicSayGoodToGo(bool canBeInlined(int maxNodes)) { |
// Don't inline recursivly |
if (inliningStack.any((entry) => entry.function == function)) { |
return false; |
@@ -1371,17 +1431,16 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + |
InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; |
} |
- bool canBeInlined = InlineWeeder.canBeInlined( |
- functionExpression, maxInliningNodes); |
- if (canBeInlined) { |
+ bool canInline = canBeInlined(maxInliningNodes); |
+ if (canInline) { |
backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); |
} else { |
backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); |
} |
- return canBeInlined; |
+ return canInline; |
} |
- void doInlining(FunctionExpression functionExpression) { |
+ void doInlining(void visitBody()) { |
// Add an explicit null check on the receiver before doing the |
// inlining. We use [element] to get the same name in the |
// NoSuchMethodError message as if we had called it. |
@@ -1407,7 +1466,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
if (element.isGenerativeConstructor()) { |
buildFactory(element); |
} else { |
- functionExpression.body.accept(this); |
+ visitBody(); |
} |
removeInlinedInstantiation(instantiatedType); |
}); |
@@ -1415,11 +1474,21 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
} |
if (meetsHardConstraints()) { |
- FunctionExpression functionExpression = function.parseNode(compiler); |
- |
- if (heuristicSayGoodToGo(functionExpression)) { |
- doInlining(functionExpression); |
- return true; |
+ if (function.hasIrNode(compiler)) { |
+ IrFunction irFunction = function.irNode(compiler); |
+ bool canInline(int n) => IrInlineWeeder.canBeInlined(irFunction, n); |
+ if (heuristicSayGoodToGo(canInline)) { |
+ SsaFromIrInliner irInliner = new SsaFromIrInliner(this); |
+ doInlining(() => irInliner.visitAll(irFunction.statements)); |
+ return true; |
+ } |
+ } else { |
+ FunctionExpression functionNode = function.parseNode(compiler); |
+ bool canInline(int n) => InlineWeeder.canBeInlined(functionNode, n); |
+ if (heuristicSayGoodToGo(canInline)) { |
+ doInlining(() => functionNode.body.accept(this)); |
+ return true; |
+ } |
} |
} |
@@ -2047,58 +2116,6 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
return graph; |
} |
- HBasicBlock addNewBlock() { |
- HBasicBlock block = graph.addNewBlock(); |
- // If adding a new block during building of an expression, it is due to |
- // conditional expressions or short-circuit logical operators. |
- return block; |
- } |
- |
- void open(HBasicBlock block) { |
- block.open(); |
- current = block; |
- lastOpenedBlock = block; |
- } |
- |
- HBasicBlock close(HControlFlow end) { |
- HBasicBlock result = current; |
- current.close(end); |
- current = null; |
- return result; |
- } |
- |
- HBasicBlock closeAndGotoExit(HControlFlow end) { |
- HBasicBlock result = current; |
- current.close(end); |
- current = null; |
- result.addSuccessor(graph.exit); |
- return result; |
- } |
- |
- void goto(HBasicBlock from, HBasicBlock to) { |
- from.close(new HGoto()); |
- from.addSuccessor(to); |
- } |
- |
- bool isAborted() { |
- return _current == null; |
- } |
- |
- /** |
- * Creates a new block, transitions to it from any current block, and |
- * opens the new block. |
- */ |
- HBasicBlock openNewBlock() { |
- HBasicBlock newBlock = addNewBlock(); |
- if (!isAborted()) goto(current, newBlock); |
- open(newBlock); |
- return newBlock; |
- } |
- |
- void add(HInstruction instruction) { |
- current.add(instruction); |
- } |
- |
void addWithPosition(HInstruction instruction, Node node) { |
add(attachPosition(instruction, node)); |
} |
@@ -2155,7 +2172,8 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
} |
Script script = element.getCompilationUnit().script; |
SourceFile sourceFile = script.file; |
- SourceFileLocation location = new SourceFileLocation(sourceFile, token); |
+ SourceFileLocation location = |
+ new TokenSourceFileLocation(sourceFile, token); |
if (!location.isValid()) { |
throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( |
{'offset': token.charOffset, |