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

Unified Diff: pkg/compiler/lib/src/js_backend/codegen/codegen.dart

Issue 1203423003: dart2js cps: Better fallthrough analysis and eliminate "return null". (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update tests Created 5 years, 6 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 | pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/js_backend/codegen/codegen.dart
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index 6168f8ef69b10cc440c858b960372b696192b527..54e247234d710e64eb456f4a0cbcdc975e40e349 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -46,10 +46,7 @@ class CodeGenerator extends tree_ir.StatementVisitor
/// Variable names that have already been used. Used to avoid name clashes.
Set<String> usedVariableNames = new Set<String>();
- /// Input to [visitStatement]. Denotes the statement that will execute next
- /// if the statements produced by [visitStatement] complete normally.
- /// Set to null if control will fall over the end of the method.
- tree_ir.Statement fallthrough = null;
+ final tree_ir.FallthroughStack fallthrough = new tree_ir.FallthroughStack();
Set<tree_ir.Label> usedLabels = new Set<tree_ir.Label>();
@@ -408,12 +405,13 @@ class CodeGenerator extends tree_ir.StatementVisitor
@override
void visitContinue(tree_ir.Continue node) {
- tree_ir.Statement fallthrough = this.fallthrough;
- if (node.target.binding == fallthrough) {
+ tree_ir.Statement next = fallthrough.target;
+ if (node.target.binding == next) {
// Fall through to continue target
- } else if (fallthrough is tree_ir.Continue &&
- fallthrough.target == node.target) {
+ fallthrough.use();
+ } else if (next is tree_ir.Continue && next.target == node.target) {
// Fall through to equivalent continue
+ fallthrough.use();
} else {
usedLabels.add(node.target);
accumulator.add(new js.Continue(node.target.name));
@@ -421,6 +419,21 @@ class CodeGenerator extends tree_ir.StatementVisitor
}
@override
+ void visitBreak(tree_ir.Break node) {
+ tree_ir.Statement next = fallthrough.target;
+ if (node.target.binding.next == next) {
+ // Fall through to break target
+ fallthrough.use();
+ } else if (next is tree_ir.Break && next.target == node.target) {
+ // Fall through to equivalent break
+ fallthrough.use();
+ } else {
+ usedLabels.add(node.target);
+ accumulator.add(new js.Break(node.target.name));
+ }
+ }
+
+ @override
void visitExpressionStatement(tree_ir.ExpressionStatement node) {
accumulator.add(new js.ExpressionStatement(
visitExpression(node.expression)));
@@ -429,9 +442,19 @@ class CodeGenerator extends tree_ir.StatementVisitor
@override
void visitIf(tree_ir.If node) {
- accumulator.add(new js.If(visitExpression(node.condition),
- buildBodyStatement(node.thenStatement),
- buildBodyStatement(node.elseStatement)));
+ js.Expression condition = visitExpression(node.condition);
+ int usesBefore = fallthrough.useCount;
+ js.Statement thenBody = buildBodyStatement(node.thenStatement);
+ bool thenHasFallthrough = (fallthrough.useCount > usesBefore);
+ if (thenHasFallthrough) {
+ js.Statement elseBody = buildBodyStatement(node.elseStatement);
+ accumulator.add(new js.If(condition, thenBody, elseBody));
+ } else {
+ // The 'then' body cannot complete normally, so emit a short 'if'
+ // and put the 'else' body after it.
+ accumulator.add(new js.If.noElse(condition, thenBody));
+ visitStatement(node.elseStatement);
+ }
}
@override
@@ -443,32 +466,17 @@ class CodeGenerator extends tree_ir.StatementVisitor
}
js.Statement buildLabeled(js.Statement buildBody(),
- tree_ir.Label label,
- tree_ir.Statement fallthroughStatement) {
- tree_ir.Statement savedFallthrough = fallthrough;
- fallthrough = fallthroughStatement;
+ tree_ir.Label label,
+ tree_ir.Statement fallthroughStatement) {
+ fallthrough.push(fallthroughStatement);
js.Statement result = buildBody();
if (usedLabels.remove(label)) {
result = new js.LabeledStatement(label.name, result);
}
- fallthrough = savedFallthrough;
+ fallthrough.pop();
return result;
}
- @override
- void visitBreak(tree_ir.Break node) {
- tree_ir.Statement fallthrough = this.fallthrough;
- if (node.target.binding.next == fallthrough) {
- // Fall through to break target
- } else if (fallthrough is tree_ir.Break &&
- fallthrough.target == node.target) {
- // Fall through to equivalent break
- } else {
- usedLabels.add(node.target);
- accumulator.add(new js.Break(node.target.name));
- }
- }
-
/// Returns the current [accumulator] wrapped in a block if neccessary.
js.Statement _bodyAsStatement() {
if (accumulator.length == 0) {
@@ -524,9 +532,19 @@ class CodeGenerator extends tree_ir.StatementVisitor
buildWhile(new js.LiteralBool(true), node.body, node.label, node));
}
+ bool isNull(tree_ir.Expression node) {
+ return node is tree_ir.Constant && node.value.isNull;
+ }
+
@override
void visitReturn(tree_ir.Return node) {
- accumulator.add(new js.Return(visitExpression(node.value)));
+ if (isNull(node.value) && fallthrough.target == null) {
+ // Do nothing. Implicitly return JS undefined by falling over the end.
+ registry.registerCompileTimeConstant(new NullConstantValue());
+ fallthrough.use();
+ } else {
+ accumulator.add(new js.Return(visitExpression(node.value)));
+ }
}
@override
« no previous file with comments | « no previous file | pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698