Chromium Code Reviews| 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 09d61717b2faaaf303de1cf042723c375377fef0..7e864836d7cc6eef6106ac7495b14d38cfc67e77 100644 |
| --- a/runtime/vm/flow_graph_type_propagator.cc |
| +++ b/runtime/vm/flow_graph_type_propagator.cc |
| @@ -20,10 +20,15 @@ DECLARE_FLAG(bool, use_cha); |
| FlowGraphTypePropagator::FlowGraphTypePropagator(FlowGraph* flow_graph) |
| : FlowGraphVisitor(flow_graph->reverse_postorder()), |
| flow_graph_(flow_graph), |
| + visited_(flow_graph->reverse_postorder().length()), |
| types_(flow_graph->current_ssa_temp_index()), |
| in_worklist_(new BitVector(flow_graph->current_ssa_temp_index())), |
| asserts_(NULL), |
| collected_asserts_(NULL) { |
| + for (intptr_t i = 0; i < flow_graph->reverse_postorder().length(); i++) { |
| + visited_.Add(false); |
| + } |
| + |
| for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { |
| types_.Add(NULL); |
| } |
| @@ -89,6 +94,11 @@ void FlowGraphTypePropagator::Propagate() { |
| void FlowGraphTypePropagator::PropagateRecursive(BlockEntryInstr* block) { |
| + if (visited_[block->postorder_number()]) { |
| + return; |
| + } |
| + visited_[block->postorder_number()] = true; |
| + |
| const intptr_t rollback_point = rollback_.length(); |
| if (FLAG_enable_type_checks) { |
| @@ -119,10 +129,50 @@ void FlowGraphTypePropagator::PropagateRecursive(BlockEntryInstr* block) { |
| } |
| } |
| + HandleBranchOnNull(block); |
| + |
| for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { |
| PropagateRecursive(block->dominated_blocks()[i]); |
| } |
| + RollbackTo(rollback_point); |
| +} |
| + |
| + |
| +void FlowGraphTypePropagator::HandleBranchOnNull(BlockEntryInstr* block) { |
| + BranchInstr* branch = block->last_instruction()->AsBranch(); |
| + if (branch == NULL) { |
| + return; |
| + } |
| + |
| + StrictCompareInstr* compare = branch->comparison()->AsStrictCompare(); |
| + if ((compare == NULL) || !compare->InputAt(1)->BindsToConstantNull()) { |
|
Kevin Millikin (Google)
2013/03/12 12:14:56
I find it easier to read with the (non-virtual) ac
Vyacheslav Egorov (Google)
2013/03/12 16:54:40
Done.
|
| + return; |
| + } |
| + |
| + const intptr_t rollback_point = rollback_.length(); |
| + |
| + Definition* defn = compare->InputAt(0)->definition(); |
| + |
| + if (compare->kind() == Token::kEQ_STRICT) { |
| + MarkNonNullable(defn); |
| + PropagateRecursive(branch->false_successor()); |
| + |
| + SetCid(defn, kNullCid); |
| + PropagateRecursive(branch->true_successor()); |
| + } else if (compare->kind() == Token::kNE_STRICT) { |
| + MarkNonNullable(defn); |
| + PropagateRecursive(branch->true_successor()); |
| + |
| + SetCid(defn, kNullCid); |
| + PropagateRecursive(branch->false_successor()); |
| + } |
| + |
| + RollbackTo(rollback_point); |
| +} |
| + |
| + |
| +void FlowGraphTypePropagator::RollbackTo(intptr_t rollback_point) { |
| for (intptr_t i = rollback_.length() - 1; i >= rollback_point; i--) { |
| types_[rollback_[i].index()] = rollback_[i].type(); |
| } |
| @@ -151,12 +201,23 @@ void FlowGraphTypePropagator::SetTypeOf(Definition* def, CompileType* type) { |
| void FlowGraphTypePropagator::SetCid(Definition* def, intptr_t cid) { |
| CompileType* current = TypeOf(def); |
| - if (current->ToCid() == cid) return; |
| + if (!current->IsNone() && (current->ToCid() == cid)) return; |
|
Kevin Millikin (Google)
2013/03/12 12:14:56
I find the early return guarding a single statemen
Vyacheslav Egorov (Google)
2013/03/12 16:54:40
Done.
|
| SetTypeOf(def, ZoneCompileType::Wrap(CompileType::FromCid(cid))); |
| } |
| +void FlowGraphTypePropagator::MarkNonNullable(Definition* def) { |
| + CompileType* current = TypeOf(def); |
| + if (current->IsNone() || |
| + (current->is_nullable() == CompileType::kNonNullable)) { |
|
Kevin Millikin (Google)
2013/03/12 12:14:56
Also here.
Vyacheslav Egorov (Google)
2013/03/12 16:54:40
Done.
|
| + return; |
| + } |
| + |
| + SetTypeOf(def, ZoneCompileType::Wrap(current->CopyNonNullable())); |
| +} |
| + |
| + |
| void FlowGraphTypePropagator::VisitValue(Value* value) { |
| CompileType* type = TypeOf(value->definition()); |
| value->SetReachingType(type); |
| @@ -786,6 +847,11 @@ CompileType LoadFieldInstr::ComputeType() const { |
| return CompileType::FromAbstractType(type()); |
| } |
| + if (field_ != NULL) { |
| + return CompileType::CreateNullable(field_->is_nullable(), |
| + field_->guarded_cid()); |
| + } |
| + |
| return CompileType::FromCid(result_cid_); |
| } |