Index: lib/compiler/implementation/ssa/codegen.dart |
=================================================================== |
--- lib/compiler/implementation/ssa/codegen.dart (revision 8244) |
+++ lib/compiler/implementation/ssa/codegen.dart (working copy) |
@@ -147,7 +147,7 @@ |
final String parameters; |
final Set<HInstruction> generateAtUseSite; |
- final Map<HPhi, String> logicalOperations; |
+ final Set<HInstruction> logicalOperations; |
final Map<Element, ElementAction> breakAction; |
final Map<Element, ElementAction> continueAction; |
final Map<Element, String> parameterNames; |
@@ -206,7 +206,7 @@ |
delayedVariablesDeclaration = new List<String>(), |
buffer = new StringBuffer(), |
generateAtUseSite = new Set<HInstruction>(), |
- logicalOperations = new Map<HPhi, String>(), |
+ logicalOperations = new Set<HInstruction>(), |
breakAction = new Map<Element, ElementAction>(), |
continueAction = new Map<Element, ElementAction>(), |
unsignedShiftPrecedences = JSPrecedence.binary['>>>'] { |
@@ -487,6 +487,11 @@ |
} |
void define(HInstruction instruction) { |
+ if (isGeneratingExpression()) { |
+ addExpressionSeparator(); |
+ } else { |
+ addIndentation(); |
+ } |
if (instruction is !HCheck && variableNames.hasName(instruction)) { |
declareInstruction(instruction); |
buffer.add(" = "); |
@@ -494,6 +499,7 @@ |
} else { |
visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
} |
+ if (!isGeneratingExpression()) buffer.add(';\n'); |
} |
void use(HInstruction argument, int expectedPrecedenceForArgument) { |
@@ -533,6 +539,9 @@ |
} |
bool visitIfInfo(HIfBlockInformation info) { |
+ // If the [HIf] instruction is actually a logical operation, we |
+ // let the flow-based traversal handle it. |
+ if (logicalOperations.contains(info.condition.end.last)) return false; |
HInstruction condition = info.condition.conditionExpression; |
if (condition.isConstant()) { |
// If the condition is constant, only generate one branch (if any). |
@@ -809,16 +818,6 @@ |
return true; |
} |
- void emitLogicalOperation(HPhi node, String operation) { |
- JSBinaryOperatorPrecedence operatorPrecedence = |
- JSPrecedence.binary[operation]; |
- beginExpression(operatorPrecedence.precedence); |
- use(node.inputs[0], operatorPrecedence.left); |
- buffer.add(" $operation "); |
- use(node.inputs[1], operatorPrecedence.right); |
- endExpression(operatorPrecedence.precedence); |
- } |
- |
// Wraps a loop body in a block to make continues have a target to break |
// to (if necessary). |
void wrapLoopBodyForContinue(HLoopBlockInformation info) { |
@@ -1012,38 +1011,19 @@ |
void iterateBasicBlock(HBasicBlock node) { |
HInstruction instruction = node.first; |
- while (instruction != null) { |
- if (instruction === node.last) { |
- assignPhisOfSuccessors(node); |
- } |
- |
- if (isGenerateAtUseSite(instruction)) { |
- if (instruction is HIf) { |
- HIf hif = instruction; |
- // The "if" is implementing part of a logical expression. |
- // Skip directly forward to to its latest successor, since everything |
- // in-between must also be generateAtUseSite. |
- assert(hif.trueBranch.id < hif.falseBranch.id); |
- visitBasicBlock(hif.falseBranch); |
- } |
- } else if (instruction is HControlFlow) { |
- if (instruction is HLoopBranch && isGeneratingExpression()) { |
- addExpressionSeparator(); |
- } |
+ while (instruction !== node.last) { |
+ if (instruction is HTypeGuard) { |
visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
- } else if (instruction is HTypeGuard) { |
- visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
- } else { |
- if (isGeneratingExpression()) { |
- addExpressionSeparator(); |
- } else { |
- addIndentation(); |
- } |
+ } else if (!isGenerateAtUseSite(instruction)) { |
define(instruction); |
- if (!isGeneratingExpression()) buffer.add(';\n'); |
} |
instruction = instruction.next; |
} |
+ assignPhisOfSuccessors(node); |
+ if (instruction is HLoopBranch && isGeneratingExpression()) { |
+ addExpressionSeparator(); |
+ } |
+ visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
} |
visitInvokeBinary(HInvokeBinary node, String op) { |
@@ -1263,7 +1243,6 @@ |
|| start.last is HContinue) { |
return false; |
} |
- HInstruction instruction = start.first; |
for (HInstruction instruction = start.first; |
instruction != start.last; |
instruction = instruction.next) { |
@@ -1286,12 +1265,20 @@ |
} |
visitIf(HIf node) { |
+ if (logicalOperations.contains(node)) { |
+ HPhi phi = node.joinBlock.phis.first; |
+ if (!isGenerateAtUseSite(phi)) define(phi); |
+ visitBasicBlock(node.joinBlock); |
+ return; |
+ } |
+ |
if (subGraph !== null && node.block === subGraph.end) { |
if (isGeneratingExpression()) { |
use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); |
} |
return; |
} |
+ |
HInstruction condition = node.inputs[0]; |
int preVisitedBlocks = 0; |
List<HBasicBlock> dominated = node.block.dominatedBlocks; |
@@ -1587,17 +1574,20 @@ |
} |
visitNot(HNot node) { |
+ assert(node.inputs.length == 1); |
+ generateNot(node.inputs[0]); |
+ } |
+ |
+ |
+ void generateNot(HInstruction input) { |
bool isBuiltinRelational(HInstruction instruction) { |
if (instruction is !HRelational) return false; |
HRelational relational = instruction; |
return relational.builtin; |
} |
- assert(node.inputs.length == 1); |
- HInstruction input = node.inputs[0]; |
if (input is HBoolify && isGenerateAtUseSite(input)) { |
beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
- assert(node.inputs.length == 1); |
use(input.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE); |
buffer.add(' !== true'); |
endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
@@ -1636,11 +1626,33 @@ |
} |
visitPhi(HPhi node) { |
- String operation = logicalOperations[node]; |
- if (operation !== null) { |
- emitLogicalOperation(node, operation); |
+ HBasicBlock ifBlock = node.block.predecessors[0].predecessors[0]; |
+ // This method is only called for phis that are generated at use |
+ // site. A phi can be generated at use site only if it is the |
+ // result of a logical operation. |
+ assert(logicalOperations.contains(ifBlock.last)); |
+ HInstruction input = ifBlock.last.inputs[0]; |
+ if (input.isConstantFalse()) { |
+ use(node.inputs[1], expectedPrecedence); |
+ } else if (input.isConstantTrue()) { |
+ use(node.inputs[0], expectedPrecedence); |
} else { |
- buffer.add('${variableNames.getName(node)}'); |
+ String operation = node.inputs[1].isConstantFalse() ? '&&' : '||'; |
+ JSBinaryOperatorPrecedence operatorPrecedence = |
+ JSPrecedence.binary[operation]; |
+ beginExpression(operatorPrecedence.precedence); |
+ if (operation == '||') { |
+ if (input is HNot) { |
+ use(input.inputs[0], operatorPrecedence.left); |
+ } else { |
+ generateNot(input); |
+ } |
+ } else { |
+ use(input, operatorPrecedence.left); |
+ } |
+ buffer.add(" $operation "); |
+ use(node.inputs[0], operatorPrecedence.right); |
+ endExpression(operatorPrecedence.precedence); |
} |
} |