Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Unified Diff: lib/compiler/implementation/ssa/codegen.dart

Issue 10383062: Avoid inserting new temporaries because of HTypeConversion nodes. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen_helpers.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/compiler/implementation/ssa/codegen.dart
===================================================================
--- lib/compiler/implementation/ssa/codegen.dart (revision 7417)
+++ lib/compiler/implementation/ssa/codegen.dart (working copy)
@@ -516,25 +516,107 @@
}
}
+ bool needsNewVariable(HInstruction instruction) {
+ bool needsVar = !instruction.usedBy.isEmpty();
+ if (needsVar && instruction is HCheck) {
+ HCheck check = instruction;
+ HInstruction input = check.checkedInput;
+ // We only need a new var if [input] is generated at use site
+ // but is not a trivial code motion invariant instruction like
+ // for parameters or this.
+ //
+ // For example:
+ // Foo a = this;
+ // print(a);
+ // print(a);
+ //
+ // In checked mode no new variable is needed.
+ // 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();
+ }
+ return needsVar;
+ }
+
void define(HInstruction instruction) {
- String name = temporary(instruction);
- declareVariable(name);
- buffer.add(" = ");
- visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE);
+ if (needsNewVariable(instruction)) {
+ 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 is HCheck) {
+ HCheck instruction = argument;
+ HInstruction input = instruction.checkedInput;
+ 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)) {
+ // If [argument] cannot be generated at use site, but [input]
+ // can, use the temporary of [argument]. A code motion
+ // invariant instruction does not have a temporary, so we just
+ //
+ // For example:
+ // Foo a = foo();
+ // print(a);
+ // print(a);
+ //
+ // In checked mode will turn into:
+ // var a = FooTypeCheck(foo());
+ // print(a);
+ // print(a);
+ //
+ // Note that in case the input is code motion invariant, like
+ // for parameters or this, we just need to visit it, since
+ // there is no temporary for such instruction.
+ if (input.isCodeMotionInvariant()) {
+ visit(input, expectedPrecedenceForArgument);
+ } else {
+ buffer.add(temporary(argument));
+ }
+ } else {
+ // Otherwise we just use [input]. [argument] has already been
+ // emitted, and we just need the temporary of [input].
+ //
+ // For example:
+ // var a = foo();
+ // print(a);
+ // Foo b = a;
+ // print(b);
+ //
+ // In checked mode will turn into:
+ // var a = foo();
+ // print(a);
+ // FooTypeCheck(a);
+ // print(a);
+ 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));
}
@@ -1066,41 +1148,30 @@
assignPhisOfAllSuccessors(node);
}
- if (instruction is HGoto || instruction is HExit || instruction is HTry) {
+ 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();
+ }
visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
- return;
- } else if (!isGenerateAtUseSite(instruction)) {
- if (instruction is !HIf
- && instruction is !HTypeGuard
- && instruction is !HLoopBranch
- && !isGeneratingExpression()) {
- addIndentation();
- }
+ } else if (instruction is HTypeGuard) {
+ visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
+ } else {
if (isGeneratingExpression()) {
addExpressionSeparator();
- }
- if (instruction.usedBy.isEmpty()
- || instruction is HTypeGuard
- || instruction is HCheck) {
- visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
} else {
- define(instruction);
+ addIndentation();
}
- // 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;
+ define(instruction);
+ if (!isGeneratingExpression()) buffer.add(';\n');
}
instruction = instruction.next;
}
@@ -1652,6 +1723,7 @@
}
visitReturn(HReturn node) {
+ addIndentation();
assert(node.inputs.length == 1);
HInstruction input = node.inputs[0];
if (input.isConstantNull()) {
@@ -1668,6 +1740,7 @@
}
visitThrow(HThrow node) {
+ addIndentation();
if (node.isRethrow) {
buffer.add('throw ');
use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
@@ -2114,12 +2187,12 @@
compiler.registerStaticUse(helperElement);
buffer.add(compiler.namer.isolateAccess(helperElement));
buffer.add('(');
- use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
+ use(node.checkedInput, JSPrecedence.EXPRESSION_PRECEDENCE);
if (additionalArgument !== null) buffer.add(", '$additionalArgument'");
buffer.add(')');
endExpression(JSPrecedence.CALL_PRECEDENCE);
} else {
- use(node.inputs[0], expectedPrecedence);
+ visit(node.checkedInput, expectedPrecedence);
}
}
}
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698