Chromium Code Reviews| 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 d1f51fcadabcd01738f0f0f8957c1e78c8f09fc7..4f0b61167accc1343cd7b74d2b8712ac319163c5 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,26 @@ class LetCont extends Expression implements InteriorNode { |
| accept(Visitor visitor) => visitor.visitLetCont(this); |
| } |
| +// Binding an exception handler. |
|
karlklose
2015/02/16 10:15:48
Make this a DartDoc comment ('///'), and maybe put
Kevin Millikin (Google)
2015/02/24 11:59:25
OK. But I'll just address the TODO before submitt
|
| +// |
| +// let handler h(v0 ...) = E0 in E1 |
| +// |
| +// The handler is a continuation which is implicitly the error continuation of |
| +// all the code in its body E1. The handler parameters represent the |
| +// exception and possibly the stack trace. (TODO(kmillikin): should we just |
| +// ensure that they always have two parameters?) It differs from let cont |
| +// binding a call continuation 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 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 |
| @@ -869,6 +889,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); |
| @@ -981,6 +1002,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); |
| @@ -1275,6 +1303,18 @@ class RegisterAllocator extends Visitor { |
| visit(node.body); |
| } |
| + void visitLetHandler(LetHandler node) { |
| + visit(node.handler); |
| + // Assign indices to unused handler parameters, because they should |
| + // not be eliminated. Then release all of them because they are not |
| + // live in the try block. |
| + node.handler.parameters.forEach((p) { |
|
floitsch
2015/02/16 14:54:07
We tend to type (even for closures) and not to abb
Kevin Millikin (Google)
2015/02/24 11:59:25
Done.
|
| + allocate(p); |
| + release(p); |
|
floitsch
2015/02/16 14:54:07
I'm not sure I understand (even with the comment).
Kevin Millikin (Google)
2015/02/24 11:59:25
The clearest name I can think of is "AllocateThenR
|
| + }); |
| + visit(node.body); |
| + } |
| + |
| void visitLetMutable(LetMutable node) { |
| visit(node.body); |
| visitReference(node.value); |