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

Unified Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart

Issue 1092023002: CPS implementation of throw and rethrow. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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
Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index 59b0f96b1e12a77dd4c0696d41bd20f176dac04f..e786e17a8bd25413cb9e335306f7ed8aae7a59ce 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -366,7 +366,20 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
// where (C', _) = Build(e, C)
ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) {
assert(irBuilder.isOpen);
- visit(node.expression);
+ if (node.expression is ast.Throw) {
+ // Throw expressions that occur as statements are translated differently
+ // from ones that occur as subexpressions. This is achieved by peeking
+ // at statement-level expressions here.
+ irBuilder.buildThrow(visit(node.expression));
+ } else {
+ visit(node.expression);
+ }
+ return null;
+ }
+
+ ir.Primitive visitRethrow(ast.Rethrow node) {
+ assert(irBuilder.isOpen);
+ irBuilder.buildRethrow();
return null;
}
@@ -494,7 +507,7 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
visitTryStatement(ast.TryStatement node) {
// Multiple catch blocks are not yet implemented.
if (node.catchBlocks.isEmpty ||
- node.catchBlocks.nodes.tail == null) {
+ !node.catchBlocks.nodes.tail.isEmpty) {
return giveup(node, 'not exactly one catch block');
}
// 'on T' catch blocks are not yet implemented.
@@ -1761,10 +1774,17 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
return irBuilder.buildConstantLiteral(getConstantForNode(node));
}
+ ir.Primitive visitThrow(ast.Throw node) {
+ assert(irBuilder.isOpen);
+ // This function is not called for throw expressions occurring as
+ // statements.
+ return irBuilder.buildNonTailThrow(visit(node.expression));
+ }
+
ir.RootNode nullIfGiveup(ir.RootNode action()) {
try {
return action();
- } catch(e, tr) {
+ } catch(e) {
if (e == ABORT_IRNODE_BUILDER) {
return null;
}
@@ -2004,13 +2024,16 @@ class DartIrBuilderVisitor extends IrBuilderVisitor {
ir.RootNode buildExecutable(ExecutableElement element) {
return nullIfGiveup(() {
+ ir.RootNode root;
if (element is FieldElement) {
- return buildField(element);
+ root = buildField(element);
} else if (element is FunctionElement || element is ConstructorElement) {
- return buildFunction(element);
+ root = buildFunction(element);
} else {
compiler.internalError(element, "Unexpected element type $element");
}
+ new CleanupPass().visit(root);
+ return root;
});
}
@@ -2224,21 +2247,27 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
ir.RootNode buildExecutable(ExecutableElement element) {
return nullIfGiveup(() {
+ ir.RootNode root;
switch (element.kind) {
case ElementKind.GENERATIVE_CONSTRUCTOR:
- return buildConstructor(element);
+ root = buildConstructor(element);
+ break;
case ElementKind.GENERATIVE_CONSTRUCTOR_BODY:
- return buildConstructorBody(element);
+ root = buildConstructorBody(element);
+ break;
case ElementKind.FUNCTION:
case ElementKind.GETTER:
case ElementKind.SETTER:
- return buildFunction(element);
+ root = buildFunction(element);
+ break;
default:
compiler.internalError(element, "Unexpected element type $element");
}
+ new CleanupPass().visit(root);
+ return root;
});
}
@@ -2772,3 +2801,71 @@ class PositionSourceInformationBuilder implements SourceInformationBuilder {
return new PositionSourceInformationBuilder(element);
}
}
+
+/// Perform simple post-processing on the initial CPS-translated root term.
+///
+/// This pass performs backend-independent post-processing on the translated
+/// term. It is implemented separately from the optimization passes because
+/// it is required for correctness of the implementation.
+///
+/// It performs the following translations:
+/// - Replace [ir.LetPrim] binding a [ir.NonTailThrow] with a [ir.Throw]
+/// expression.
+class CleanupPass extends ir.RecursiveVisitor {
+ RemovalVisitor _remover = new RemovalVisitor();
+
+ ir.Expression replacementFor(ir.Expression expression) {
+ if (expression != null && expression is ir.LetPrim) {
+ ir.Primitive primitive = expression.primitive;
+ if (primitive is ir.NonTailThrow) {
+ _remover.visit(expression);
+ return new ir.Throw(primitive.value.definition);
+ }
+ }
+ return expression;
+ }
+
+ processLetPrim(ir.LetPrim node) {
+ node.body = replacementFor(node.body);
+ }
+
+ processLetCont(ir.LetCont node) {
+ node.body = replacementFor(node.body);
+ }
+
+ processLetHandler(ir.LetHandler node) {
+ node.body = replacementFor(node.body);
+ }
+
+ processLetMutable(ir.LetMutable node) {
+ node.body = replacementFor(node.body);
+ }
+
+ processSetMutableVariable(ir.SetMutableVariable node) {
+ node.body = replacementFor(node.body);
+ }
+
+ processDeclareFunction(ir.DeclareFunction node) {
+ node.body = replacementFor(node.body);
+ }
+
+ processSetField(ir.SetField node) {
+ node.body = replacementFor(node.body);
+ }
+
+ processContinuation(ir.Continuation node) {
+ node.body = replacementFor(node.body);
+ }
+
+ processBody(ir.Body node) {
+ node.body = replacementFor(node.body);
+ }
+}
+
+/// Visit a just-deleted subterm and unlink all [Reference]s in it.
+class RemovalVisitor extends ir.RecursiveVisitor {
+ processReference(ir.Reference reference) {
+ reference.unlink();
+ }
+}
+

Powered by Google App Engine
This is Rietveld 408576698