Chromium Code Reviews| Index: pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart |
| diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart |
| index 2f7e5fe7e2e94fdfd1e17765259374304641d032..5304abe1366298d212eb235723ffa464d8d5babc 100644 |
| --- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart |
| +++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart |
| @@ -57,6 +57,12 @@ class Builder extends cps_ir.Visitor<Node> { |
| // is the mapping from continuations to labels. |
| final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; |
| + // Code for continuations with exactly one use is inlined at the use site. |
|
karlklose
2015/02/16 10:15:48
Use '///'.
|
| + // This is not safe if the code is moved inside the scope of an exception |
| + // handler (i.e., into a try block). We keep a stack of singly-referenced |
| + // continuations that are in scope without crossing a binding for a handler. |
| + List<cps_ir.Continuation> safeForHandlers = <cps_ir.Continuation>[]; |
| + |
| ExecutableElement currentElement; |
| cps_ir.Continuation returnContinuation; |
| @@ -370,12 +376,16 @@ class Builder extends cps_ir.Visitor<Node> { |
| Statement visitLetCont(cps_ir.LetCont node) { |
| // Introduce labels for continuations that need them. |
| + int safeForHandlersLengthOnEntry = safeForHandlers.length; |
| for (cps_ir.Continuation continuation in node.continuations) { |
| if (continuation.hasMultipleUses) { |
| labels[continuation] = new Label(); |
| + } else { |
| + safeForHandlers.add(continuation); |
| } |
| } |
| Statement body = visit(node.body); |
| + safeForHandlers.length = safeForHandlersLengthOnEntry; |
| // Continuations are bound at the same level, but they have to be |
| // translated as if nested. This is because the body can invoke any |
| // of them from anywhere, so it must be nested inside all of them. |
| @@ -399,6 +409,17 @@ class Builder extends cps_ir.Visitor<Node> { |
| return current; |
| } |
| + Statement visitLetHandler(cps_ir.LetHandler node) { |
| + List<cps_ir.Continuation> saved = safeForHandlers; |
| + safeForHandlers = <cps_ir.Continuation>[]; |
| + Statement tryBody = visit(node.body); |
| + safeForHandlers = saved; |
| + List<Variable> catchParameters = |
| + node.handler.parameters.map(getVariable).toList(); |
| + Statement catchBody = visit(node.handler.body); |
| + return new TryStatement(tryBody, catchParameters, catchBody); |
| + } |
| + |
| Statement visitInvokeStatic(cps_ir.InvokeStatic node) { |
| // Calls are translated to direct style. |
| List<Expression> arguments = translateArguments(node.arguments); |
| @@ -507,9 +528,13 @@ class Builder extends cps_ir.Visitor<Node> { |
| ? new Continue(labels[cont]) |
| : new WhileTrue(labels[cont], visit(cont.body)); |
| } else { |
| - return cont.hasExactlyOneUse |
| - ? visit(cont.body) |
| - : new Break(labels[cont]); |
| + if (cont.hasExactlyOneUse) { |
| + if (safeForHandlers.contains(cont)) { |
| + return visit(cont.body); |
| + } |
| + labels[cont] = new Label(); |
|
asgerf
2015/02/20 10:10:08
I think you should create the Label inside visitLe
Kevin Millikin (Google)
2015/02/25 11:06:36
I agree that the whole thing is complicated.
* Th
asgerf
2015/02/25 11:55:11
I guess we could also just let the statement rewri
|
| + } |
| + return new Break(labels[cont]); |
| } |
| }); |
| } |