| 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 659b5e2f288f75b6f4e2d8ef46b682d026efa13b..4455ea197ae610285d44efe1ee847bb46ed16c37 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| @@ -1196,21 +1196,26 @@ class Branch extends TailExpression {
|
| /// boolean.
|
| bool isStrictCheck;
|
|
|
| - Branch.strict(Primitive condition,
|
| - Continuation trueCont,
|
| - Continuation falseCont)
|
| + Branch(Primitive condition,
|
| + Continuation trueCont,
|
| + Continuation falseCont,
|
| + {bool strict})
|
| : this.condition = new Reference<Primitive>(condition),
|
| trueContinuation = new Reference<Continuation>(trueCont),
|
| falseContinuation = new Reference<Continuation>(falseCont),
|
| - isStrictCheck = true;
|
| + isStrictCheck = strict {
|
| + assert(strict != null);
|
| + }
|
| +
|
| + Branch.strict(Primitive condition,
|
| + Continuation trueCont,
|
| + Continuation falseCont)
|
| + : this(condition, trueCont, falseCont, strict: true);
|
|
|
| Branch.loose(Primitive condition,
|
| Continuation trueCont,
|
| Continuation falseCont)
|
| - : this.condition = new Reference<Primitive>(condition),
|
| - trueContinuation = new Reference<Continuation>(trueCont),
|
| - falseContinuation = new Reference<Continuation>(falseCont),
|
| - this.isStrictCheck = false;
|
| + : this(condition, trueCont, falseCont, strict: false);
|
|
|
| accept(BlockVisitor visitor) => visitor.visitBranch(this);
|
|
|
| @@ -1909,6 +1914,43 @@ abstract class BlockVisitor<T> {
|
| }
|
| nodes.reversed.forEach(v.visit);
|
| }
|
| +
|
| + /// Visits block-level nodes in lexical pre-order.
|
| + ///
|
| + /// Continuations and function definitions are considered "block headers".
|
| + /// The block itself is the sequence of interior expressions in the body,
|
| + /// terminated by a tail expression.
|
| + ///
|
| + /// Each block is visited starting with its tail expression, then every
|
| + /// interior expression from bottom to top, and finally the block header
|
| + /// is visited.
|
| + ///
|
| + /// Blocks are visited in pre-order, so the body of a continuation is always
|
| + /// processed after its non-recursive invocation sites.
|
| + ///
|
| + /// The IR may be transformed during the traversal, but only the original
|
| + /// nodes will be visited.
|
| + static void traverseInPreOrder(FunctionDefinition root, BlockVisitor v) {
|
| + List<Continuation> stack = <Continuation>[];
|
| + void walkBlock(InteriorNode block) {
|
| + v.visit(block);
|
| + Expression node = block.body;
|
| + v.visit(node);
|
| + while (node.next != null) {
|
| + if (node is LetCont) {
|
| + stack.addAll(node.continuations);
|
| + } else if (node is LetHandler) {
|
| + stack.add(node.handler);
|
| + }
|
| + node = node.next;
|
| + v.visit(node);
|
| + }
|
| + }
|
| + walkBlock(root);
|
| + while (stack.isNotEmpty) {
|
| + walkBlock(stack.removeLast());
|
| + }
|
| + }
|
| }
|
|
|
| abstract class Visitor<T> implements BlockVisitor<T> {
|
|
|