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 561f8aca34ee99025a7b4e7f1be9ae977e73bd22..e50be5637e4b2b4d1f3a4225f2f421d542e8586d 100644 |
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
@@ -95,7 +95,11 @@ abstract class Primitive extends Definition<Primitive> { |
/// |
/// False must be returned for primitives that may throw, diverge, or have |
/// observable side-effects. |
- bool get isSafeForElimination => true; |
+ bool get isSafeForElimination; |
+ |
+ /// True if time-of-evaluation is irrelevant for the given primitive, |
+ /// assuming its inputs are the same values. |
+ bool get isSafeForReordering; |
} |
/// Operands to invocations and primitives are always variables. They point to |
@@ -266,6 +270,12 @@ class InvokeStatic extends Expression implements Invoke { |
: arguments = _referenceList(args), |
continuation = new Reference<Continuation>(cont); |
+ InvokeStatic.byReference(this.target, |
+ this.selector, |
+ this.arguments, |
+ this.continuation, |
+ [this.sourceInformation]); |
+ |
accept(Visitor visitor) => visitor.visitInvokeStatic(this); |
} |
@@ -299,6 +309,13 @@ class InvokeMethod extends Expression implements Invoke { |
this.arguments = _referenceList(arguments), |
this.continuation = new Reference<Continuation>(continuation); |
+ InvokeMethod.byReference(this.receiver, |
+ this.selector, |
+ this.mask, |
+ this.arguments, |
+ this.continuation, |
+ [this.sourceInformation]); |
+ |
accept(Visitor visitor) => visitor.visitInvokeMethod(this); |
} |
@@ -404,6 +421,9 @@ class TypeTest extends Primitive { |
this.typeArguments = _referenceList(typeArguments); |
accept(Visitor visitor) => visitor.visitTypeTest(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
/// An "as" type cast. |
@@ -446,6 +466,9 @@ class ApplyBuiltinOperator extends Primitive { |
: this.arguments = _referenceList(arguments); |
accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
/// Throw a value. |
@@ -481,6 +504,9 @@ class NonTailThrow extends Primitive { |
NonTailThrow(Primitive value) : value = new Reference<Primitive>(value); |
accept(Visitor visitor) => visitor.visitNonTailThrow(this); |
+ |
+ bool get isSafeForElimination => false; |
+ bool get isSafeForReordering => false; |
} |
/// An expression that is known to be unreachable. |
@@ -505,6 +531,9 @@ class GetMutableVariable extends Primitive { |
: this.variable = new Reference<MutableVariable>(variable); |
accept(Visitor visitor) => visitor.visitGetMutableVariable(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => false; |
} |
/// Assign a [MutableVariable]. |
@@ -622,11 +651,13 @@ class GetField extends Primitive { |
accept(Visitor visitor) => visitor.visitGetField(this); |
- @override |
bool get isSafeForElimination => objectIsNotNull; |
+ bool get isSafeForReordering => objectIsNotNull && field.isFinal; |
} |
/// Reads the value of a static field or tears off a static method. |
+/// |
+/// Note that lazily initialized fields should be read using GetLazyStatic. |
class GetStatic extends Primitive { |
/// Can be [FieldElement] or [FunctionElement]. |
final Element element; |
@@ -635,6 +666,13 @@ class GetStatic extends Primitive { |
GetStatic(this.element, [this.sourceInformation]); |
accept(Visitor visitor) => visitor.visitGetStatic(this); |
+ |
+ bool get isSafeForElimination { |
+ return true; |
+ } |
+ bool get isSafeForReordering { |
+ return element is FunctionElement || element.isFinal; |
+ } |
} |
/// Sets the value of a static field. |
@@ -677,6 +715,9 @@ class GetLazyStatic extends Expression { |
/// Creates an object for holding boxed variables captured by a closure. |
class CreateBox extends Primitive { |
accept(Visitor visitor) => visitor.visitCreateBox(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
/// Creates an instance of a class and initializes its fields and runtime type |
@@ -701,6 +742,9 @@ class CreateInstance extends Primitive { |
this.typeInformation = _referenceList(typeInformation); |
accept(Visitor visitor) => visitor.visitCreateInstance(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
class Interceptor extends Primitive { |
@@ -709,6 +753,9 @@ class Interceptor extends Primitive { |
Interceptor(Primitive input, this.interceptedClasses) |
: this.input = new Reference<Primitive>(input); |
accept(Visitor visitor) => visitor.visitInterceptor(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
/// Create an instance of [Invocation] for use in a call to `noSuchMethod`. |
@@ -720,6 +767,9 @@ class CreateInvocationMirror extends Primitive { |
: this.arguments = _referenceList(arguments); |
accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
class ForeignCode extends Expression { |
@@ -748,6 +798,9 @@ class Constant extends Primitive { |
Constant(this.value); |
accept(Visitor visitor) => visitor.visitConstant(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
class LiteralList extends Primitive { |
@@ -759,6 +812,9 @@ class LiteralList extends Primitive { |
: this.values = _referenceList(values); |
accept(Visitor visitor) => visitor.visitLiteralList(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
class LiteralMapEntry { |
@@ -777,6 +833,9 @@ class LiteralMap extends Primitive { |
LiteralMap(this.type, this.entries); |
accept(Visitor visitor) => visitor.visitLiteralMap(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
/// Currently unused. |
@@ -795,6 +854,9 @@ class CreateFunction extends Primitive { |
CreateFunction(this.definition); |
accept(Visitor visitor) => visitor.visitCreateFunction(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
class Parameter extends Primitive { |
@@ -811,6 +873,9 @@ class Parameter extends Primitive { |
accept(Visitor visitor) => visitor.visitParameter(this); |
String toString() => 'Parameter(${hint == null ? null : hint.name})'; |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
/// Continuations are normally bound by 'let cont'. A continuation with one |
@@ -877,6 +942,9 @@ class ReifyRuntimeType extends Primitive { |
@override |
accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
/// Read the value the type variable [variable] from the target object. |
@@ -893,6 +961,9 @@ class ReadTypeVariable extends Primitive { |
@override |
accept(Visitor visitor) => visitor.visitReadTypeVariable(this); |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
/// Representation of a closed type (that is, a type without type variables). |
@@ -915,6 +986,9 @@ class TypeExpression extends Primitive { |
accept(Visitor visitor) { |
return visitor.visitTypeExpression(this); |
} |
+ |
+ bool get isSafeForElimination => true; |
+ bool get isSafeForReordering => true; |
} |
List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |