Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(204)

Unified Diff: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart

Issue 1458703007: dart2js cps: Refactor CallExpressions into Primitives. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rebase Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 50e84bdfec263e44e83d33db2ab1904f3cc69187..f80d8d4a127add876af20edac72d2b71c857ad69 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -123,12 +123,6 @@ abstract class InteriorExpression extends Expression implements InteriorNode {
}
}
-/// 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 thought of as ending a
@@ -149,19 +143,21 @@ abstract class Definition<T extends Definition<T>> extends Node {
bool get hasAtLeastOneUse => firstRef != null;
bool get hasMultipleUses => !hasAtMostOneUse;
- void substituteFor(Definition<T> other) {
- if (other == this) return;
- if (other.hasNoUses) return;
- Reference<T> previous, current = other.firstRef;
+ void replaceUsesWith(Definition<T> newDefinition) {
+ if (newDefinition == this) return;
+ if (hasNoUses) return;
+ Reference<T> previous, current = firstRef;
do {
- current.definition = this;
+ current.definition = newDefinition;
previous = current;
current = current.next;
} while (current != null);
- previous.next = firstRef;
- if (firstRef != null) firstRef.previous = previous;
- firstRef = other.firstRef;
- other.firstRef = null;
+ previous.next = newDefinition.firstRef;
+ if (newDefinition.firstRef != null) {
+ newDefinition.firstRef.previous = previous;
+ }
+ newDefinition.firstRef = firstRef;
+ firstRef = null;
}
}
@@ -268,6 +264,37 @@ abstract class Primitive extends Variable<Primitive> {
assert(hasNoUses);
RemovalVisitor.remove(this);
}
+
+ /// Replaces this definition, both at the binding site and at all uses sites.
+ ///
+ /// This can be thought of as changing the definition of a `let` while
+ /// preserving the variable name:
+ ///
+ /// let x = OLD in BODY
+ /// ==>
+ /// let x = NEW in BODY
+ ///
+ void replaceWith(Primitive newDefinition) {
+ assert(this is! Parameter);
+ assert(newDefinition is! Parameter);
+ assert(newDefinition.parent == null);
+ replaceUsesWith(newDefinition);
+ destroy();
+ LetPrim let = parent;
+ let.primitive = newDefinition;
+ newDefinition.parent = let;
+ newDefinition.useElementAsHint(hint);
+ }
+}
+
+/// A primitive that is generally not safe for elimination, but may be marked
+/// as safe by type propagation
+//
+// TODO(asgerf): Store the flag in a bitmask in [Primitive] and get rid of this
+// class.
+abstract class UnsafePrimitive extends Primitive {
+ bool isSafeForElimination = false;
+ bool isSafeForReordering = false;
}
/// Operands to invocations and primitives are always variables. They point to
@@ -435,35 +462,47 @@ class LetMutable extends InteriorExpression {
/// Discussion:
/// All information in the [selector] is technically redundant; it will likely
/// be removed.
-class InvokeStatic extends CallExpression {
+class InvokeStatic extends UnsafePrimitive {
final FunctionElement target;
final Selector selector;
final List<Reference<Primitive>> arguments;
- final Reference<Continuation> continuation;
final SourceInformation sourceInformation;
InvokeStatic(this.target,
this.selector,
List<Primitive> args,
- Continuation cont,
[this.sourceInformation])
- : arguments = _referenceList(args),
- continuation = new Reference<Continuation>(cont);
+ : arguments = _referenceList(args);
InvokeStatic.byReference(this.target,
this.selector,
this.arguments,
- this.continuation,
[this.sourceInformation]);
accept(Visitor visitor) => visitor.visitInvokeStatic(this);
void setParentPointers() {
_setParentsOnList(arguments, this);
- continuation.parent = this;
}
}
+enum CallingConvention {
+ /// JS receiver is the Dart receiver, there are no extra arguments.
+ ///
+ /// For example: `foo.bar$1(x)`
+ Normal,
+
+ /// JS receiver is an interceptor, the first argument is the Dart receiver.
+ ///
+ /// For example: `getInterceptor(foo).bar$1(foo, x)`
+ Intercepted,
+
+ /// JS receiver is the Dart receiver, the first argument is a dummy value.
+ ///
+ /// For example: `foo.bar$1(0, x)`
+ DummyIntercepted,
+}
+
/// Invoke a method on an object.
///
/// This includes getters, setters, operators, and index getter/setters.
@@ -473,24 +512,30 @@ class InvokeStatic extends CallExpression {
///
/// 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 CallExpression {
+class InvokeMethod extends UnsafePrimitive {
Reference<Primitive> receiver;
Selector selector;
TypeMask mask;
final List<Reference<Primitive>> arguments;
- final Reference<Continuation> continuation;
final SourceInformation sourceInformation;
- /// If true, the [receiver] is intercepted and the actual receiver is in
- /// the first argument. Otherwise, the [receiver] is the actual receiver.
- ///
- /// This flag is always false for non-intercepted selectors, but it may also
- /// be false for intercepted selectors after dummy receiver optimization
- /// (in this case the first argument is a dummy value).
- ///
- /// It is always false before the unsugaring pass, where interceptors have
- /// not yet been introduced.
- bool receiverIsIntercepted = false;
+ CallingConvention callingConvention = CallingConvention.Normal;
+
+ Reference<Primitive> get dartReceiverReference {
+ return callingConvention == CallingConvention.Intercepted
+ ? arguments[0]
+ : receiver;
+ }
+
+ Primitive get dartReceiver => dartReceiverReference.definition;
+
+ Reference<Primitive> dartArgumentReference(int n) {
+ return callingConvention == CallingConvention.Normal
+ ? arguments[n]
+ : arguments[n + 1];
+ }
+
+ Primitive dartArgument(int n) => dartArgumentReference(n).definition;
/// If true, it is known that the receiver cannot be `null`.
bool receiverIsNotNull = false;
@@ -499,17 +544,14 @@ class InvokeMethod extends CallExpression {
this.selector,
this.mask,
List<Primitive> arguments,
- Continuation continuation,
[this.sourceInformation])
: this.receiver = new Reference<Primitive>(receiver),
- this.arguments = _referenceList(arguments),
- this.continuation = new Reference<Continuation>(continuation);
+ this.arguments = _referenceList(arguments);
InvokeMethod.byReference(this.receiver,
this.selector,
this.mask,
this.arguments,
- this.continuation,
this.sourceInformation);
accept(Visitor visitor) => visitor.visitInvokeMethod(this);
@@ -517,7 +559,6 @@ class InvokeMethod extends CallExpression {
void setParentPointers() {
receiver.parent = this;
_setParentsOnList(arguments, this);
- continuation.parent = this;
}
}
@@ -540,30 +581,44 @@ class InvokeMethod extends CallExpression {
///
/// All optional arguments declared by [target] are passed in explicitly, and
/// occur at the end of [arguments] list, in normalized order.
-class InvokeMethodDirectly extends CallExpression {
+class InvokeMethodDirectly extends UnsafePrimitive {
Reference<Primitive> receiver;
final FunctionElement target;
final Selector selector;
final List<Reference<Primitive>> arguments;
- final Reference<Continuation> continuation;
final SourceInformation sourceInformation;
+ CallingConvention callingConvention = CallingConvention.Normal;
+
+ Reference<Primitive> get dartReceiverReference {
+ return callingConvention == CallingConvention.Intercepted
+ ? arguments[0]
+ : receiver;
+ }
+
+ Primitive get dartReceiver => dartReceiverReference.definition;
+
+ Reference<Primitive> dartArgumentReference(int n) {
+ return callingConvention == CallingConvention.Normal
+ ? arguments[n]
+ : arguments[n + 1];
+ }
+
+ Primitive dartArgument(int n) => dartArgumentReference(n).definition;
+
InvokeMethodDirectly(Primitive receiver,
this.target,
this.selector,
List<Primitive> arguments,
- Continuation continuation,
this.sourceInformation)
: this.receiver = new Reference<Primitive>(receiver),
- this.arguments = _referenceList(arguments),
- this.continuation = new Reference<Continuation>(continuation);
+ this.arguments = _referenceList(arguments);
accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this);
void setParentPointers() {
receiver.parent = this;
_setParentsOnList(arguments, this);
- continuation.parent = this;
}
}
@@ -582,11 +637,10 @@ class InvokeMethodDirectly extends CallExpression {
///
/// Note that [InvokeConstructor] does it itself allocate an object.
/// The invoked constructor will do that using [CreateInstance].
-class InvokeConstructor extends CallExpression {
+class InvokeConstructor extends UnsafePrimitive {
final DartType dartType;
final ConstructorElement target;
final List<Reference<Primitive>> arguments;
- final Reference<Continuation> continuation;
final Selector selector;
final SourceInformation sourceInformation;
@@ -601,17 +655,14 @@ class InvokeConstructor extends CallExpression {
this.target,
this.selector,
List<Primitive> args,
- Continuation cont,
this.sourceInformation,
{this.allocationSiteType})
- : arguments = _referenceList(args),
- continuation = new Reference<Continuation>(cont);
+ : arguments = _referenceList(args);
accept(Visitor visitor) => visitor.visitInvokeConstructor(this);
void setParentPointers() {
_setParentsOnList(arguments, this);
- continuation.parent = this;
}
}
@@ -719,26 +770,24 @@ class TypeTestViaFlag 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 CallExpression {
+class TypeCast extends UnsafePrimitive {
Reference<Primitive> value;
final DartType dartType;
/// See the corresponding field on [TypeTest].
final List<Reference<Primitive>> typeArguments;
- final Reference<Continuation> continuation;
TypeCast(Primitive value,
this.dartType,
- List<Primitive> typeArguments,
- Continuation cont)
+ List<Primitive> typeArguments)
: this.value = new Reference<Primitive>(value),
- this.typeArguments = _referenceList(typeArguments),
- this.continuation = new Reference<Continuation>(cont);
+ this.typeArguments = _referenceList(typeArguments);
accept(Visitor visitor) => visitor.visitTypeCast(this);
void setParentPointers() {
value.parent = this;
+ _setParentsOnList(typeArguments, this);
}
}
@@ -1126,22 +1175,15 @@ class SetStatic extends Primitive {
///
/// If the field has not yet been initialized, its initializer is evaluated
/// and assigned to the field.
-///
-/// [continuation] is then invoked with the value of the field as argument.
-class GetLazyStatic extends CallExpression {
+class GetLazyStatic extends UnsafePrimitive {
final FieldElement element;
- final Reference<Continuation> continuation;
final SourceInformation sourceInformation;
- GetLazyStatic(this.element,
- Continuation continuation,
- [this.sourceInformation])
- : continuation = new Reference<Continuation>(continuation);
+ GetLazyStatic(this.element, [this.sourceInformation]);
accept(Visitor visitor) => visitor.visitGetLazyStatic(this);
void setParentPointers() {
- continuation.parent = this;
}
}
@@ -1303,24 +1345,21 @@ class CreateInvocationMirror extends Primitive {
}
}
-class ForeignCode extends CallExpression {
+class ForeignCode extends UnsafePrimitive {
final js.Template codeTemplate;
final TypeMask type;
final List<Reference<Primitive>> arguments;
final native.NativeBehavior nativeBehavior;
final FunctionElement dependency;
- final Reference<Continuation> continuation;
ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments,
- this.nativeBehavior, Continuation continuation, {this.dependency})
- : this.arguments = _referenceList(arguments),
- this.continuation = new Reference<Continuation>(continuation);
+ this.nativeBehavior, {this.dependency})
+ : this.arguments = _referenceList(arguments);
accept(Visitor visitor) => visitor.visitForeignCode(this);
void setParentPointers() {
_setParentsOnList(arguments, this);
- continuation.parent = this;
}
}
@@ -1576,13 +1615,11 @@ class TypeExpression extends Primitive {
}
}
-class Await extends CallExpression {
+class Await extends UnsafePrimitive {
final Reference<Primitive> input;
- final Reference<Continuation> continuation;
- Await(Primitive input, Continuation continuation)
- : this.input = new Reference<Primitive>(input),
- this.continuation = new Reference<Continuation>(continuation);
+ Await(Primitive input)
+ : this.input = new Reference<Primitive>(input);
@override
accept(Visitor visitor) {
@@ -1591,18 +1628,15 @@ class Await extends CallExpression {
void setParentPointers() {
input.parent = this;
- continuation.parent = this;
}
}
-class Yield extends CallExpression {
+class Yield extends UnsafePrimitive {
final Reference<Primitive> input;
- final Reference<Continuation> continuation;
final bool hasStar;
- Yield(Primitive input, this.hasStar, Continuation continuation)
- : this.input = new Reference<Primitive>(input),
- this.continuation = new Reference<Continuation>(continuation);
+ Yield(Primitive input, this.hasStar)
+ : this.input = new Reference<Primitive>(input);
@override
accept(Visitor visitor) {
@@ -1611,7 +1645,6 @@ class Yield extends CallExpression {
void setParentPointers() {
input.parent = this;
- continuation.parent = this;
}
}
@@ -1760,7 +1793,6 @@ class DeepRecursiveVisitor implements Visitor {
processInvokeStatic(InvokeStatic node) {}
visitInvokeStatic(InvokeStatic node) {
processInvokeStatic(node);
- processReference(node.continuation);
node.arguments.forEach(processReference);
}
@@ -1775,7 +1807,6 @@ class DeepRecursiveVisitor implements Visitor {
visitInvokeMethod(InvokeMethod node) {
processInvokeMethod(node);
processReference(node.receiver);
- processReference(node.continuation);
node.arguments.forEach(processReference);
}
@@ -1783,14 +1814,12 @@ class DeepRecursiveVisitor implements Visitor {
visitInvokeMethodDirectly(InvokeMethodDirectly node) {
processInvokeMethodDirectly(node);
processReference(node.receiver);
- processReference(node.continuation);
node.arguments.forEach(processReference);
}
processInvokeConstructor(InvokeConstructor node) {}
visitInvokeConstructor(InvokeConstructor node) {
processInvokeConstructor(node);
- processReference(node.continuation);
node.arguments.forEach(processReference);
}
@@ -1816,7 +1845,6 @@ class DeepRecursiveVisitor implements Visitor {
processTypeCast(TypeCast node) {}
visitTypeCast(TypeCast node) {
processTypeCast(node);
- processReference(node.continuation);
processReference(node.value);
node.typeArguments.forEach(processReference);
}
@@ -1845,7 +1873,6 @@ class DeepRecursiveVisitor implements Visitor {
processGetLazyStatic(GetLazyStatic node) {}
visitGetLazyStatic(GetLazyStatic node) {
processGetLazyStatic(node);
- processReference(node.continuation);
}
processLiteralList(LiteralList node) {}
@@ -1972,9 +1999,6 @@ class DeepRecursiveVisitor implements Visitor {
processForeignCode(ForeignCode node) {}
visitForeignCode(ForeignCode node) {
processForeignCode(node);
- if (node.continuation != null) {
- processReference(node.continuation);
- }
node.arguments.forEach(processReference);
}
@@ -1987,14 +2011,12 @@ class DeepRecursiveVisitor implements Visitor {
visitAwait(Await node) {
processAwait(node);
processReference(node.input);
- processReference(node.continuation);
}
processYield(Yield node) {}
visitYield(Yield node) {
processYield(node);
processReference(node.input);
- processReference(node.continuation);
}
processGetLength(GetLength node) {}
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698