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

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: 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..d3e59e6032fee97b0ba39500fe2e4cb67acb33ef 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
@@ -268,6 +262,33 @@ abstract class Primitive extends Variable<Primitive> {
assert(hasNoUses);
RemovalVisitor.remove(this);
}
+
+ /// Replaces this definition, both at the binding site and at all uses sites.
sra1 2015/11/19 21:41:46 Then maybe call it 'replaceWith'.
asgerf 2015/11/20 16:23:54 I would like that name, but 'substituteFor' and 'r
+ ///
+ /// 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 redefineAs(Primitive newDefinition) {
sra1 2015/11/19 21:41:45 assert(newDefinition.parent == null); assert there
asgerf 2015/11/20 16:23:53 There are uses. They are being replaced with uses
+ newDefinition.substituteFor(this);
+ 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;
}
/// Operands to invocations and primitives are always variables. They point to
@@ -435,35 +456,49 @@ 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;
+ bool get isSafeForReordering => isSafeForElimination;
+
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 {
sra1 2015/11/19 21:41:45 Just a thought: We might want to make this a hand
asgerf 2015/11/20 16:23:54 I don't know that "interceptor position" means, bu
+ /// JS receiver is the Dart receiver, there are no extra arguments.
+ ///
+ /// For example: `foo.bar$1(x)`
+ Normal,
sra1 2015/11/19 21:41:45 Maybe 'Direct'. 'Normal' implies abnormal but inte
asgerf 2015/11/20 16:23:54 I would also consider NonIntercepted to be "direct
+
+ /// 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,43 +508,52 @@ 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;
+
+ bool get receiverIsIntercepted {
sra1 2015/11/19 21:41:45 I'm wondering if there are any inconsistencies bet
asgerf 2015/11/20 16:23:54 Done.
+ return callingConvention == CallingConvention.Intercepted;
+ }
+
+ Reference<Primitive> get dartReceiverRef {
sra1 2015/11/19 21:41:46 We try to use full words where possible, e.g. dart
asgerf 2015/11/20 16:23:54 Done.
+ return callingConvention == CallingConvention.Intercepted
+ ? arguments[0]
+ : receiver;
+ }
+
+ Primitive get dartReceiver => dartReceiverRef.definition;
+
+ Reference<Primitive> getDartArgumentRef(int n) {
sra1 2015/11/19 21:41:45 can we drop the 'get' on these methods for symmetr
asgerf 2015/11/20 16:23:53 Done.
+ return callingConvention == CallingConvention.Normal
+ ? arguments[n]
+ : arguments[n + 1];
+ }
+
+ Primitive getDartArgument(int n) => getDartArgumentRef(n).definition;
/// If true, it is known that the receiver cannot be `null`.
bool receiverIsNotNull = false;
+ bool get isSafeForReordering => isSafeForElimination;
sra1 2015/11/19 21:41:46 This feels backwards. I'd rather this was a separ
asgerf 2015/11/20 16:23:53 Done.
+
InvokeMethod(Primitive receiver,
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 +561,6 @@ class InvokeMethod extends CallExpression {
void setParentPointers() {
receiver.parent = this;
_setParentsOnList(arguments, this);
- continuation.parent = this;
}
}
@@ -540,30 +583,50 @@ 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;
+
+ bool get receiverIsIntercepted {
+ return callingConvention == CallingConvention.Intercepted;
+ }
+
+ Reference<Primitive> get dartReceiverRef {
+ return callingConvention == CallingConvention.Intercepted
+ ? arguments[0]
+ : receiver;
+ }
+
+ Primitive get dartReceiver => dartReceiverRef.definition;
+
+ Reference<Primitive> getDartArgumentRef(int n) {
+ return callingConvention == CallingConvention.Normal
+ ? arguments[n]
+ : arguments[n + 1];
+ }
+
+ Primitive getDartArgument(int n) => getDartArgumentRef(n).definition;
+
+ bool get isSafeForReordering => isSafeForElimination;
+
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,14 +645,15 @@ 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;
+ bool get isSafeForReordering => isSafeForElimination;
+
/// If non-null, this is an allocation site-specific type that is potentially
/// better than the inferred return type of [target].
///
@@ -601,17 +665,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 +780,26 @@ 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;
+
+ bool get isSafeForReordering => isSafeForElimination;
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 +1187,17 @@ 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);
+ bool get isSafeForReordering => isSafeForElimination;
+
+ GetLazyStatic(this.element, [this.sourceInformation]);
accept(Visitor visitor) => visitor.visitGetLazyStatic(this);
void setParentPointers() {
- continuation.parent = this;
}
}
@@ -1303,24 +1359,23 @@ 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;
+
+ bool get isSafeForReordering => isSafeForElimination;
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 +1631,13 @@ 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);
+ bool get isSafeForReordering => isSafeForElimination;
+
+ Await(Primitive input)
+ : this.input = new Reference<Primitive>(input);
@override
accept(Visitor visitor) {
@@ -1591,18 +1646,17 @@ 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);
+ bool get isSafeForReordering => isSafeForElimination;
+
+ Yield(Primitive input, this.hasStar)
+ : this.input = new Reference<Primitive>(input);
@override
accept(Visitor visitor) {
@@ -1611,7 +1665,6 @@ class Yield extends CallExpression {
void setParentPointers() {
input.parent = this;
- continuation.parent = this;
}
}
@@ -1760,7 +1813,6 @@ class DeepRecursiveVisitor implements Visitor {
processInvokeStatic(InvokeStatic node) {}
visitInvokeStatic(InvokeStatic node) {
processInvokeStatic(node);
- processReference(node.continuation);
node.arguments.forEach(processReference);
}
@@ -1775,7 +1827,6 @@ class DeepRecursiveVisitor implements Visitor {
visitInvokeMethod(InvokeMethod node) {
processInvokeMethod(node);
processReference(node.receiver);
- processReference(node.continuation);
node.arguments.forEach(processReference);
}
@@ -1783,14 +1834,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 +1865,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 +1893,6 @@ class DeepRecursiveVisitor implements Visitor {
processGetLazyStatic(GetLazyStatic node) {}
visitGetLazyStatic(GetLazyStatic node) {
processGetLazyStatic(node);
- processReference(node.continuation);
}
processLiteralList(LiteralList node) {}
@@ -1972,9 +2019,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 +2031,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) {}

Powered by Google App Engine
This is Rietveld 408576698