Index: lib/compiler/implementation/ssa/codegen.dart |
diff --git a/lib/compiler/implementation/ssa/codegen.dart b/lib/compiler/implementation/ssa/codegen.dart |
index fccab573d47b1e3f9db95a59e5a131da30696344..27968fe1d02a178b078afe851f24b767b242f6bf 100644 |
--- a/lib/compiler/implementation/ssa/codegen.dart |
+++ b/lib/compiler/implementation/ssa/codegen.dart |
@@ -60,7 +60,7 @@ class SsaCodeGeneratorTask extends CompilerTask { |
typedef void ElementAction(Element element); |
-class SsaCodeGenerator implements HVisitor { |
+class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
/** |
* Current state for generating simple (non-local-control) code. |
* It is generated as either statements (indented and ';'-terminated), |
@@ -393,7 +393,114 @@ class SsaCodeGenerator implements HVisitor { |
buffer.add(";\n"); |
} |
- void handleLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
+ bool visitIfInfo(HIfBlockInformation info) { |
+ return false; |
+ } |
+ |
+ bool visitAndOrInfo(HAndOrBlockInformation info) { |
+ return false; |
+ } |
+ |
+ bool visitLoopInfo(HLoopInformation info) { |
+ bool success = false; |
+ SubExpression condition = info.condition; |
+ void visitBodyIgnoreLabels() { |
+ if (info.body.start.isLabeledBlock()) { |
+ HBlockInformation oldInfo = currentBlockInformation; |
+ currentBlockInformation = info.body.start.blockInformation; |
+ visitSubGraph(info.body); |
+ currentBlockInformation = oldInfo; |
+ } else { |
+ visitSubGraph(info.body); |
+ } |
+ } |
+ if (isCondition(condition)) { |
floitsch
2012/04/16 13:26:07
I would prefer bailing out here.
if (!isCondition
Lasse Reichstein Nielsen
2012/04/17 12:58:22
Done.
|
+ switch (info.type) { |
floitsch
2012/04/16 13:26:07
I would prefer 'kind' instead of 'type'.
Lasse Reichstein Nielsen
2012/04/17 12:58:22
Done.
|
+ case HLoopInformation.WHILE_LOOP: |
+ case HLoopInformation.FOR_IN_LOOP: { |
floitsch
2012/04/16 13:26:07
Afaics there is almost no difference between while
Lasse Reichstein Nielsen
2012/04/17 12:58:22
It can have an update block that isn't just phis.
|
+ addIndentation(); |
+ for (LabelElement label in info.labels) { |
+ writeLabel(label); |
+ buffer.add(":"); |
+ } |
+ bool inlineUpdates = |
+ info.updates !== null && isExpression(info.updates); |
+ if (inlineUpdates) { |
+ buffer.add("for (; "); |
+ visitConditionGraph(condition); |
+ buffer.add("; "); |
+ visitExpressionGraph(info.updates); |
+ buffer.add(") {\n"); |
+ indent++; |
+ // The body might be labeled. Ignore this when recursing on the |
+ // subgraph. |
+ // TODO(lrn): Remove this extra labeling when handling all loops |
+ // using subgraphs. |
+ visitBodyIgnoreLabels(); |
+ |
+ indent--; |
+ } else { |
+ buffer.add("while ("); |
+ visitConditionGraph(condition); |
+ buffer.add(") {\n"); |
+ indent++; |
+ wrapLoopBodyForContinue(info); |
+ if (info.updates !== null) visitSubGraph(info.updates); |
+ indent--; |
+ } |
+ addIndentation(); |
+ buffer.add("}\n"); |
+ success = true; |
+ break; |
+ } |
+ case HLoopInformation.FOR_LOOP: { |
+ // TODO(lrn): Find a way to put initialization into the for. |
+ // It's currently handled before we reach the [HLoopInformation]. |
+ addIndentation(); |
+ for (LabelElement label in info.labels) { |
+ if (label.isTarget) { |
+ writeLabel(label); |
+ buffer.add(":"); |
+ } |
+ } |
+ buffer.add("for(;"); |
+ visitConditionGraph(info.condition); |
+ buffer.add(";"); |
+ if (isExpression(info.updates)) { |
+ visitExpressionGraph(info.updates); |
+ buffer.add(") {\n"); |
+ indent++; |
+ |
+ visitBodyIgnoreLabels(); |
+ |
+ indent--; |
+ addIndentation(); |
+ buffer.add("}\n"); |
+ } else { |
+ addIndentation(); |
+ buffer.add(") {\n"); |
+ indent++; |
+ wrapLoopBodyForContinue(info); |
+ visitSubGraph(info.updates); |
+ indent--; |
+ buffer.add("}\n"); |
+ } |
+ success = true; |
+ break; |
+ } |
+ case HLoopInformation.DO_WHILE_LOOP: |
+ // Currently unhandled. |
floitsch
2012/04/16 13:26:07
We don't have fall-throughs. Why didn't this throu
Lasse Reichstein Nielsen
2012/04/17 12:58:22
It's an empty case, so it's joined with the follow
|
+ default: |
floitsch
2012/04/16 13:26:07
Is default an internal error?
Lasse Reichstein Nielsen
2012/04/17 12:58:22
Probably, yes. I'll make it an internal error, and
|
+ } |
+ } |
+ if (success) { |
floitsch
2012/04/16 13:26:07
Unless wrong you can merge while, for-in and for.
Lasse Reichstein Nielsen
2012/04/17 12:58:22
I'll keep it here, but without the if (I'll return
|
+ visitBasicBlock(info.joinBlock); |
+ return true; |
+ } |
+ return false; |
+ } |
+ |
+ bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) { |
addIndentation(); |
Link<Element> continueOverrides = const EmptyLink<Element>(); |
// If [labeledBlockInfo.isContinue], the block is an artificial |
@@ -454,6 +561,7 @@ class SsaCodeGenerator implements HVisitor { |
} else { |
breakAction.remove(labeledBlockInfo.target); |
} |
+ return true; |
} |
void emitLogicalOperation(HPhi node, String operation) { |
@@ -499,99 +607,6 @@ class SsaCodeGenerator implements HVisitor { |
} |
} |
- bool handleLoop(HBasicBlock node) { |
- bool success = false; |
- assert(node.isLoopHeader()); |
- HLoopInformation info = node.loopInformation; |
- SubExpression condition = info.condition; |
- if (isCondition(condition)) { |
- switch (info.type) { |
- case HLoopInformation.WHILE_LOOP: |
- case HLoopInformation.FOR_IN_LOOP: { |
- addIndentation(); |
- for (LabelElement label in info.labels) { |
- writeLabel(label); |
- buffer.add(":"); |
- } |
- bool inlineUpdates = |
- info.updates !== null && isExpression(info.updates); |
- if (inlineUpdates) { |
- buffer.add("for (; "); |
- visitConditionGraph(condition); |
- buffer.add("; "); |
- visitExpressionGraph(info.updates); |
- buffer.add(") {\n"); |
- indent++; |
- // The body might be labeled. Ignore this when recursing on the |
- // subgraph. |
- // TODO(lrn): Remove this extra labeling when handling all loops |
- // using subgraphs. |
- HBlockInformation oldInfo = currentBlockInformation; |
- currentBlockInformation = info.body.start.labeledBlockInformation; |
- visitSubGraph(info.body); |
- currentBlockInformation = oldInfo; |
- |
- indent--; |
- } else { |
- buffer.add("while ("); |
- visitConditionGraph(condition); |
- buffer.add(") {\n"); |
- indent++; |
- wrapLoopBodyForContinue(info); |
- if (info.updates !== null) visitSubGraph(info.updates); |
- indent--; |
- } |
- addIndentation(); |
- buffer.add("}\n"); |
- success = true; |
- break; |
- } |
- case HLoopInformation.FOR_LOOP: { |
- // TODO(lrn): Find a way to put initialization into the for. |
- // It's currently handled before we reach the [HLoopInformation]. |
- addIndentation(); |
- for (LabelElement label in info.labels) { |
- if (label.isTarget) { |
- writeLabel(label); |
- buffer.add(":"); |
- } |
- } |
- buffer.add("for(;"); |
- visitConditionGraph(info.condition); |
- buffer.add(";"); |
- if (isExpression(info.updates)) { |
- visitExpressionGraph(info.updates); |
- buffer.add(") {\n"); |
- indent++; |
- |
- HBlockInformation oldInfo = currentBlockInformation; |
- currentBlockInformation = info.body.start.labeledBlockInformation; |
- visitSubGraph(info.body); |
- currentBlockInformation = oldInfo; |
- |
- indent--; |
- addIndentation(); |
- buffer.add("}\n"); |
- } else { |
- addIndentation(); |
- buffer.add(") {\n"); |
- indent++; |
- wrapLoopBodyForContinue(info); |
- visitSubGraph(info.updates); |
- indent--; |
- buffer.add("}\n"); |
- } |
- success = true; |
- break; |
- } |
- case HLoopInformation.DO_WHILE_LOOP: |
- // Currently unhandled. |
- default: |
- } |
- } |
- return success; |
- } |
- |
void visitBasicBlock(HBasicBlock node) { |
// Abort traversal if we are leaving the currently active sub-graph. |
if (!subGraph.contains(node)) return; |
@@ -600,28 +615,20 @@ class SsaCodeGenerator implements HVisitor { |
// If we reach here again while handling the attached information, |
// e.g., because we call visitSubGraph on a subgraph starting here, |
// don't handle it again. |
- if (node.hasLabeledBlockInformation() && |
- node.labeledBlockInformation !== currentBlockInformation) { |
+ if (node.blockInformation !== null && |
+ node.blockInformation !== currentBlockInformation) { |
HBlockInformation oldBlockInformation = currentBlockInformation; |
- currentBlockInformation = node.labeledBlockInformation; |
- handleLabeledBlock(currentBlockInformation); |
+ currentBlockInformation = node.blockInformation; |
+ bool success = currentBlockInformation.accept(this); |
currentBlockInformation = oldBlockInformation; |
- return; |
- } |
+ if (success) return; |
- if (node.isLoopHeader() && |
- node.loopInformation !== currentBlockInformation) { |
- HBlockInformation oldBlockInformation = currentBlockInformation; |
- currentBlockInformation = node.loopInformation; |
- bool prettyLoop = handleLoop(node); |
- currentBlockInformation = oldBlockInformation; |
- if (prettyLoop) { |
- visitBasicBlock(node.loopInformation.joinBlock); |
- return; |
+ // Even if our special handling didn't succeed, loop blocks |
floitsch
2012/04/16 13:26:07
If our special handling didn't succeed, we have to
Lasse Reichstein Nielsen
2012/04/17 12:58:22
Done.
|
+ // have special treatement in the primitive traversal too. |
+ if (node.isLoopHeader()) { |
+ beginLoop(node); |
} |
- beginLoop(node); |
} |
- |
iterateBasicBlock(node); |
} |
@@ -1591,7 +1598,7 @@ class SsaOptimizedCodeGenerator extends SsaCodeGenerator { |
buffer.add('||'); |
checkImmutableArray(input); |
buffer.add(') '); |
- bailout(node, 'Not a mutable array'); |
+ bailout(node, 'Not a mutable array'); |
} else if (node.isArray()) { |
buffer.add('if ('); |
checkObject(input, '!=='); |
@@ -1616,7 +1623,8 @@ class SsaOptimizedCodeGenerator extends SsaCodeGenerator { |
void beginLoop(HBasicBlock block) { |
addIndentation(); |
- for (LabelElement label in block.loopInformation.labels) { |
+ HLoopInformation info = block.blockInformation; |
+ for (LabelElement label in info.labels) { |
writeLabel(label); |
buffer.add(":"); |
} |
@@ -1735,7 +1743,7 @@ class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator { |
} |
} |
- bool handleLoop(HBasicBlock node) => false; |
+ bool visitLoopInfo(HLoopInformation info) => false; |
void visitTypeGuard(HTypeGuard node) { |
indent--; |
@@ -1787,7 +1795,6 @@ class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator { |
buffer.add('}\n'); // Close 'switch'. |
} |
- |
void beginLoop(HBasicBlock block) { |
// TODO(ngeoffray): Don't put labels on loops that don't bailout. |
String newLabel = pushLabel(); |
@@ -1796,7 +1803,8 @@ class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator { |
} |
addIndentation(); |
- for (SourceString label in block.loopInformation.labels) { |
+ HLoopInformation info = block.blockInformation; |
+ for (SourceString label in info.labels) { |
writeLabel(label); |
buffer.add(":"); |
} |