| 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 430eb6dd903fe88925c594b3afb93092934807bd..1187618e0bbe5b7419f62db628c8c3e37cbea55a 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| @@ -124,20 +124,29 @@ class LetPrim extends Expression implements InteriorNode {
|
| }
|
|
|
|
|
| -/// Binding a continuation: 'let cont k(v) = E in E'. The bound continuation
|
| -/// is in scope in the body and the continuation parameter is in scope in the
|
| -/// continuation body.
|
| -/// During one-pass construction a LetCont with an empty continuation body is
|
| -/// used to represent the one-level context 'let cont k(v) = [] in E'.
|
| +/// Binding continuations.
|
| +///
|
| +/// let cont k0(v0 ...) = E0
|
| +/// k1(v1 ...) = E1
|
| +/// ...
|
| +/// in E
|
| +///
|
| +/// The bound continuations are in scope in the body and the continuation
|
| +/// parameters are in scope in the respective continuation bodies.
|
| +/// During one-pass construction a LetCont whose first continuation has an empty
|
| +/// body is used to represent the one-level context
|
| +/// 'let cont ... k(v) = [] ... in E'.
|
| class LetCont extends Expression implements InteriorNode {
|
| - Continuation continuation;
|
| + List<Continuation> continuations;
|
| Expression body;
|
|
|
| - LetCont(this.continuation, this.body);
|
| + LetCont(this.continuations, this.body);
|
|
|
| Expression plug(Expression expr) {
|
| - assert(continuation != null && continuation.body == null);
|
| - return continuation.body = expr;
|
| + assert(continuations != null &&
|
| + continuations.isNotEmpty &&
|
| + continuations.first.body == null);
|
| + return continuations.first.body = expr;
|
| }
|
|
|
| accept(Visitor visitor) => visitor.visitLetCont(this);
|
| @@ -156,7 +165,7 @@ abstract class Invoke {
|
| ///
|
| /// child.parent = parent;
|
| /// parent.body = child;
|
| -abstract class InteriorNode implements Node {
|
| +abstract class InteriorNode extends Node {
|
| Expression body;
|
| }
|
|
|
| @@ -608,6 +617,11 @@ class Continuation extends Definition<Continuation> implements InteriorNode {
|
| final List<Parameter> parameters;
|
| Expression body = null;
|
|
|
| + // In addition to a parent pointer to the containing LetCont, continuations
|
| + // have an index into the list of continuations bound by the LetCont. This
|
| + // gives constant-time access to the continuation from the parent.
|
| + int parent_index;
|
| +
|
| // A continuation is recursive if it has any recursive invocations.
|
| bool isRecursive = false;
|
|
|
| @@ -672,10 +686,9 @@ class ClosureVariable extends Definition {
|
| accept(Visitor v) => v.visitClosureVariable(this);
|
| }
|
|
|
| -class RunnableBody implements InteriorNode {
|
| +class RunnableBody extends InteriorNode {
|
| Expression body;
|
| final Continuation returnContinuation;
|
| - Node parent;
|
| RunnableBody(this.body, this.returnContinuation);
|
| accept(Visitor visitor) => visitor.visitRunnableBody(this);
|
| }
|
| @@ -722,20 +735,18 @@ class FunctionDefinition extends Node
|
|
|
| abstract class Initializer extends Node {}
|
|
|
| -class FieldInitializer implements Initializer {
|
| +class FieldInitializer extends Initializer {
|
| final FieldElement element;
|
| final RunnableBody body;
|
| - Node parent;
|
|
|
| FieldInitializer(this.element, this.body);
|
| accept(Visitor visitor) => visitor.visitFieldInitializer(this);
|
| }
|
|
|
| -class SuperInitializer implements Initializer {
|
| +class SuperInitializer extends Initializer {
|
| final ConstructorElement target;
|
| final List<RunnableBody> arguments;
|
| final Selector selector;
|
| - Node parent;
|
| SuperInitializer(this.target, this.arguments, this.selector);
|
| accept(Visitor visitor) => visitor.visitSuperInitializer(this);
|
| }
|
| @@ -903,7 +914,7 @@ abstract class RecursiveVisitor extends Visitor {
|
| processLetCont(LetCont node) {}
|
| visitLetCont(LetCont node) {
|
| processLetCont(node);
|
| - visit(node.continuation);
|
| + node.continuations.forEach(visit);
|
| visit(node.body);
|
| }
|
|
|
| @@ -1176,7 +1187,7 @@ class RegisterAllocator extends Visitor {
|
| }
|
|
|
| void visitSuperInitializer(SuperInitializer node) {
|
| - node.arguments.forEach((RunnableBody argument) => visit(argument.body));
|
| + node.arguments.forEach(visit);
|
| }
|
|
|
| void visitLetPrim(LetPrim node) {
|
| @@ -1186,7 +1197,7 @@ class RegisterAllocator extends Visitor {
|
| }
|
|
|
| void visitLetCont(LetCont node) {
|
| - visit(node.continuation);
|
| + node.continuations.forEach(visit);
|
| visit(node.body);
|
| }
|
|
|
|
|