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 cbb45f0e81aa9504dbe05bdf5a26d544672b77a4..0c28fa4cc9a53283df59ac6913a62231fc5a9492 100644 |
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
@@ -28,16 +28,7 @@ abstract class Node { |
static int _usedHashCodes = 0; |
final int hashCode = ++_usedHashCodes; |
- Node() { |
- setParentPointers(); |
- } |
- |
accept(Visitor visitor); |
- |
- /// Updates the [parent] of the immediate children to refer to this node. |
- /// |
- /// All constructors call this method to initialize parent pointers. |
- void setParentPointers(); |
} |
/// Expressions can be evaluated, and may diverge, throw, and/or have |
@@ -327,13 +318,9 @@ class LetPrim extends InteriorExpression { |
} |
accept(Visitor visitor) => visitor.visitLetPrim(this); |
- |
- void setParentPointers() { |
- primitive.parent = this; |
- if (body != null) body.parent = this; |
- } |
} |
+ |
/// Binding continuations. |
/// |
/// let cont k0(v0 ...) = E0 |
@@ -367,11 +354,6 @@ class LetCont extends InteriorExpression { |
} |
accept(Visitor visitor) => visitor.visitLetCont(this); |
- |
- void setParentPointers() { |
- _setParentsOnNodes(continuations, this); |
- if (body != null) body.parent = this; |
- } |
} |
// Binding an exception handler. |
@@ -390,11 +372,6 @@ class LetHandler extends InteriorExpression { |
LetHandler(this.handler, this.body); |
accept(Visitor visitor) => visitor.visitLetHandler(this); |
- |
- void setParentPointers() { |
- handler.parent = this; |
- if (body != null) body.parent = this; |
- } |
} |
/// Binding mutable variables. |
@@ -419,12 +396,6 @@ class LetMutable extends InteriorExpression { |
} |
accept(Visitor visitor) => visitor.visitLetMutable(this); |
- |
- void setParentPointers() { |
- variable.parent = this; |
- value.parent = this; |
- if (body != null) body.parent = this; |
- } |
} |
/// Invoke a static function. |
@@ -457,11 +428,6 @@ class InvokeStatic extends CallExpression { |
[this.sourceInformation]); |
accept(Visitor visitor) => visitor.visitInvokeStatic(this); |
- |
- void setParentPointers() { |
- _setParentsOnList(arguments, this); |
- continuation.parent = this; |
- } |
} |
/// Invoke a method on an object. |
@@ -513,12 +479,6 @@ class InvokeMethod extends CallExpression { |
this.sourceInformation); |
accept(Visitor visitor) => visitor.visitInvokeMethod(this); |
- |
- void setParentPointers() { |
- receiver.parent = this; |
- _setParentsOnList(arguments, this); |
- continuation.parent = this; |
- } |
} |
/// Invoke [target] on [receiver], bypassing dispatch and override semantics. |
@@ -559,12 +519,6 @@ class InvokeMethodDirectly extends CallExpression { |
this.continuation = new Reference<Continuation>(continuation); |
accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); |
- |
- void setParentPointers() { |
- receiver.parent = this; |
- _setParentsOnList(arguments, this); |
- continuation.parent = this; |
- } |
} |
/// Non-const call to a constructor. |
@@ -600,11 +554,6 @@ class InvokeConstructor extends CallExpression { |
continuation = new Reference<Continuation>(cont); |
accept(Visitor visitor) => visitor.visitInvokeConstructor(this); |
- |
- void setParentPointers() { |
- _setParentsOnList(arguments, this); |
- continuation.parent = this; |
- } |
} |
/// An alias for [value] in a context where the value is known to satisfy |
@@ -627,10 +576,6 @@ class Refinement extends Primitive { |
accept(Visitor visitor) => visitor.visitRefinement(this); |
Primitive get effectiveDefinition => value.definition.effectiveDefinition; |
- |
- void setParentPointers() { |
- value.parent = this; |
- } |
} |
/// An "is" type test. |
@@ -673,12 +618,6 @@ class TypeTest extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() { |
- value.parent = this; |
- _setParentsOnList(typeArguments, this); |
- if (interceptor != null) interceptor.parent = this; |
- } |
} |
/// An "is" type test for a raw type, performed by testing a flag property. |
@@ -695,10 +634,6 @@ class TypeTestViaFlag extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() { |
- interceptor.parent = this; |
- } |
} |
/// An "as" type cast. |
@@ -728,10 +663,6 @@ class TypeCast extends CallExpression { |
this.continuation = new Reference<Continuation>(cont); |
accept(Visitor visitor) => visitor.visitTypeCast(this); |
- |
- void setParentPointers() { |
- value.parent = this; |
- } |
} |
/// Apply a built-in operator. |
@@ -751,10 +682,6 @@ class ApplyBuiltinOperator extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() { |
- _setParentsOnList(arguments, this); |
- } |
} |
/// Apply a built-in method. |
@@ -780,11 +707,6 @@ class ApplyBuiltinMethod extends Primitive { |
bool get isSafeForElimination => false; |
bool get isSafeForReordering => false; |
- |
- void setParentPointers() { |
- receiver.parent = this; |
- _setParentsOnList(arguments, this); |
- } |
} |
/// Throw a value. |
@@ -797,10 +719,6 @@ class Throw extends TailExpression { |
Throw(Primitive value) : value = new Reference<Primitive>(value); |
accept(Visitor visitor) => visitor.visitThrow(this); |
- |
- void setParentPointers() { |
- value.parent = this; |
- } |
} |
/// Rethrow |
@@ -810,7 +728,6 @@ class Throw extends TailExpression { |
/// the same stack trace as the enclosing handler. |
class Rethrow extends TailExpression { |
accept(Visitor visitor) => visitor.visitRethrow(this); |
- void setParentPointers() {} |
} |
/// An expression that is known to be unreachable. |
@@ -819,7 +736,6 @@ class Rethrow extends TailExpression { |
/// known never to invoke it, e.g. because the calling expression always throws. |
class Unreachable extends TailExpression { |
accept(Visitor visitor) => visitor.visitUnreachable(this); |
- void setParentPointers() {} |
} |
/// Gets the value from a [MutableVariable]. |
@@ -839,10 +755,6 @@ class GetMutable extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => false; |
- |
- void setParentPointers() { |
- variable.parent = this; |
- } |
} |
/// Assign a [MutableVariable]. |
@@ -863,11 +775,6 @@ class SetMutable extends Primitive { |
bool get isSafeForElimination => false; |
bool get isSafeForReordering => false; |
- |
- void setParentPointers() { |
- variable.parent = this; |
- value.parent = this; |
- } |
} |
/// Invoke a continuation in tail position. |
@@ -906,11 +813,6 @@ class InvokeContinuation extends TailExpression { |
sourceInformation = null; |
accept(Visitor visitor) => visitor.visitInvokeContinuation(this); |
- |
- void setParentPointers() { |
- if (continuation != null) continuation.parent = this; |
- if (arguments != null) _setParentsOnList(arguments, this); |
- } |
} |
/// Choose between a pair of continuations based on a condition value. |
@@ -945,12 +847,6 @@ class Branch extends TailExpression { |
this.isStrictCheck = false; |
accept(Visitor visitor) => visitor.visitBranch(this); |
- |
- void setParentPointers() { |
- condition.parent = this; |
- trueContinuation.parent = this; |
- falseContinuation.parent = this; |
- } |
} |
/// Directly assigns to a field on a given object. |
@@ -967,11 +863,6 @@ class SetField extends Primitive { |
bool get isSafeForElimination => false; |
bool get isSafeForReordering => false; |
- |
- void setParentPointers() { |
- object.parent = this; |
- value.parent = this; |
- } |
} |
/// Directly reads from a field on a given object. |
@@ -995,10 +886,6 @@ class GetField extends Primitive { |
bool get isSafeForReordering => false; |
toString() => 'GetField($field)'; |
- |
- void setParentPointers() { |
- object.parent = this; |
- } |
} |
/// Get the length of a string or native list. |
@@ -1014,10 +901,6 @@ class GetLength extends Primitive { |
bool get isSafeForReordering => false; |
accept(Visitor v) => v.visitGetLength(this); |
- |
- void setParentPointers() { |
- object.parent = this; |
- } |
} |
/// Read an entry from a string or native list. |
@@ -1039,11 +922,6 @@ class GetIndex extends Primitive { |
bool get isSafeForReordering => false; |
accept(Visitor v) => v.visitGetIndex(this); |
- |
- void setParentPointers() { |
- object.parent = this; |
- index.parent = this; |
- } |
} |
/// Set an entry on a native list. |
@@ -1065,12 +943,6 @@ class SetIndex extends Primitive { |
bool get isSafeForReordering => false; |
accept(Visitor v) => v.visitSetIndex(this); |
- |
- void setParentPointers() { |
- object.parent = this; |
- index.parent = this; |
- value.parent = this; |
- } |
} |
/// Reads the value of a static field or tears off a static method. |
@@ -1091,8 +963,6 @@ class GetStatic extends Primitive { |
bool get isSafeForReordering { |
return element is FunctionElement || element.isFinal; |
} |
- |
- void setParentPointers() {} |
} |
/// Sets the value of a static field. |
@@ -1108,10 +978,6 @@ class SetStatic extends Primitive { |
bool get isSafeForElimination => false; |
bool get isSafeForReordering => false; |
- |
- void setParentPointers() { |
- value.parent = this; |
- } |
} |
/// Reads the value of a lazily initialized static field. |
@@ -1131,10 +997,6 @@ class GetLazyStatic extends CallExpression { |
: continuation = new Reference<Continuation>(continuation); |
accept(Visitor visitor) => visitor.visitGetLazyStatic(this); |
- |
- void setParentPointers() { |
- continuation.parent = this; |
- } |
} |
/// Creates an object for holding boxed variables captured by a closure. |
@@ -1143,8 +1005,6 @@ class CreateBox extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() {} |
} |
/// Creates an instance of a class and initializes its fields and runtime type |
@@ -1177,11 +1037,6 @@ class CreateInstance extends Primitive { |
bool get isSafeForReordering => true; |
toString() => 'CreateInstance($classElement)'; |
- |
- void setParentPointers() { |
- _setParentsOnList(arguments, this); |
- if (typeInformation != null) _setParentsOnList(typeInformation, this); |
- } |
} |
class Interceptor extends Primitive { |
@@ -1208,10 +1063,6 @@ class Interceptor extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() { |
- input.parent = this; |
- } |
} |
/// Create an instance of [Invocation] for use in a call to `noSuchMethod`. |
@@ -1226,10 +1077,6 @@ class CreateInvocationMirror extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() { |
- _setParentsOnList(arguments, this); |
- } |
} |
class ForeignCode extends CallExpression { |
@@ -1246,11 +1093,6 @@ class ForeignCode extends CallExpression { |
this.continuation = new Reference<Continuation>(continuation); |
accept(Visitor visitor) => visitor.visitForeignCode(this); |
- |
- void setParentPointers() { |
- _setParentsOnList(arguments, this); |
- continuation.parent = this; |
- } |
} |
class Constant extends Primitive { |
@@ -1265,8 +1107,6 @@ class Constant extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() {} |
} |
class LiteralList extends Primitive { |
@@ -1281,10 +1121,6 @@ class LiteralList extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() { |
- _setParentsOnList(values, this); |
- } |
} |
class LiteralMapEntry { |
@@ -1306,13 +1142,6 @@ class LiteralMap extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() { |
- for (LiteralMapEntry entry in entries) { |
- entry.key.parent = this; |
- entry.value.parent = this; |
- } |
- } |
} |
/// Currently unused. |
@@ -1334,8 +1163,6 @@ class CreateFunction extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() {} |
} |
class Parameter extends Primitive { |
@@ -1343,14 +1170,18 @@ class Parameter extends Primitive { |
super.hint = hint; |
} |
+ // In addition to a parent pointer to the containing Continuation or |
+ // FunctionDefinition, parameters have an index into the list of parameters |
+ // bound by the parent. This gives constant-time access to the continuation |
+ // from the parent. |
+ int parentIndex; |
+ |
accept(Visitor visitor) => visitor.visitParameter(this); |
String toString() => 'Parameter(${hint == null ? null : hint.name})'; |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() {} |
} |
/// Continuations are normally bound by 'let cont'. A continuation with one |
@@ -1360,6 +1191,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; |
@@ -1372,11 +1208,6 @@ class Continuation extends Definition<Continuation> implements InteriorNode { |
isRecursive = false; |
accept(Visitor visitor) => visitor.visitContinuation(this); |
- |
- void setParentPointers() { |
- _setParentsOnNodes(parameters, this); |
- if (body != null) body.parent = this; |
- } |
} |
/// Common interface for [Primitive] and [MutableVariable]. |
@@ -1394,8 +1225,6 @@ class MutableVariable extends Variable<MutableVariable> { |
MutableVariable(this.hint); |
accept(Visitor v) => v.visitMutableVariable(this); |
- |
- void setParentPointers() {} |
} |
/// A function definition, consisting of parameters and a body. |
@@ -1416,13 +1245,6 @@ class FunctionDefinition extends InteriorNode { |
this.body); |
accept(Visitor visitor) => visitor.visitFunctionDefinition(this); |
- |
- void setParentPointers() { |
- if (thisParameter != null) thisParameter.parent = this; |
- _setParentsOnNodes(parameters, this); |
- returnContinuation.parent = this; |
- if (body != null) body.parent = this; |
- } |
} |
/// Converts the internal representation of a type to a Dart object of type |
@@ -1442,10 +1264,6 @@ class ReifyRuntimeType extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() { |
- value.parent = this; |
- } |
} |
/// Read the value the type variable [variable] from the target object. |
@@ -1466,10 +1284,6 @@ class ReadTypeVariable extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() { |
- target.parent = this; |
- } |
} |
/// Representation of a closed type (that is, a type without type variables). |
@@ -1495,10 +1309,6 @@ class TypeExpression extends Primitive { |
bool get isSafeForElimination => true; |
bool get isSafeForReordering => true; |
- |
- void setParentPointers() { |
- _setParentsOnList(arguments, this); |
- } |
} |
class Await extends CallExpression { |
@@ -1513,11 +1323,6 @@ class Await extends CallExpression { |
accept(Visitor visitor) { |
return visitor.visitAwait(this); |
} |
- |
- void setParentPointers() { |
- input.parent = this; |
- continuation.parent = this; |
- } |
} |
class Yield extends CallExpression { |
@@ -1533,29 +1338,12 @@ class Yield extends CallExpression { |
accept(Visitor visitor) { |
return visitor.visitYield(this); |
} |
- |
- void setParentPointers() { |
- input.parent = this; |
- continuation.parent = this; |
- } |
} |
List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |
return definitions.map((e) => new Reference<Primitive>(e)).toList(); |
} |
-void _setParentsOnNodes(List<Node> nodes, Node parent) { |
- for (Node node in nodes) { |
- node.parent = parent; |
- } |
-} |
- |
-void _setParentsOnList(List<Reference> nodes, Node parent) { |
- for (Reference node in nodes) { |
- node.parent = parent; |
- } |
-} |
- |
abstract class Visitor<T> { |
const Visitor(); |
@@ -1617,20 +1405,13 @@ abstract class Visitor<T> { |
T visitForeignCode(ForeignCode node); |
} |
-/// Recursively visits all children of a CPS term. |
-/// |
-/// The user of the class is responsible for avoiding stack overflows from |
-/// deep recursion, e.g. by overriding methods to cut off recursion at certain |
-/// points. |
-/// |
-/// All recursive invocations occur through the [visit] method, which the |
-/// subclass may override as a generic way to control the visitor without |
-/// overriding all visitor methods. |
+/// Visits all non-recursive children of a CPS term, i.e. anything |
+/// not of type [Expression] or [Continuation]. |
/// |
/// The `process*` methods are called in pre-order for every node visited. |
/// These can be overridden without disrupting the visitor traversal. |
-class DeepRecursiveVisitor implements Visitor { |
- const DeepRecursiveVisitor(); |
+class LeafVisitor implements Visitor { |
+ const LeafVisitor(); |
visit(Node node) => node.accept(this); |
@@ -1642,36 +1423,25 @@ class DeepRecursiveVisitor implements Visitor { |
if (node.thisParameter != null) visit(node.thisParameter); |
node.parameters.forEach(visit); |
visit(node.returnContinuation); |
- visit(node.body); |
- } |
- |
- processContinuation(Continuation node) {} |
- visitContinuation(Continuation node) { |
- processContinuation(node); |
- node.parameters.forEach(visit); |
- if (node.body != null) visit(node.body); |
} |
// Expressions. |
+ |
processLetPrim(LetPrim node) {} |
visitLetPrim(LetPrim node) { |
processLetPrim(node); |
visit(node.primitive); |
- visit(node.body); |
} |
processLetCont(LetCont node) {} |
visitLetCont(LetCont node) { |
processLetCont(node); |
node.continuations.forEach(visit); |
- visit(node.body); |
} |
processLetHandler(LetHandler node) {} |
visitLetHandler(LetHandler node) { |
processLetHandler(node); |
- visit(node.handler); |
- visit(node.body); |
} |
processLetMutable(LetMutable node) {} |
@@ -1679,7 +1449,6 @@ class DeepRecursiveVisitor implements Visitor { |
processLetMutable(node); |
visit(node.variable); |
processReference(node.value); |
- visit(node.body); |
} |
processInvokeStatic(InvokeStatic node) {} |
@@ -1815,6 +1584,12 @@ class DeepRecursiveVisitor implements Visitor { |
processParameter(node); |
} |
+ processContinuation(Continuation node) {} |
+ visitContinuation(Continuation node) { |
+ processContinuation(node); |
+ node.parameters.forEach(visitParameter); |
+ } |
+ |
processInterceptor(Interceptor node) {} |
visitInterceptor(Interceptor node) { |
processInterceptor(node); |
@@ -1975,7 +1750,7 @@ typedef void StackAction(); |
/// |
/// Subclasses should not override the `visit` methods for the nodes that have |
/// a `traverse` method. |
-class TrampolineRecursiveVisitor extends DeepRecursiveVisitor { |
+class RecursiveVisitor extends LeafVisitor { |
List<StackAction> _stack = <StackAction>[]; |
void pushAction(StackAction callback) { |
@@ -2070,7 +1845,7 @@ class TrampolineRecursiveVisitor extends DeepRecursiveVisitor { |
} |
/// Visit a just-deleted subterm and unlink all [Reference]s in it. |
-class RemovalVisitor extends TrampolineRecursiveVisitor { |
+class RemovalVisitor extends RecursiveVisitor { |
processReference(Reference reference) { |
reference.unlink(); |
} |