| 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..1ff043cfd0b8c4c6fd957a5efb71b27dafa6728c 100644
|
| --- a/runtime/vm/flow_graph_type_propagator.cc
|
| +++ b/runtime/vm/flow_graph_type_propagator.cc
|
| @@ -20,6 +20,7 @@ DECLARE_FLAG(bool, use_cha);
|
| FlowGraphTypePropagator::FlowGraphTypePropagator(FlowGraph* flow_graph)
|
| : FlowGraphVisitor(flow_graph->reverse_postorder()),
|
| flow_graph_(flow_graph),
|
| + visited_blocks_(new BitVector(flow_graph->reverse_postorder().length())),
|
| types_(flow_graph->current_ssa_temp_index()),
|
| in_worklist_(new BitVector(flow_graph->current_ssa_temp_index())),
|
| asserts_(NULL),
|
| @@ -89,6 +90,11 @@ void FlowGraphTypePropagator::Propagate() {
|
|
|
|
|
| void FlowGraphTypePropagator::PropagateRecursive(BlockEntryInstr* block) {
|
| + if (visited_blocks_->Contains(block->postorder_number())) {
|
| + return;
|
| + }
|
| + visited_blocks_->Add(block->postorder_number());
|
| +
|
| const intptr_t rollback_point = rollback_.length();
|
|
|
| if (FLAG_enable_type_checks) {
|
| @@ -119,10 +125,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->right()->BindsToConstantNull()) {
|
| + return;
|
| + }
|
| +
|
| + const intptr_t rollback_point = rollback_.length();
|
| +
|
| + Definition* defn = compare->left()->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,9 +197,17 @@ 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)) {
|
| + SetTypeOf(def, ZoneCompileType::Wrap(CompileType::FromCid(cid)));
|
| + }
|
| +}
|
|
|
| - SetTypeOf(def, ZoneCompileType::Wrap(CompileType::FromCid(cid)));
|
| +
|
| +void FlowGraphTypePropagator::MarkNonNullable(Definition* def) {
|
| + CompileType* current = TypeOf(def);
|
| + if (!current->IsNone() && current->is_nullable()) {
|
| + SetTypeOf(def, ZoneCompileType::Wrap(current->CopyNonNullable()));
|
| + }
|
| }
|
|
|
|
|
| @@ -786,6 +840,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_);
|
| }
|
|
|
|
|