Chromium Code Reviews| Index: lib/compiler/implementation/ssa/codegen.dart |
| =================================================================== |
| --- lib/compiler/implementation/ssa/codegen.dart (revision 7378) |
| +++ lib/compiler/implementation/ssa/codegen.dart (working copy) |
| @@ -517,24 +517,80 @@ |
| } |
| void define(HInstruction instruction) { |
| - String name = temporary(instruction); |
| - declareVariable(name); |
| - buffer.add(" = "); |
| - visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| + bool needsVar = !instruction.usedBy.isEmpty(); |
| + if (needsVar) { |
| + if (instruction.returnsInput()) { |
|
Lasse Reichstein Nielsen
2012/05/08 12:39:08
Use single if with '&&'.
ngeoffray
2012/05/08 16:09:12
Done.
|
| + HInstruction input = instruction.input; |
| + // We only need a new var if [input] is generated at use site |
| + // but is not a trivial code motion invariant instruction (eg |
|
floitsch
2012/05/08 13:21:42
"like for". There is enough space.
ngeoffray
2012/05/08 16:09:12
Done.
|
| + // parameters or this). |
| + // |
| + // For example: |
| + // Foo a = this; |
| + // print(a); |
| + // print(a); |
| + // |
| + // In checked mode does not need a new variable: |
|
floitsch
2012/05/08 13:21:42
In checked mode no new variable is needed:
ngeoffray
2012/05/08 16:09:12
Done.
|
| + // FooTypeCheck(this); |
| + // print(this); |
| + // print(this); |
| + // |
| + // But for this example: |
| + // Foo a = foo(); |
| + // print(a); |
| + // print(a); |
| + // |
| + // We need a new variable: |
| + // var a = FooTypeCheck(foo()); |
| + // print(a); |
| + // print(a); |
| + needsVar = isGenerateAtUseSite(input) && !input.isCodeMotionInvariant(); |
|
floitsch
2012/05/08 13:21:42
If I understand correctly it is crucial that 'defi
ngeoffray
2012/05/08 16:09:12
Done.
|
| + } |
| + } |
| + if (needsVar) { |
| + String name = temporary(instruction); |
| + declareVariable(name); |
| + buffer.add(" = "); |
| + visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| + } else { |
| + visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| + } |
| } |
| void use(HInstruction argument, int expectedPrecedenceForArgument) { |
| - if (isGenerateAtUseSite(argument)) { |
| + if (argument.returnsInput()) { |
| + HInstruction input = argument.input; |
| + if (isGenerateAtUseSite(argument) && isGenerateAtUseSite(input)) { |
| + // If both instructions can be generated at use site, we can |
| + // just visit [argument]. |
| + // |
| + // For example: |
| + // Foo a = foo(); |
| + // print(a); |
| + // |
| + // In checked mode will turn into: |
| + // print(FooTypeCheck(foo())); |
| + visit(argument, expectedPrecedenceForArgument); |
| + } else if (isGenerateAtUseSite(input) && !input.isCodeMotionInvariant()) { |
|
Lasse Reichstein Nielsen
2012/05/08 12:39:08
Please explain the use of isCodeMotionInvariant.
ngeoffray
2012/05/08 16:09:12
Done.
|
| + // If [argument] cannot be generated at use site, but [input] |
| + // can, use the temporary of [argument]. |
| + // |
| + // For example: |
| + // Foo a = foo(); |
| + // print(a); |
| + // print(a); |
| + // |
| + // In checked mode will turn into: |
| + // var a = FooTypeCheck(foo()); |
| + // print(a); |
| + // print(a); |
| + buffer.add(temporary(argument)); |
| + } else { |
| + // Otherwise we just use [input]. |
|
Lasse Reichstein Nielsen
2012/05/08 12:39:08
Please give example of output here too.
What happe
ngeoffray
2012/05/08 16:09:12
Done.
|
| + use(input, expectedPrecedenceForArgument); |
| + } |
| + } else if (isGenerateAtUseSite(argument)) { |
| visit(argument, expectedPrecedenceForArgument); |
| - } else if (argument is HIntegerCheck) { |
| - HIntegerCheck instruction = argument; |
| - use(instruction.value, expectedPrecedenceForArgument); |
| - } else if (argument is HBoundsCheck) { |
| - HBoundsCheck instruction = argument; |
| - use(instruction.index, expectedPrecedenceForArgument); |
| - } else if (argument is HTypeGuard) { |
| - HTypeGuard instruction = argument; |
| - use(instruction.guarded, expectedPrecedenceForArgument); |
| } else { |
| buffer.add(temporary(argument)); |
| } |
| @@ -1063,41 +1119,26 @@ |
| assignPhisOfAllSuccessors(node); |
| } |
| - if (instruction is HGoto || instruction is HExit || instruction is HTry) { |
| - visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| - return; |
| - } else if (!isGenerateAtUseSite(instruction)) { |
| - if (instruction is !HIf |
| - && instruction is !HTypeGuard |
| - && instruction is !HLoopBranch |
| - && !isGeneratingExpression()) { |
| - addIndentation(); |
| + 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); |
| } |
| - if (isGeneratingExpression()) { |
| + } else if (instruction is HControlFlow) { |
| + if (instruction is HLoopBranch && isGeneratingExpression()) { |
| addExpressionSeparator(); |
| } |
| - if (instruction.usedBy.isEmpty() |
| - || instruction is HTypeGuard |
| - || instruction is HCheck) { |
| - visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| - } else { |
| - define(instruction); |
| - } |
| - // Control flow instructions, and some other instructions, |
| - // know how to handle ';'. |
| - if (instruction is !HControlFlow |
| - && instruction is !HTypeGuard |
| - && !isGeneratingExpression()) { |
| - buffer.add(';\n'); |
| - } |
| - } else 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); |
| - return; |
| + visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| + } else if (instruction is HTypeGuard) { |
| + visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| + } else { |
| + isGeneratingExpression() ? addExpressionSeparator() : addIndentation(); |
|
Lasse Reichstein Nielsen
2012/05/08 12:39:08
Use if. Please don't (try) to be clever with the c
ngeoffray
2012/05/08 16:09:12
Done.
|
| + define(instruction); |
| + if (!isGeneratingExpression()) buffer.add(';\n'); |
| } |
| instruction = instruction.next; |
| } |
| @@ -1618,6 +1659,7 @@ |
| } |
| visitReturn(HReturn node) { |
| + addIndentation(); |
| assert(node.inputs.length == 1); |
| HInstruction input = node.inputs[0]; |
| if (input.isConstantNull()) { |
| @@ -1634,6 +1676,7 @@ |
| } |
| visitThrow(HThrow node) { |
| + addIndentation(); |
| if (node.isRethrow) { |
| buffer.add('throw '); |
| use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); |
| @@ -2033,6 +2076,7 @@ |
| } |
| void visitTypeConversion(HTypeConversion node) { |
| + HInstruction input = node.inputs[0]; |
|
Lasse Reichstein Nielsen
2012/05/08 12:39:08
node.input?
Why extract input here, when it's only
ngeoffray
2012/05/08 16:09:12
Done.
|
| if (node.checked) { |
| Element element = node.type.computeType(compiler).element; |
| compiler.registerIsCheck(element); |
| @@ -2080,12 +2124,12 @@ |
| compiler.registerStaticUse(helperElement); |
| buffer.add(compiler.namer.isolateAccess(helperElement)); |
| buffer.add('('); |
| - use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); |
| + use(input, JSPrecedence.EXPRESSION_PRECEDENCE); |
| if (additionalArgument !== null) buffer.add(", '$additionalArgument'"); |
| buffer.add(')'); |
| endExpression(JSPrecedence.CALL_PRECEDENCE); |
| } else { |
| - use(node.inputs[0], expectedPrecedence); |
| + visit(input, expectedPrecedence); |
| } |
| } |
| } |