Index: sdk/lib/_internal/compiler/implementation/ssa/nodes.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/ssa/nodes.dart (revision 17440) |
+++ sdk/lib/_internal/compiler/implementation/ssa/nodes.dart (working copy) |
@@ -303,12 +303,12 @@ |
visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); |
visitInvokeSuper(HInvokeSuper node) => visitInvoke(node); |
visitJump(HJump node) => visitControlFlow(node); |
- visitLazyStatic(HLazyStatic node) => visitStatic(node); |
+ visitLazyStatic(HLazyStatic node) => visitInstruction(node); |
visitLess(HLess node) => visitRelational(node); |
visitLessEqual(HLessEqual node) => visitRelational(node); |
visitLiteralList(HLiteralList node) => visitInstruction(node); |
- visitLocalGet(HLocalGet node) => visitFieldGet(node); |
- visitLocalSet(HLocalSet node) => visitFieldSet(node); |
+ visitLocalGet(HLocalGet node) => visitFieldAccess(node); |
+ visitLocalSet(HLocalSet node) => visitFieldAccess(node); |
visitLocalValue(HLocalValue node) => visitInstruction(node); |
visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); |
visitNegate(HNegate node) => visitInvokeUnary(node); |
@@ -792,9 +792,7 @@ |
static const int INVOKE_DYNAMIC_GETTER_TYPECODE = 31; |
static const int INDEX_TYPECODE = 32; |
- HInstruction(this.inputs) |
- : id = idCounter++, |
- usedBy = <HInstruction>[]; |
+ HInstruction(this.inputs) : id = idCounter++, usedBy = <HInstruction>[]; |
int get hashCode => id; |
@@ -812,11 +810,6 @@ |
bool hasSideEffects() => getChangesFlags() != 0; |
bool dependsOnSomething() => getDependsOnFlags() != 0; |
- void prepareGvn(HTypeMap types) { |
- setAllSideEffects(); |
- setDependsOnSomething(); |
- } |
- |
void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); } |
void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); } |
@@ -824,6 +817,10 @@ |
int count = FLAG_DEPENDS_ON_COUNT - FLAG_CHANGES_COUNT; |
flags |= (((1 << count) - 1) << FLAG_CHANGES_COUNT); |
} |
+ void clearAllDependencies() { |
+ int count = FLAG_DEPENDS_ON_COUNT - FLAG_CHANGES_COUNT; |
+ flags &= ~(((1 << count) - 1) << FLAG_CHANGES_COUNT); |
+ } |
bool dependsOnStaticPropertyStore() { |
return getFlag(FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE); |
@@ -1161,8 +1158,7 @@ |
} |
class HBoolify extends HInstruction { |
- HBoolify(HInstruction value) : super(<HInstruction>[value]); |
- void prepareGvn(HTypeMap types) { |
+ HBoolify(HInstruction value) : super(<HInstruction>[value]) { |
assert(!hasSideEffects()); |
setUseGvn(); |
} |
@@ -1183,21 +1179,19 @@ |
* instruction itself. |
*/ |
abstract class HCheck extends HInstruction { |
- HCheck(inputs) : super(inputs); |
- HInstruction get checkedInput => inputs[0]; |
- bool isJsStatement() => true; |
- void prepareGvn(HTypeMap types) { |
+ HCheck(inputs) : super(inputs) { |
assert(!hasSideEffects()); |
setUseGvn(); |
} |
+ HInstruction get checkedInput => inputs[0]; |
+ bool isJsStatement() => true; |
bool canThrow() => true; |
} |
class HBailoutTarget extends HInstruction { |
final int state; |
bool isEnabled = true; |
- HBailoutTarget(this.state) : super(<HInstruction>[]); |
- void prepareGvn(HTypeMap types) { |
+ HBailoutTarget(this.state) : super(<HInstruction>[]) { |
assert(!hasSideEffects()); |
setUseGvn(); |
} |
@@ -1300,9 +1294,6 @@ |
abstract class HControlFlow extends HInstruction { |
HControlFlow(inputs) : super(inputs); |
- void prepareGvn(HTypeMap types) { |
- // Control flow does not have side-effects. |
- } |
bool isControlFlow() => true; |
bool isJsStatement() => true; |
} |
@@ -1313,7 +1304,10 @@ |
* the receiver of a method-call. The remaining inputs are the arguments |
* to the invocation. |
*/ |
- HInvoke(List<HInstruction> inputs) : super(inputs); |
+ HInvoke(List<HInstruction> inputs) : super(inputs) { |
+ setAllSideEffects(); |
+ setDependsOnSomething(); |
+ } |
static const int ARGUMENTS_OFFSET = 1; |
bool canThrow() => true; |
} |
@@ -1383,13 +1377,8 @@ |
} |
class HInvokeDynamicGetter extends HInvokeDynamicField { |
- HInvokeDynamicGetter( |
- selector, element, receiver, isSideEffectFree) |
- : super(selector, element, [receiver], isSideEffectFree); |
- toString() => 'invoke dynamic getter: $selector'; |
- accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); |
- |
- void prepareGvn(HTypeMap types) { |
+ HInvokeDynamicGetter(selector, element, receiver, isSideEffectFree) |
+ : super(selector, element, [receiver], isSideEffectFree) { |
clearAllSideEffects(); |
if (isSideEffectFree) { |
setUseGvn(); |
@@ -1399,6 +1388,8 @@ |
setAllSideEffects(); |
} |
} |
+ toString() => 'invoke dynamic getter: $selector'; |
+ accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); |
int typeCode() => HInstruction.INVOKE_DYNAMIC_GETTER_TYPECODE; |
bool typeEquals(other) => other is HInvokeDynamicGetter; |
@@ -1407,11 +1398,7 @@ |
class HInvokeDynamicSetter extends HInvokeDynamicField { |
HInvokeDynamicSetter(selector, element, receiver, value, isSideEffectFree) |
- : super(selector, element, [receiver, value], isSideEffectFree); |
- toString() => 'invoke dynamic setter: $selector'; |
- accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this); |
- |
- void prepareGvn(HTypeMap types) { |
+ : super(selector, element, [receiver, value], isSideEffectFree) { |
clearAllSideEffects(); |
if (isSideEffectFree) { |
setChangesInstanceProperty(); |
@@ -1420,6 +1407,8 @@ |
setDependsOnSomething(); |
} |
} |
+ toString() => 'invoke dynamic setter: $selector'; |
+ accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this); |
} |
class HInvokeStatic extends HInvoke { |
@@ -1433,20 +1422,6 @@ |
int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE; |
Element get element => target.element; |
HStatic get target => inputs[0]; |
- |
- HType computeDesiredTypeForInput(HInstruction input, |
- HTypeMap types, |
- Compiler compiler) { |
- // TODO(floitsch): we want the target to be a function. |
- if (input == target) return HType.UNKNOWN; |
- return computeDesiredTypeForNonTargetInput(input, types, compiler); |
- } |
- |
- HType computeDesiredTypeForNonTargetInput(HInstruction input, |
- HTypeMap types, |
- Compiler compiler) { |
- return HType.UNKNOWN; |
- } |
} |
class HInvokeSuper extends HInvokeStatic { |
@@ -1466,11 +1441,9 @@ |
final Element element; |
HFieldAccess(Element element, List<HInstruction> inputs) |
- : this.element = element, |
- super(inputs); |
+ : this.element = element, super(inputs); |
- // TODO(ngeoffray): Only if input can be null. |
- bool canThrow() => true; |
+ HInstruction get receiver => inputs[0]; |
} |
class HFieldGet extends HFieldAccess { |
@@ -1480,20 +1453,19 @@ |
: this.isAssignable = (isAssignable != null) |
? isAssignable |
: element.isAssignable(), |
- super(element, <HInstruction>[receiver]); |
- |
- HInstruction get receiver => inputs[0]; |
- |
- accept(HVisitor visitor) => visitor.visitFieldGet(this); |
- |
- void prepareGvn(HTypeMap types) { |
+ super(element, <HInstruction>[receiver]) { |
clearAllSideEffects(); |
setUseGvn(); |
- if (isAssignable) { |
+ if (this.isAssignable) { |
setDependsOnInstancePropertyStore(); |
} |
} |
+ // TODO(ngeoffray): Only if input can be null. |
+ bool canThrow() => true; |
+ |
+ accept(HVisitor visitor) => visitor.visitFieldGet(this); |
+ |
int typeCode() => HInstruction.FIELD_GET_TYPECODE; |
bool typeEquals(other) => other is HFieldGet; |
bool dataEquals(HFieldGet other) => element == other.element; |
@@ -1504,57 +1476,61 @@ |
HFieldSet(Element element, |
HInstruction receiver, |
HInstruction value) |
- : super(element, <HInstruction>[receiver, value]); |
- |
- HInstruction get receiver => inputs[0]; |
- HInstruction get value => inputs[1]; |
- accept(HVisitor visitor) => visitor.visitFieldSet(this); |
- |
- void prepareGvn(HTypeMap types) { |
+ : super(element, <HInstruction>[receiver, value]) { |
clearAllSideEffects(); |
setChangesInstanceProperty(); |
} |
+ // TODO(ngeoffray): Only if input can be null. |
+ bool canThrow() => true; |
+ |
+ HInstruction get value => inputs[1]; |
+ accept(HVisitor visitor) => visitor.visitFieldSet(this); |
+ |
bool isJsStatement() => true; |
String toString() => "FieldSet $element"; |
} |
-class HLocalGet extends HFieldGet { |
- HLocalGet(Element element, HLocalValue local) : super(element, local); |
+class HLocalGet extends HFieldAccess { |
+ // No need to use GVN for a [HLocalGet], it is just a local |
+ // access. |
+ HLocalGet(Element element, HLocalValue local) |
+ : super(element, <HInstruction>[local]); |
accept(HVisitor visitor) => visitor.visitLocalGet(this); |
HLocalValue get local => inputs[0]; |
- |
- void prepareGvn(HTypeMap types) { |
- // No need to use GVN for a [HLocalGet], it is just a local |
- // access. |
- clearAllSideEffects(); |
- } |
} |
-class HLocalSet extends HFieldSet { |
+class HLocalSet extends HFieldAccess { |
HLocalSet(Element element, HLocalValue local, HInstruction value) |
- : super(element, local, value); |
+ : super(element, <HInstruction>[local, value]); |
accept(HVisitor visitor) => visitor.visitLocalSet(this); |
HLocalValue get local => inputs[0]; |
+ HInstruction get value => inputs[1]; |
+ bool isJsStatement() => true; |
} |
class HForeign extends HInstruction { |
final DartString code; |
final HType foreignType; |
- final bool _isStatement; |
+ final bool isStatement; |
- HForeign(this.code, DartString declaredType, List<HInstruction> inputs) |
+ HForeign(this.code, |
+ DartString declaredType, |
+ List<HInstruction> inputs, |
+ {this.isStatement: false}) |
: foreignType = computeTypeFromDeclaredType(declaredType), |
- _isStatement = false, |
- super(inputs); |
- HForeign.statement(this.code, List<HInstruction> inputs) |
- : foreignType = HType.UNKNOWN, |
- _isStatement = true, |
- super(inputs); |
+ super(inputs) { |
+ setAllSideEffects(); |
+ setDependsOnSomething(); |
+ } |
+ |
+ HForeign.statement(code, List<HInstruction> inputs) |
+ : this(code, const LiteralDartString('var'), input, isStatement: true); |
+ |
accept(HVisitor visitor) => visitor.visitForeign(this); |
static HType computeTypeFromDeclaredType(DartString declaredType) { |
@@ -1569,7 +1545,7 @@ |
HType get guaranteedType => foreignType; |
- bool isJsStatement() => _isStatement; |
+ bool isJsStatement() => isStatement; |
bool canThrow() => true; |
} |
@@ -1584,9 +1560,7 @@ |
abstract class HInvokeBinary extends HInstruction { |
HInvokeBinary(HInstruction left, HInstruction right) |
- : super(<HInstruction>[left, right]); |
- |
- void prepareGvn(HTypeMap types) { |
+ : super(<HInstruction>[left, right]) { |
clearAllSideEffects(); |
setUseGvn(); |
} |
@@ -1730,15 +1704,13 @@ |
} |
abstract class HInvokeUnary extends HInstruction { |
- HInvokeUnary(HInstruction input) : super(<HInstruction>[input]); |
- |
- HInstruction get operand => inputs[0]; |
- |
- void prepareGvn(HTypeMap types) { |
+ HInvokeUnary(HInstruction input) : super(<HInstruction>[input]) { |
clearAllSideEffects(); |
setUseGvn(); |
} |
+ HInstruction get operand => inputs[0]; |
+ |
UnaryOperation operation(ConstantSystem constantSystem); |
} |
@@ -1865,10 +1837,6 @@ |
HConstant.internal(this.constant, HType this.constantType) |
: super(<HInstruction>[]); |
- void prepareGvn(HTypeMap types) { |
- assert(!hasSideEffects()); |
- } |
- |
toString() => 'literal: $constant'; |
accept(HVisitor visitor) => visitor.visitConstant(this); |
@@ -1891,9 +1859,7 @@ |
} |
class HNot extends HInstruction { |
- HNot(HInstruction value) : super(<HInstruction>[value]); |
- void prepareGvn(HTypeMap types) { |
- assert(!hasSideEffects()); |
+ HNot(HInstruction value) : super(<HInstruction>[value]) { |
setUseGvn(); |
} |
@@ -1922,9 +1888,6 @@ |
sourceElement = element; |
} |
- void prepareGvn(HTypeMap types) { |
- assert(!hasSideEffects()); |
- } |
toString() => 'local ${sourceElement.name}'; |
accept(HVisitor visitor) => visitor.visitLocalValue(this); |
} |
@@ -2114,9 +2077,6 @@ |
HStatic(this.element) : super(<HInstruction>[]) { |
assert(element != null); |
assert(invariant(this, element.isDeclaration)); |
- } |
- |
- void prepareGvn(HTypeMap types) { |
clearAllSideEffects(); |
if (element.isAssignable()) { |
setDependsOnStaticPropertyStore(); |
@@ -2136,16 +2096,14 @@ |
class HInterceptor extends HInstruction { |
Set<ClassElement> interceptedClasses; |
HInterceptor(this.interceptedClasses, HInstruction receiver) |
- : super(<HInstruction>[receiver]); |
+ : super(<HInstruction>[receiver]) { |
+ clearAllSideEffects(); |
+ setUseGvn(); |
+ } |
String toString() => 'interceptor on $interceptedClasses'; |
accept(HVisitor visitor) => visitor.visitInterceptor(this); |
HInstruction get receiver => inputs[0]; |
- void prepareGvn(HTypeMap types) { |
- clearAllSideEffects(); |
- setUseGvn(); |
- } |
- |
HType computeDesiredTypeForInput(HInstruction input, |
HTypeMap types, |
Compiler compiler) { |
@@ -2174,10 +2132,9 @@ |
} |
/** An [HLazyStatic] is a static that is initialized lazily at first read. */ |
-class HLazyStatic extends HStatic { |
- HLazyStatic(Element element) : super(element); |
- |
- void prepareGvn(HTypeMap types) { |
+class HLazyStatic extends HInstruction { |
+ final Element element; |
+ HLazyStatic(this.element) : super(<HInstruction>[]) { |
// TODO(4931): The first access has side-effects, but we afterwards we |
// should be able to GVN. |
setAllSideEffects(); |
@@ -2195,7 +2152,11 @@ |
class HStaticStore extends HInstruction { |
Element element; |
- HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]); |
+ HStaticStore(this.element, HInstruction value) |
+ : super(<HInstruction>[value]) { |
+ clearAllSideEffects(); |
+ setChangesStaticProperty(); |
+ } |
toString() => 'static store ${element.name}'; |
accept(HVisitor visitor) => visitor.visitStaticStore(this); |
@@ -2203,11 +2164,6 @@ |
bool typeEquals(other) => other is HStaticStore; |
bool dataEquals(HStaticStore other) => element == other.element; |
bool isJsStatement() => true; |
- |
- void prepareGvn(HTypeMap types) { |
- clearAllSideEffects(); |
- setChangesStaticProperty(); |
- } |
} |
class HLiteralList extends HInstruction { |
@@ -2216,10 +2172,6 @@ |
accept(HVisitor visitor) => visitor.visitLiteralList(this); |
HType get guaranteedType => HType.EXTENDABLE_ARRAY; |
- |
- void prepareGvn(HTypeMap types) { |
- assert(!hasSideEffects()); |
- } |
} |
/** |
@@ -2228,16 +2180,15 @@ |
*/ |
class HIndex extends HInstruction { |
HIndex(HInstruction receiver, HInstruction index) |
- : super(<HInstruction>[receiver, index]); |
- String toString() => 'index operator'; |
- accept(HVisitor visitor) => visitor.visitIndex(this); |
- |
- void prepareGvn(HTypeMap types) { |
+ : super(<HInstruction>[receiver, index]) { |
clearAllSideEffects(); |
setDependsOnIndexStore(); |
setUseGvn(); |
} |
+ String toString() => 'index operator'; |
+ accept(HVisitor visitor) => visitor.visitIndex(this); |
+ |
HInstruction get receiver => inputs[0]; |
HInstruction get index => inputs[1]; |
@@ -2254,33 +2205,27 @@ |
HIndexAssign(HInstruction receiver, |
HInstruction index, |
HInstruction value) |
- : super(<HInstruction>[receiver, index, value]); |
+ : super(<HInstruction>[receiver, index, value]) { |
+ clearAllSideEffects(); |
+ setChangesIndex(); |
+ } |
String toString() => 'index assign operator'; |
accept(HVisitor visitor) => visitor.visitIndexAssign(this); |
HInstruction get receiver => inputs[0]; |
HInstruction get index => inputs[1]; |
HInstruction get value => inputs[2]; |
- |
- void prepareGvn(HTypeMap types) { |
- clearAllSideEffects(); |
- setChangesIndex(); |
- } |
} |
class HIs extends HInstruction { |
final DartType typeExpression; |
final bool nullOk; |
- HIs.withArgumentChecks(this.typeExpression, |
- HInstruction expression, |
- List<HInstruction> checks, |
- [this.nullOk = false]) |
- : super(<HInstruction>[expression]..addAll(checks)); |
+ HIs(this.typeExpression, List<HInstruction> inputs, {this.nullOk: false}) |
+ : super(inputs) { |
+ setUseGvn(); |
+ } |
- HIs(this.typeExpression, HInstruction expression, {this.nullOk: false}) |
- : super(<HInstruction>[expression]); |
- |
HInstruction get expression => inputs[0]; |
HInstruction getCheck(int index) => inputs[index + 1]; |
int get checkCount => inputs.length - 1; |
@@ -2352,7 +2297,10 @@ |
class HStringConcat extends HInstruction { |
final Node node; |
HStringConcat(HInstruction left, HInstruction right, this.node) |
- : super(<HInstruction>[left, right]); |
+ : super(<HInstruction>[left, right]) { |
+ setAllSideEffects(); |
+ setDependsOnSomething(); |
+ } |
HType get guaranteedType => HType.STRING; |
HInstruction get left => inputs[0]; |