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

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

Issue 1476293003: dart2js cps: Emit 'return' after throwing call to assist VM analysis. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update test case expected output Created 5 years 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 | tests/compiler/dart2js/js_backend_cps_ir_gvn_test.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 487eb4508fd26b79eba8879da264ec83b0baac8f..8bb26fd773bd3439b8db3e8c9a99466e54209db6 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -68,6 +68,18 @@ class CodeGenerator extends tree_ir.StatementVisitor
final tree_ir.FallthroughStack shortContinue =
new tree_ir.FallthroughStack();
+ /// When the top element is true, [Unreachable] statements will be emitted
+ /// as [Return]s, otherwise they are emitted as empty because they are
+ /// followed by the end of the method.
+ ///
+ /// Note on why the [fallthrough] stack should not be used for this:
+ /// Ordinary statements may choose whether to use the [fallthrough] target,
+ /// and the choice to do so may disable an optimization in [visitIf].
+ /// But omitting an unreachable 'return' should have lower priority than
+ /// the optimizations in [visitIf], so [visitIf] will instead tell the
+ /// [Unreachable] statements whether they may use fallthrough or not.
+ List<bool> emitUnreachableAsReturn = <bool>[false];
+
Set<tree_ir.Label> usedLabels = new Set<tree_ir.Label>();
List<js.Statement> accumulator = new List<js.Statement>();
@@ -534,16 +546,34 @@ class CodeGenerator extends tree_ir.StatementVisitor
@override
void visitExpressionStatement(tree_ir.ExpressionStatement node) {
- accumulator.add(new js.ExpressionStatement(
- visitExpression(node.expression)));
- visitStatement(node.next);
+ js.Expression exp = visitExpression(node.expression);
+ if (node.next is tree_ir.Unreachable && emitUnreachableAsReturn.last) {
+ // Emit as 'return exp' to assist local analysis in the VM.
+ accumulator.add(new js.Return(exp));
+ } else {
+ accumulator.add(new js.ExpressionStatement(exp));
+ visitStatement(node.next);
+ }
+ }
+
+ bool isNullReturn(tree_ir.Statement node) {
+ return node is tree_ir.Return && isNull(node.value);
+ }
+
+ bool isEndOfMethod(tree_ir.Statement node) {
+ return isNullReturn(node) ||
+ node is tree_ir.Break && isNullReturn(node.target.binding.next);
}
@override
void visitIf(tree_ir.If node) {
js.Expression condition = visitExpression(node.condition);
int usesBefore = fallthrough.useCount;
+ // Unless the 'else' part ends the method. make sure to terminate any
+ // uncompletable code paths in the 'then' part.
+ emitUnreachableAsReturn.add(!isEndOfMethod(node.elseStatement));
js.Statement thenBody = buildBodyStatement(node.thenStatement);
+ emitUnreachableAsReturn.removeLast();
bool thenHasFallthrough = (fallthrough.useCount > usesBefore);
if (thenHasFallthrough) {
js.Statement elseBody = buildBodyStatement(node.elseStatement);
@@ -614,7 +644,9 @@ class CodeGenerator extends tree_ir.StatementVisitor
shortBreak.push(node.next);
shortContinue.push(node);
fallthrough.push(node);
+ emitUnreachableAsReturn.add(true);
js.Statement body = buildBodyStatement(node.body);
+ emitUnreachableAsReturn.removeLast();
fallthrough.pop();
shortContinue.pop();
shortBreak.pop();
@@ -644,7 +676,9 @@ class CodeGenerator extends tree_ir.StatementVisitor
shortBreak.push(fallthrough.target);
shortContinue.push(node);
fallthrough.push(node);
+ emitUnreachableAsReturn.add(true);
js.Statement jsBody = buildBodyStatement(node.body);
+ emitUnreachableAsReturn.removeLast();
fallthrough.pop();
shortContinue.pop();
if (shortBreak.useCount > 0) {
@@ -683,8 +717,10 @@ class CodeGenerator extends tree_ir.StatementVisitor
@override
void visitUnreachable(tree_ir.Unreachable node) {
- // Output nothing.
- // TODO(asgerf): Emit a throw/return to assist local analysis in the VM?
+ if (emitUnreachableAsReturn.last) {
+ // Emit a return to assist local analysis in the VM.
+ accumulator.add(new js.Return());
+ }
}
@override
« no previous file with comments | « no previous file | tests/compiler/dart2js/js_backend_cps_ir_gvn_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698