| Index: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| index f1d56163157da376b22d540653a20edb6d686c7e..285af06f126558136b9c40b925740a45c0a1c192 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| @@ -154,6 +154,24 @@ class LetCont extends Expression implements InteriorNode {
|
| accept(Visitor visitor) => visitor.visitLetCont(this);
|
| }
|
|
|
| +// Binding an exception handler.
|
| +//
|
| +// let handler h(v0, v1) = E0 in E1
|
| +//
|
| +// The handler is a two-argument (exception, stack trace) continuation which
|
| +// is implicitly the error continuation of all the code in its body E1.
|
| +// [LetHandler] differs from a [LetCont] binding in that it (1) has the
|
| +// runtime semantics of pushing/popping a handler from the dynamic exception
|
| +// handler stack and (2) it does not have any explicit invocations.
|
| +class LetHandler extends Expression implements InteriorNode {
|
| + Continuation handler;
|
| + Expression body;
|
| +
|
| + LetHandler(this.handler, this.body);
|
| +
|
| + accept(Visitor visitor) => visitor.visitLetHandler(this);
|
| +}
|
| +
|
| /// Binding mutable variables.
|
| ///
|
| /// let mutable v = P in E
|
| @@ -873,6 +891,7 @@ abstract class Visitor<T> {
|
| // Expressions.
|
| T visitLetPrim(LetPrim node) => visitExpression(node);
|
| T visitLetCont(LetCont node) => visitExpression(node);
|
| + T visitLetHandler(LetHandler node) => visitExpression(node);
|
| T visitLetMutable(LetMutable node) => visitExpression(node);
|
| T visitInvokeStatic(InvokeStatic node) => visitExpression(node);
|
| T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node);
|
| @@ -985,6 +1004,13 @@ abstract class RecursiveVisitor extends Visitor {
|
| visit(node.body);
|
| }
|
|
|
| + processLetHandler(LetHandler node) {}
|
| + visitLetHandler(LetHandler node) {
|
| + processLetHandler(node);
|
| + visit(node.handler);
|
| + visit(node.body);
|
| + }
|
| +
|
| processLetMutable(LetMutable node) {}
|
| visitLetMutable(LetMutable node) {
|
| processLetMutable(node);
|
| @@ -1279,6 +1305,22 @@ class RegisterAllocator extends Visitor {
|
| visit(node.body);
|
| }
|
|
|
| + void visitLetHandler(LetHandler node) {
|
| + visit(node.handler);
|
| + // Handler parameters that were not used in the handler body will not have
|
| + // had register indexes assigned. Assign them here, otherwise they will
|
| + // be eliminated later and they should not be (i.e., a catch clause that
|
| + // does not use the exception parameter should not have the exception
|
| + // parameter eliminated, because it would not be well-formed anymore).
|
| + // In any case release the parameter indexes because the parameters are
|
| + // not live in the try block.
|
| + node.handler.parameters.forEach((Parameter parameter) {
|
| + allocate(parameter);
|
| + release(parameter);
|
| + });
|
| + visit(node.body);
|
| + }
|
| +
|
| void visitLetMutable(LetMutable node) {
|
| visit(node.body);
|
| visitReference(node.value);
|
|
|