| 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 8c5bf34b55f808e940905dfae91c7e40c761d332..37e91fe15c09214d1a826163661a57e93dcd4d6c 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| @@ -36,10 +36,51 @@ abstract class Node {
|
| /// invoke a [Continuation] with the result as argument. Alternatively, values
|
| /// that can be obtained without side-effects, divergence, or throwing
|
| /// exceptions can be built using a [LetPrim].
|
| +///
|
| +/// All subclasses implement exactly one of [CallExpression],
|
| +/// [InteriorExpression], or [TailExpression].
|
| abstract class Expression extends Node {
|
| InteriorNode get parent; // Only InteriorNodes may contain expressions.
|
|
|
| Expression plug(Expression expr) => throw 'impossible';
|
| +
|
| + /// The next expression in the basic block.
|
| + ///
|
| + /// For [InteriorExpression]s this is the body, for [CallExpressions] it is
|
| + /// the body of the continuation, and for [TailExpressions] it is `null`.
|
| + Expression get next;
|
| +}
|
| +
|
| +/// Represents a node with a child node, which can be accessed through the
|
| +/// `body` member. A typical usage is when removing a node from the CPS graph:
|
| +///
|
| +/// Node child = node.body;
|
| +/// InteriorNode parent = node.parent;
|
| +///
|
| +/// child.parent = parent;
|
| +/// parent.body = child;
|
| +abstract class InteriorNode extends Node {
|
| + Expression get body;
|
| + void set body(Expression body);
|
| +}
|
| +
|
| +/// An expression with a subexpression as body.
|
| +abstract class InteriorExpression extends Expression implements InteriorNode {
|
| + Expression get next => body;
|
| +}
|
| +
|
| +/// An expression that passes a continuation to a call.
|
| +abstract class CallExpression extends Expression {
|
| + Reference<Continuation> get continuation;
|
| + Expression get next => continuation.definition.body;
|
| +}
|
| +
|
| +/// An expression without a continuation or a subexpression body.
|
| +///
|
| +/// These break straight-line control flow and can be throught of as ending a
|
| +/// basic block.
|
| +abstract class TailExpression extends Expression {
|
| + Expression get next => null;
|
| }
|
|
|
| /// The base class of things that variables can refer to: primitives,
|
| @@ -147,7 +188,7 @@ class Reference<T extends Definition<T>> {
|
| ///
|
| /// During one-pass construction a LetPrim with an empty body is used to
|
| /// represent the one-hole context `let val x = V in []`.
|
| -class LetPrim extends Expression implements InteriorNode {
|
| +class LetPrim extends InteriorExpression {
|
| Primitive primitive;
|
| Expression body;
|
|
|
| @@ -175,7 +216,7 @@ class LetPrim extends Expression implements InteriorNode {
|
| /// During one-pass construction a LetCont whose first continuation has an empty
|
| /// body is used to represent the one-hole context
|
| /// `let cont ... k(v) = [] ... in E`.
|
| -class LetCont extends Expression implements InteriorNode {
|
| +class LetCont extends InteriorExpression {
|
| List<Continuation> continuations;
|
| Expression body;
|
|
|
| @@ -206,7 +247,7 @@ class LetCont extends Expression implements InteriorNode {
|
| // [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 {
|
| +class LetHandler extends InteriorExpression {
|
| Continuation handler;
|
| Expression body;
|
|
|
| @@ -224,7 +265,7 @@ class LetHandler extends Expression implements InteriorNode {
|
| /// to prevent unrestricted use of references to them. During one-pass
|
| /// construction, a [LetMutable] with an empty body is use to represent the
|
| /// one-hole context 'let mutable v = P in []'.
|
| -class LetMutable extends Expression implements InteriorNode {
|
| +class LetMutable extends InteriorExpression {
|
| final MutableVariable variable;
|
| final Reference<Primitive> value;
|
| Expression body;
|
| @@ -239,25 +280,6 @@ class LetMutable extends Expression implements InteriorNode {
|
| accept(Visitor visitor) => visitor.visitLetMutable(this);
|
| }
|
|
|
| -abstract class Invoke implements Expression {
|
| - Selector get selector;
|
| - List<Reference<Primitive>> get arguments;
|
| - Reference<Continuation> get continuation;
|
| -}
|
| -
|
| -/// Represents a node with a child node, which can be accessed through the
|
| -/// `body` member. A typical usage is when removing a node from the CPS graph:
|
| -///
|
| -/// Node child = node.body;
|
| -/// InteriorNode parent = node.parent;
|
| -///
|
| -/// child.parent = parent;
|
| -/// parent.body = child;
|
| -abstract class InteriorNode extends Node {
|
| - Expression get body;
|
| - void set body(Expression body);
|
| -}
|
| -
|
| /// Invoke a static function.
|
| ///
|
| /// All optional arguments declared by [target] are passed in explicitly, and
|
| @@ -266,7 +288,7 @@ abstract class InteriorNode extends Node {
|
| /// Discussion:
|
| /// All information in the [selector] is technically redundant; it will likely
|
| /// be removed.
|
| -class InvokeStatic extends Expression implements Invoke {
|
| +class InvokeStatic extends CallExpression {
|
| final FunctionElement target;
|
| final Selector selector;
|
| final List<Reference<Primitive>> arguments;
|
| @@ -299,7 +321,7 @@ class InvokeStatic extends Expression implements Invoke {
|
| ///
|
| /// The [selector] records the names of named arguments. The value of named
|
| /// arguments occur at the end of the [arguments] list, in normalized order.
|
| -class InvokeMethod extends Expression implements Invoke {
|
| +class InvokeMethod extends CallExpression {
|
| Reference<Primitive> receiver;
|
| Selector selector;
|
| TypeMask mask;
|
| @@ -349,7 +371,7 @@ class InvokeMethod extends Expression implements Invoke {
|
| ///
|
| /// All optional arguments declared by [target] are passed in explicitly, and
|
| /// occur at the end of [arguments] list, in normalized order.
|
| -class InvokeMethodDirectly extends Expression implements Invoke {
|
| +class InvokeMethodDirectly extends CallExpression {
|
| Reference<Primitive> receiver;
|
| final FunctionElement target;
|
| final Selector selector;
|
| @@ -385,7 +407,7 @@ class InvokeMethodDirectly extends Expression implements Invoke {
|
| ///
|
| /// Note that [InvokeConstructor] does it itself allocate an object.
|
| /// The invoked constructor will do that using [CreateInstance].
|
| -class InvokeConstructor extends Expression implements Invoke {
|
| +class InvokeConstructor extends CallExpression {
|
| final DartType type;
|
| final ConstructorElement target;
|
| final List<Reference<Primitive>> arguments;
|
| @@ -451,7 +473,7 @@ class TypeTest extends Primitive {
|
| /// [value], which is typically in scope in the continuation. However, it might
|
| /// simplify type propagation, since a better type can be computed for the
|
| /// continuation parameter without needing flow-sensitive analysis.
|
| -class TypeCast extends Expression {
|
| +class TypeCast extends CallExpression {
|
| Reference<Primitive> value;
|
| final DartType type;
|
|
|
| @@ -490,7 +512,7 @@ class ApplyBuiltinOperator extends Primitive {
|
| ///
|
| /// Throw is an expression, i.e., it always occurs in tail position with
|
| /// respect to a body or expression.
|
| -class Throw extends Expression {
|
| +class Throw extends TailExpression {
|
| Reference<Primitive> value;
|
|
|
| Throw(Primitive value) : value = new Reference<Primitive>(value);
|
| @@ -503,7 +525,7 @@ class Throw extends Expression {
|
| /// Rethrow can only occur inside a continuation bound by [LetHandler]. It
|
| /// implicitly throws the exception parameter of the enclosing handler with
|
| /// the same stack trace as the enclosing handler.
|
| -class Rethrow extends Expression {
|
| +class Rethrow extends TailExpression {
|
| accept(Visitor visitor) => visitor.visitRethrow(this);
|
| }
|
|
|
| @@ -528,7 +550,7 @@ class NonTailThrow extends Primitive {
|
| ///
|
| /// This can be placed as the body of a call continuation, when the caller is
|
| /// known never to invoke it, e.g. because the calling expression always throws.
|
| -class Unreachable extends Expression {
|
| +class Unreachable extends TailExpression {
|
| accept(Visitor visitor) => visitor.visitUnreachable(this);
|
| }
|
|
|
| @@ -557,7 +579,7 @@ class GetMutableVariable extends Primitive {
|
| /// values. This can be seen as a dereferencing assignment:
|
| ///
|
| /// { [variable] := [value]; [body] }
|
| -class SetMutableVariable extends Expression implements InteriorNode {
|
| +class SetMutableVariable extends InteriorExpression {
|
| final Reference<MutableVariable> variable;
|
| final Reference<Primitive> value;
|
| Expression body;
|
| @@ -575,7 +597,7 @@ class SetMutableVariable extends Expression implements InteriorNode {
|
| }
|
|
|
| /// Invoke a continuation in tail position.
|
| -class InvokeContinuation extends Expression {
|
| +class InvokeContinuation extends TailExpression {
|
| Reference<Continuation> continuation;
|
| List<Reference<Primitive>> arguments;
|
| SourceInformation sourceInformation;
|
| @@ -627,7 +649,7 @@ class IsTrue extends Condition {
|
| /// Choose between a pair of continuations based on a condition value.
|
| ///
|
| /// The two continuations must not declare any parameters.
|
| -class Branch extends Expression {
|
| +class Branch extends TailExpression {
|
| final Condition condition;
|
| final Reference<Continuation> trueContinuation;
|
| final Reference<Continuation> falseContinuation;
|
| @@ -640,7 +662,7 @@ class Branch extends Expression {
|
| }
|
|
|
| /// Directly assigns to a field on a given object.
|
| -class SetField extends Expression implements InteriorNode {
|
| +class SetField extends InteriorExpression {
|
| final Reference<Primitive> object;
|
| FieldElement field;
|
| final Reference<Primitive> value;
|
| @@ -756,7 +778,7 @@ class GetStatic extends Primitive {
|
| }
|
|
|
| /// Sets the value of a static field.
|
| -class SetStatic extends Expression implements InteriorNode {
|
| +class SetStatic extends InteriorExpression {
|
| final FieldElement element;
|
| final Reference<Primitive> value;
|
| Expression body;
|
| @@ -779,7 +801,7 @@ class SetStatic extends Expression implements InteriorNode {
|
| /// and assigned to the field.
|
| ///
|
| /// [continuation] is then invoked with the value of the field as argument.
|
| -class GetLazyStatic extends Expression {
|
| +class GetLazyStatic extends CallExpression {
|
| final FieldElement element;
|
| final Reference<Continuation> continuation;
|
| final SourceInformation sourceInformation;
|
| @@ -855,22 +877,18 @@ class CreateInvocationMirror extends Primitive {
|
| bool get isSafeForReordering => true;
|
| }
|
|
|
| -class ForeignCode extends Expression {
|
| +class ForeignCode extends CallExpression {
|
| final js.Template codeTemplate;
|
| final TypeMask type;
|
| final List<Reference<Primitive>> arguments;
|
| final native.NativeBehavior nativeBehavior;
|
| final FunctionElement dependency;
|
| -
|
| - /// The continuation, if the foreign code is not a JavaScript 'throw',
|
| - /// otherwise null.
|
| final Reference<Continuation> continuation;
|
|
|
| ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments,
|
| - this.nativeBehavior, {Continuation continuation, this.dependency})
|
| - : arguments = _referenceList(arguments),
|
| - continuation = continuation == null ? null
|
| - : new Reference<Continuation>(continuation);
|
| + this.nativeBehavior, Continuation continuation, {this.dependency})
|
| + : this.arguments = _referenceList(arguments),
|
| + this.continuation = new Reference<Continuation>(continuation);
|
|
|
| accept(Visitor visitor) => visitor.visitForeignCode(this);
|
| }
|
| @@ -992,7 +1010,7 @@ class Continuation extends Definition<Continuation> implements InteriorNode {
|
| class MutableVariable extends Definition {
|
| Entity hint;
|
|
|
| - MutableVariable(this.hint);
|
| +MutableVariable(this.hint);
|
|
|
| accept(Visitor v) => v.visitMutableVariable(this);
|
| }
|
|
|