Index: runtime/vm/flow_graph_type_propagator.cc |
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc |
index d6a3808302d7559c96518c1a32671ed0f61ed5ab..b1c19cb90f824fd77214d98b72dc69b7bc0dd4ff 100644 |
--- a/runtime/vm/flow_graph_type_propagator.cc |
+++ b/runtime/vm/flow_graph_type_propagator.cc |
@@ -350,7 +350,7 @@ void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) { |
} else if ((call != NULL) && |
call->MatchesCoreName(Symbols::_simpleInstanceOf()) && |
comparison->InputAt(1)->BindsToConstant() && |
- (comparison->InputAt(1)->BoundConstant().IsBool())) { |
+ comparison->InputAt(1)->BoundConstant().IsBool()) { |
ASSERT(call->ArgumentAt(1)->IsConstant()); |
if (comparison->InputAt(1)->BoundConstant().raw() == Bool::False().raw()) { |
negated = !negated; |
@@ -367,8 +367,24 @@ void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) { |
true_successor, call->ArgumentAt(0), |
CompileType::FromAbstractType(Type::Cast(type), is_nullable)); |
} |
+ } else if (comparison->InputAt(0)->BindsToConstant() && |
+ comparison->InputAt(0)->BoundConstant().IsNull()) { |
+ // Handle for expr != null. |
+ BlockEntryInstr* true_successor = |
+ negated ? instr->true_successor() : instr->false_successor(); |
+ redef = flow_graph_->EnsureRedefinition( |
+ true_successor, comparison->InputAt(1)->definition(), |
+ comparison->InputAt(1)->Type()->CopyNonNullable()); |
+ |
+ } else if (comparison->InputAt(1)->BindsToConstant() && |
+ comparison->InputAt(1)->BoundConstant().IsNull()) { |
+ // Handle for null != expr. |
+ BlockEntryInstr* true_successor = |
+ negated ? instr->true_successor() : instr->false_successor(); |
+ redef = flow_graph_->EnsureRedefinition( |
+ true_successor, comparison->InputAt(0)->definition(), |
+ comparison->InputAt(0)->Type()->CopyNonNullable()); |
} |
- // TODO(fschneider): Add propagation for null-comparisons. |
// TODO(fschneider): Add propagation for generic is-tests. |
// Grow types array if a new redefinition was inserted. |
@@ -550,7 +566,7 @@ CompileType CompileType::Bool() { |
CompileType CompileType::Int() { |
- return FromAbstractType(Type::ZoneHandle(Type::IntType()), kNonNullable); |
+ return FromAbstractType(Type::ZoneHandle(Type::Int64Type()), kNonNullable); |
} |
@@ -771,16 +787,18 @@ CompileType RedefinitionInstr::ComputeType() const { |
// than the type of its input. If yes, return it. Otherwise, fall back |
// to the input's type. |
- // If either type has a concrete cid, stick with it. |
- if (value()->Type()->ToCid() != kDynamicCid) { |
- return *value()->Type(); |
- } |
- if (constrained_type_->ToCid() != kDynamicCid) { |
- return *constrained_type_; |
- } |
// If either type is non-nullable, the resulting type is non-nullable. |
const bool is_nullable = |
value()->Type()->is_nullable() && constrained_type_->is_nullable(); |
+ |
+ // If either type has a concrete cid, stick with it. |
+ if (value()->Type()->ToNullableCid() != kDynamicCid) { |
+ return CompileType::CreateNullable(is_nullable, value()->Type()->ToCid()); |
+ } |
+ if (constrained_type_->ToNullableCid() != kDynamicCid) { |
+ return CompileType::CreateNullable(is_nullable, |
+ constrained_type_->ToCid()); |
+ } |
if (value()->Type()->IsMoreSpecificThan( |
*constrained_type_->ToAbstractType())) { |
return is_nullable ? *value()->Type() |