| Index: lib/compiler/implementation/ssa/codegen.dart
|
| diff --git a/lib/compiler/implementation/ssa/codegen.dart b/lib/compiler/implementation/ssa/codegen.dart
|
| index 67774ca552f11613bb09748c48bc90608e9c06e8..c7a7b9679817f748e3e8e61d639fee5a8f67fc95 100644
|
| --- a/lib/compiler/implementation/ssa/codegen.dart
|
| +++ b/lib/compiler/implementation/ssa/codegen.dart
|
| @@ -15,7 +15,7 @@ class SsaCodeGeneratorTask extends CompilerTask {
|
| SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator(
|
| compiler, work, parameters, parameterNames);
|
| codegen.visitGraph(graph);
|
| -
|
| +
|
| FunctionElement element = work.element;
|
| String code;
|
| if (element.isInstanceMember()
|
| @@ -80,7 +80,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),
|
| @@ -413,7 +413,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) {
|
| + 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)) {
|
| + return false;
|
| + }
|
| + switch (info.kind) {
|
| + 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.
|
| + 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");
|
| + 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");
|
| + }
|
| + break;
|
| + }
|
| + case HLoopInformation.DO_WHILE_LOOP:
|
| + // Currently unhandled.
|
| + return false;
|
| + default:
|
| + compiler.internalError(
|
| + 'Unexpected loop kind: ${info.kind}',
|
| + instruction: condition.expression);
|
| + }
|
| + visitBasicBlock(info.joinBlock);
|
| + return true;
|
| + }
|
| +
|
| + bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) {
|
| addIndentation();
|
| Link<Element> continueOverrides = const EmptyLink<Element>();
|
| // If [labeledBlockInfo.isContinue], the block is an artificial
|
| @@ -474,6 +581,7 @@ class SsaCodeGenerator implements HVisitor {
|
| } else {
|
| breakAction.remove(labeledBlockInfo.target);
|
| }
|
| + return true;
|
| }
|
|
|
| void emitLogicalOperation(HPhi node, String operation) {
|
| @@ -519,99 +627,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;
|
| @@ -620,28 +635,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;
|
| + // If our special handling didn't succeed, we have to emit a generic
|
| + // version. This still requires special handling for loop-blocks
|
| + if (node.isLoopHeader()) {
|
| + beginLoop(node);
|
| }
|
| - beginLoop(node);
|
| }
|
| -
|
| iterateBasicBlock(node);
|
| }
|
|
|
| @@ -1614,7 +1621,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, '!==');
|
| @@ -1639,7 +1646,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(":");
|
| }
|
| @@ -1758,7 +1766,7 @@ class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator {
|
| }
|
| }
|
|
|
| - bool handleLoop(HBasicBlock node) => false;
|
| + bool visitLoopInfo(HLoopInformation info) => false;
|
|
|
| void visitTypeGuard(HTypeGuard node) {
|
| indent--;
|
| @@ -1810,7 +1818,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();
|
| @@ -1819,7 +1826,8 @@ class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator {
|
| }
|
|
|
| addIndentation();
|
| - for (LabelElement label in block.loopInformation.labels) {
|
| + HLoopInformation loopInformation = block.blockInformation;
|
| + for (LabelElement label in loopInformation.labels) {
|
| writeLabel(label);
|
| buffer.add(":");
|
| }
|
|
|