// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/compiler/backend/type_propagator.h"

#include "platform/text_buffer.h"

#include "vm/bit_vector.h"
#include "vm/compiler/compiler_state.h"
#include "vm/object_store.h"
#include "vm/regexp_assembler.h"
#include "vm/resolver.h"
#include "vm/timeline.h"

namespace dart {

DEFINE_FLAG(bool,
            trace_type_propagation,
            false,
            "Trace flow graph type propagation");

static void TraceStrongModeType(const Instruction* instr,
                                const AbstractType& type) {
  if (FLAG_trace_strong_mode_types) {
    THR_Print("[Strong mode] Type of %s - %s\n", instr->ToCString(),
              type.ToCString());
  }
}

static void TraceStrongModeType(const Instruction* instr,
                                CompileType* compileType) {
  if (FLAG_trace_strong_mode_types) {
    const AbstractType* type = compileType->ToAbstractType();
    if ((type != NULL) && !type->IsDynamicType()) {
      TraceStrongModeType(instr, *type);
    }
  }
}

void FlowGraphTypePropagator::Propagate(FlowGraph* flow_graph) {
  TIMELINE_DURATION(flow_graph->thread(), CompilerVerbose,
                    "FlowGraphTypePropagator");
  FlowGraphTypePropagator propagator(flow_graph);
  propagator.Propagate();
}

FlowGraphTypePropagator::FlowGraphTypePropagator(FlowGraph* flow_graph)
    : FlowGraphVisitor(flow_graph->reverse_postorder()),
      flow_graph_(flow_graph),
      is_aot_(CompilerState::Current().is_aot()),
      visited_blocks_(new (flow_graph->zone())
                          BitVector(flow_graph->zone(),
                                    flow_graph->reverse_postorder().length())),
      types_(flow_graph->current_ssa_temp_index()),
      in_worklist_(NULL),
      asserts_(NULL),
      collected_asserts_(NULL) {
  for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) {
    types_.Add(NULL);
  }

  asserts_ = new ZoneGrowableArray<AssertAssignableInstr*>(
      flow_graph->current_ssa_temp_index());
  for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) {
    asserts_->Add(NULL);
  }

  collected_asserts_ = new ZoneGrowableArray<intptr_t>(10);
}

void FlowGraphTypePropagator::Propagate() {
  // Walk the dominator tree and propagate reaching types to all Values.
  // Collect all phis for a fixed point iteration.
  PropagateRecursive(flow_graph_->graph_entry());

  // Initially the worklist contains only phis.
  // Reset compile type of all phis to None to ensure that
  // types are correctly propagated through the cycles of
  // phis.
  in_worklist_ = new (flow_graph_->zone())
      BitVector(flow_graph_->zone(), flow_graph_->current_ssa_temp_index());
  for (intptr_t i = 0; i < worklist_.length(); i++) {
    ASSERT(worklist_[i]->IsPhi());
    *worklist_[i]->Type() = CompileType::None();
  }

  // Iterate until a fixed point is reached, updating the types of
  // definitions.
  while (!worklist_.is_empty()) {
    Definition* def = RemoveLastFromWorklist();
    if (FLAG_support_il_printer && FLAG_trace_type_propagation &&
        flow_graph_->should_print()) {
      THR_Print("recomputing type of v%" Pd ": %s\n", def->ssa_temp_index(),
                def->Type()->ToCString());
    }
    if (def->RecomputeType()) {
      if (FLAG_support_il_printer && FLAG_trace_type_propagation &&
          flow_graph_->should_print()) {
        THR_Print("  ... new type %s\n", def->Type()->ToCString());
      }
      for (Value::Iterator it(def->input_use_list()); !it.Done();
           it.Advance()) {
        Instruction* instr = it.Current()->instruction();

        Definition* use_defn = instr->AsDefinition();
        if (use_defn != NULL) {
          AddToWorklist(use_defn);
        }
      }
    }
  }
}

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 (!is_aot_) {
    // Don't try to strengthen asserts with class checks in AOT mode, this is a
    // speculative optimization which only really makes sense in JIT mode.
    // It is also written to expect environments to be attached to
    // AssertAssignable instructions, which is not always a case in AOT mode.
    StrengthenAsserts(block);
  }

  block->Accept(this);

  for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
    Instruction* instr = it.Current();

    for (intptr_t i = 0; i < instr->InputCount(); i++) {
      VisitValue(instr->InputAt(i));
    }
    if (instr->IsDefinition()) {
      instr->AsDefinition()->RecomputeType();
    }
    instr->Accept(this);
  }

  GotoInstr* goto_instr = block->last_instruction()->AsGoto();
  if (goto_instr != NULL) {
    JoinEntryInstr* join = goto_instr->successor();
    intptr_t pred_index = join->IndexOfPredecessor(block);
    ASSERT(pred_index >= 0);
    for (PhiIterator it(join); !it.Done(); it.Advance()) {
      VisitValue(it.Current()->InputAt(pred_index));
    }
  }

  for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) {
    PropagateRecursive(block->dominated_blocks()[i]);
  }

  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();
  }
  rollback_.TruncateTo(rollback_point);
}

CompileType* FlowGraphTypePropagator::TypeOf(Definition* def) {
  const intptr_t index = def->ssa_temp_index();

  CompileType* type = types_[index];
  if (type == NULL) {
    type = types_[index] = def->Type();
    ASSERT(type != NULL);
  }
  return type;
}

void FlowGraphTypePropagator::SetTypeOf(Definition* def, CompileType* type) {
  const intptr_t index = def->ssa_temp_index();
  rollback_.Add(RollbackEntry(index, types_[index]));
  types_[index] = type;
}

void FlowGraphTypePropagator::SetCid(Definition* def, intptr_t cid) {
  CompileType* current = TypeOf(def);
  if (current->IsNone() || (current->ToCid() != cid)) {
    SetTypeOf(def, new (zone()) CompileType(CompileType::FromCid(cid)));
  }
}

void FlowGraphTypePropagator::GrowTypes(intptr_t up_to) {
  // Grow types array if a new redefinition was inserted.
  for (intptr_t i = types_.length(); i <= up_to; ++i) {
    types_.Add(nullptr);
  }
}

void FlowGraphTypePropagator::EnsureMoreAccurateRedefinition(
    Instruction* prev,
    Definition* original,
    CompileType new_type) {
  RedefinitionInstr* redef =
      flow_graph_->EnsureRedefinition(prev, original, new_type);
  if (redef != nullptr) {
    GrowTypes(redef->ssa_temp_index() + 1);
  }
}

void FlowGraphTypePropagator::VisitValue(Value* value) {
  CompileType* type = TypeOf(value->definition());

  // Force propagation of None type (which means unknown) to inputs of phis
  // in order to avoid contamination of cycles of phis with previously inferred
  // types.
  if (type->IsNone() && value->instruction()->IsPhi()) {
    value->SetReachingType(type);
  } else {
    value->RefineReachingType(type);
  }

  if (FLAG_support_il_printer && FLAG_trace_type_propagation &&
      flow_graph_->should_print()) {
    THR_Print("reaching type to %s for v%" Pd " is %s\n",
              value->instruction()->ToCString(),
              value->definition()->ssa_temp_index(),
              value->Type()->ToCString());
  }
}

void FlowGraphTypePropagator::VisitJoinEntry(JoinEntryInstr* join) {
  for (PhiIterator it(join); !it.Done(); it.Advance()) {
    worklist_.Add(it.Current());
  }
}

void FlowGraphTypePropagator::VisitCheckSmi(CheckSmiInstr* check) {
  SetCid(check->value()->definition(), kSmiCid);
}

void FlowGraphTypePropagator::VisitCheckArrayBound(
    CheckArrayBoundInstr* check) {
  // Array bounds checks also test index for smi.
  SetCid(check->index()->definition(), kSmiCid);
}

void FlowGraphTypePropagator::VisitCheckClass(CheckClassInstr* check) {
  // Use a monomorphic cid directly.
  const Cids& cids = check->cids();
  if (cids.IsMonomorphic()) {
    SetCid(check->value()->definition(), cids.MonomorphicReceiverCid());
    return;
  }
  // Take the union of polymorphic cids.
  CompileType result = CompileType::None();
  for (intptr_t i = 0, n = cids.length(); i < n; i++) {
    CidRange* cid_range = cids.At(i);
    if (cid_range->IsIllegalRange()) {
      return;
    }
    for (intptr_t cid = cid_range->cid_start; cid <= cid_range->cid_end;
         cid++) {
      CompileType tp = CompileType::FromCid(cid);
      result.Union(&tp);
    }
  }
  if (!result.IsNone()) {
    SetTypeOf(check->value()->definition(), new (zone()) CompileType(result));
  }
}

void FlowGraphTypePropagator::VisitCheckClassId(CheckClassIdInstr* check) {
  LoadClassIdInstr* load_cid =
      check->value()->definition()->OriginalDefinition()->AsLoadClassId();
  if (load_cid != NULL && check->cids().IsSingleCid()) {
    SetCid(load_cid->object()->definition(), check->cids().cid_start);
  }
}

void FlowGraphTypePropagator::VisitCheckNull(CheckNullInstr* check) {
  Definition* receiver = check->value()->definition();
  CompileType* type = TypeOf(receiver);
  if (type->is_nullable()) {
    // If the type is nullable, translate an implicit control
    // dependence to an explicit data dependence at this point
    // to guard against invalid code motion later. Valid code
    // motion of the check may still enable valid code motion
    // of the checked code.
    if (check->ssa_temp_index() == -1) {
      flow_graph_->AllocateSSAIndexes(check);
      GrowTypes(check->ssa_temp_index() + 1);
    }
    FlowGraph::RenameDominatedUses(receiver, check, check);
    // Set non-nullable type on check itself (but avoid None()).
    CompileType result = type->CopyNonNullable();
    if (!result.IsNone()) {
      SetTypeOf(check, new (zone()) CompileType(result));
    }
  }
}

void FlowGraphTypePropagator::CheckNonNullSelector(
    Instruction* call,
    Definition* receiver,
    const String& function_name) {
  if (!receiver->Type()->is_nullable()) {
    // Nothing to do if type is already non-nullable.
    return;
  }
  Thread* thread = Thread::Current();
  const Class& null_class =
      Class::Handle(thread->isolate_group()->object_store()->null_class());
  Function& target = Function::Handle();
  if (Error::Handle(null_class.EnsureIsFinalized(thread)).IsNull()) {
    target = Resolver::ResolveDynamicAnyArgs(thread->zone(), null_class,
                                             function_name);
  }
  if (target.IsNull()) {
    // If the selector is not defined on Null, we can propagate non-nullness.
    CompileType* type = TypeOf(receiver);
    if (type->is_nullable()) {
      // Insert redefinition for the receiver to guard against invalid
      // code motion.
      EnsureMoreAccurateRedefinition(call, receiver, type->CopyNonNullable());
    }
  }
}

void FlowGraphTypePropagator::VisitInstanceCall(InstanceCallInstr* instr) {
  if (instr->has_unique_selector()) {
    SetCid(instr->Receiver()->definition(),
           instr->ic_data()->GetReceiverClassIdAt(0));
    return;
  }
  CheckNonNullSelector(instr, instr->Receiver()->definition(),
                       instr->function_name());
}

void FlowGraphTypePropagator::VisitPolymorphicInstanceCall(
    PolymorphicInstanceCallInstr* instr) {
  if (instr->has_unique_selector()) {
    SetCid(instr->Receiver()->definition(),
           instr->targets().MonomorphicReceiverCid());
    return;
  }
  CheckNonNullSelector(instr, instr->Receiver()->definition(),
                       instr->function_name());
}

void FlowGraphTypePropagator::VisitGuardFieldClass(
    GuardFieldClassInstr* guard) {
  const intptr_t cid = guard->field().guarded_cid();
  if ((cid == kIllegalCid) || (cid == kDynamicCid)) {
    return;
  }

  Definition* def = guard->value()->definition();
  CompileType* current = TypeOf(def);
  if (current->IsNone() || (current->ToCid() != cid) ||
      (current->is_nullable() && !guard->field().is_nullable())) {
    const bool is_nullable =
        guard->field().is_nullable() && current->is_nullable();
    SetTypeOf(def,
              new (zone()) CompileType(
                  is_nullable, CompileType::kCannotBeSentinel, cid, nullptr));
  }
}

void FlowGraphTypePropagator::VisitAssertAssignable(
    AssertAssignableInstr* instr) {
  SetTypeOf(instr->value()->definition(),
            new (zone()) CompileType(instr->ComputeType()));
}

void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanInstr* instr) {
  SetTypeOf(instr->value()->definition(),
            new (zone()) CompileType(CompileType::Bool()));
}

void FlowGraphTypePropagator::VisitAssertSubtype(AssertSubtypeInstr* instr) {}

void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) {
  StrictCompareInstr* comparison = instr->comparison()->AsStrictCompare();
  if (comparison == NULL) return;
  bool negated = comparison->kind() == Token::kNE_STRICT;
  LoadClassIdInstr* load_cid =
      comparison->InputAt(0)->definition()->AsLoadClassId();
  InstanceCallInstr* call =
      comparison->InputAt(0)->definition()->AsInstanceCall();
  InstanceOfInstr* instance_of =
      comparison->InputAt(0)->definition()->AsInstanceOf();
  bool is_simple_instance_of =
      (call != NULL) && call->MatchesCoreName(Symbols::_simpleInstanceOf());
  if (load_cid != NULL && comparison->InputAt(1)->BindsToConstant()) {
    intptr_t cid = Smi::Cast(comparison->InputAt(1)->BoundConstant()).Value();
    BlockEntryInstr* true_successor =
        negated ? instr->false_successor() : instr->true_successor();
    EnsureMoreAccurateRedefinition(true_successor,
                                   load_cid->object()->definition(),
                                   CompileType::FromCid(cid));
  } else if ((is_simple_instance_of || (instance_of != NULL)) &&
             comparison->InputAt(1)->BindsToConstant() &&
             comparison->InputAt(1)->BoundConstant().IsBool()) {
    if (comparison->InputAt(1)->BoundConstant().ptr() == Bool::False().ptr()) {
      negated = !negated;
    }
    BlockEntryInstr* true_successor =
        negated ? instr->false_successor() : instr->true_successor();
    const AbstractType* type = NULL;
    Definition* left = NULL;
    if (is_simple_instance_of) {
      ASSERT(call->ArgumentAt(1)->IsConstant());
      const Object& type_obj = call->ArgumentAt(1)->AsConstant()->value();
      if (!type_obj.IsType()) {
        return;
      }
      type = &Type::Cast(type_obj);
      left = call->ArgumentAt(0);
    } else {
      type = &(instance_of->type());
      left = instance_of->value()->definition();
    }
    if (!type->IsTopTypeForInstanceOf()) {
      const bool is_nullable = (type->IsNullable() || type->IsTypeParameter() ||
                                (type->IsNeverType() && type->IsLegacy()))
                                   ? CompileType::kCanBeNull
                                   : CompileType::kCannotBeNull;
      EnsureMoreAccurateRedefinition(
          true_successor, left,
          CompileType::FromAbstractType(*type, is_nullable,
                                        CompileType::kCannotBeSentinel));
    }
  } 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();
    EnsureMoreAccurateRedefinition(
        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();
    EnsureMoreAccurateRedefinition(
        true_successor, comparison->InputAt(0)->definition(),
        comparison->InputAt(0)->Type()->CopyNonNullable());
  } else if (comparison->InputAt(0)->BindsToConstant() &&
             comparison->InputAt(0)->BoundConstant().ptr() ==
                 Object::sentinel().ptr()) {
    // Handle for expr != sentinel.
    BlockEntryInstr* true_successor =
        negated ? instr->true_successor() : instr->false_successor();
    EnsureMoreAccurateRedefinition(
        true_successor, comparison->InputAt(1)->definition(),
        comparison->InputAt(1)->Type()->CopyNonSentinel());

  } else if (comparison->InputAt(1)->BindsToConstant() &&
             comparison->InputAt(1)->BoundConstant().ptr() ==
                 Object::sentinel().ptr()) {
    // Handle for sentinel != expr.
    BlockEntryInstr* true_successor =
        negated ? instr->true_successor() : instr->false_successor();
    EnsureMoreAccurateRedefinition(
        true_successor, comparison->InputAt(0)->definition(),
        comparison->InputAt(0)->Type()->CopyNonSentinel());
  }
  // TODO(fschneider): Add propagation for generic is-tests.
}

void FlowGraphTypePropagator::AddToWorklist(Definition* defn) {
  if (defn->ssa_temp_index() == -1) {
    return;
  }

  const intptr_t index = defn->ssa_temp_index();
  if (!in_worklist_->Contains(index)) {
    worklist_.Add(defn);
    in_worklist_->Add(index);
  }
}

Definition* FlowGraphTypePropagator::RemoveLastFromWorklist() {
  Definition* defn = worklist_.RemoveLast();
  ASSERT(defn->ssa_temp_index() != -1);
  in_worklist_->Remove(defn->ssa_temp_index());
  return defn;
}

// In the given block strengthen type assertions by hoisting first class or smi
// check over the same value up to the point before the assertion. This allows
// to eliminate type assertions that are postdominated by class or smi checks as
// these checks are strongly stricter than type assertions.
void FlowGraphTypePropagator::StrengthenAsserts(BlockEntryInstr* block) {
  for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
    Instruction* instr = it.Current();

    if (instr->IsCheckSmi() || instr->IsCheckClass()) {
      StrengthenAssertWith(instr);
    }

    // If this is the first type assertion checking given value record it.
    AssertAssignableInstr* assert = instr->AsAssertAssignable();
    if (assert != NULL) {
      Definition* defn = assert->value()->definition()->OriginalDefinition();
      if ((*asserts_)[defn->ssa_temp_index()] == NULL) {
        (*asserts_)[defn->ssa_temp_index()] = assert;
        collected_asserts_->Add(defn->ssa_temp_index());
      }
    }
  }

  for (intptr_t i = 0; i < collected_asserts_->length(); i++) {
    (*asserts_)[(*collected_asserts_)[i]] = NULL;
  }

  collected_asserts_->TruncateTo(0);
}

void FlowGraphTypePropagator::StrengthenAssertWith(Instruction* check) {
  // Marker that is used to mark values that already had type assertion
  // strengthened.
  AssertAssignableInstr* kStrengthenedAssertMarker =
      reinterpret_cast<AssertAssignableInstr*>(-1);

  Definition* defn = check->InputAt(0)->definition()->OriginalDefinition();

  AssertAssignableInstr* assert = (*asserts_)[defn->ssa_temp_index()];
  if ((assert == NULL) || (assert == kStrengthenedAssertMarker)) {
    return;
  }
  ASSERT(assert->env() != NULL);

  Instruction* check_clone = NULL;
  if (check->IsCheckSmi()) {
    check_clone = new CheckSmiInstr(assert->value()->Copy(zone()),
                                    assert->deopt_id(), check->source());
    check_clone->AsCheckSmi()->set_licm_hoisted(
        check->AsCheckSmi()->licm_hoisted());
  } else {
    ASSERT(check->IsCheckClass());
    check_clone =
        new CheckClassInstr(assert->value()->Copy(zone()), assert->deopt_id(),
                            check->AsCheckClass()->cids(), check->source());
    check_clone->AsCheckClass()->set_licm_hoisted(
        check->AsCheckClass()->licm_hoisted());
  }
  ASSERT(check_clone != NULL);
  check_clone->InsertBefore(assert);
  assert->env()->DeepCopyTo(zone(), check_clone);

  (*asserts_)[defn->ssa_temp_index()] = kStrengthenedAssertMarker;
}

void CompileType::Union(CompileType* other) {
  if (other->IsNone()) {
    return;
  }

  if (IsNone()) {
    *this = *other;
    return;
  }

  can_be_null_ = can_be_null_ || other->can_be_null_;
  can_be_sentinel_ = can_be_sentinel_ || other->can_be_sentinel_;

  ToNullableCid();  // Ensure cid_ is set.
  if ((cid_ == kNullCid) || (cid_ == kSentinelCid)) {
    cid_ = other->cid_;
    type_ = other->type_;
    return;
  }

  other->ToNullableCid();  // Ensure other->cid_ is set.
  if ((other->cid_ == kNullCid) || (other->cid_ == kSentinelCid)) {
    return;
  }

  const AbstractType* abstract_type = ToAbstractType();
  if (cid_ != other->cid_) {
    cid_ = kDynamicCid;
  }

  const AbstractType* other_abstract_type = other->ToAbstractType();
  if (abstract_type->IsSubtypeOf(*other_abstract_type, Heap::kOld)) {
    type_ = other_abstract_type;
    return;
  } else if (other_abstract_type->IsSubtypeOf(*abstract_type, Heap::kOld)) {
    return;  // Nothing to do.
  }

  // Climb up the hierarchy to find a suitable supertype. Note that interface
  // types are not considered, making the union potentially non-commutative
  if (abstract_type->IsInstantiated() && !abstract_type->IsDynamicType() &&
      !abstract_type->IsFunctionType()) {
    Class& cls = Class::Handle(abstract_type->type_class());
    for (; !cls.IsNull() && !cls.IsGeneric(); cls = cls.SuperClass()) {
      type_ = &AbstractType::ZoneHandle(cls.RareType());
      if (other_abstract_type->IsSubtypeOf(*type_, Heap::kOld)) {
        // Found suitable supertype: keep type_ only.
        cid_ = kDynamicCid;
        return;
      }
    }
  }

  // Can't unify.
  type_ = &Object::dynamic_type();
}

CompileType* CompileType::ComputeRefinedType(CompileType* old_type,
                                             CompileType* new_type) {
  ASSERT(new_type != nullptr);

  // In general, prefer the newly inferred type over old type.
  // It is possible that new and old types are unrelated or do not intersect
  // at all (for example, in case of unreachable code).

  // Discard None type as it is used to denote an unknown type.
  if (old_type == nullptr || old_type->IsNone()) {
    return new_type;
  }
  if (new_type->IsNone()) {
    return old_type;
  }

  // Prefer exact Cid if known.
  if (new_type->ToCid() != kDynamicCid) {
    return new_type;
  }
  if (old_type->ToCid() != kDynamicCid) {
    return old_type;
  }

  const AbstractType* old_abstract_type = old_type->ToAbstractType();
  const AbstractType* new_abstract_type = new_type->ToAbstractType();

  CompileType* preferred_type;
  if (old_abstract_type->IsSubtypeOf(*new_abstract_type, Heap::kOld)) {
    // Prefer old type, as it is clearly more specific.
    preferred_type = old_type;
  } else {
    // Prefer new type as it is more recent, even though it might be
    // no better than the old type.
    preferred_type = new_type;
  }

  // Refine non-nullability and whether it can be sentinel.
  const bool can_be_null = old_type->is_nullable() && new_type->is_nullable();
  const bool can_be_sentinel =
      old_type->can_be_sentinel() && new_type->can_be_sentinel();

  if ((preferred_type->is_nullable() && !can_be_null) ||
      (preferred_type->can_be_sentinel() && !can_be_sentinel)) {
    return new CompileType(can_be_null, can_be_sentinel, preferred_type->cid_,
                           preferred_type->type_);
  } else {
    ASSERT(preferred_type->is_nullable() == can_be_null);
    ASSERT(preferred_type->can_be_sentinel() == can_be_sentinel);
    return preferred_type;
  }
}

CompileType CompileType::FromAbstractType(const AbstractType& type,
                                          bool can_be_null,
                                          bool can_be_sentinel) {
  return CompileType(can_be_null && !type.IsStrictlyNonNullable(),
                     can_be_sentinel, kIllegalCid, &type);
}

CompileType CompileType::FromCid(intptr_t cid) {
  ASSERT(cid != kIllegalCid);
  ASSERT(cid != kDynamicCid);
  return CompileType(cid == kNullCid, cid == kSentinelCid, cid, nullptr);
}

CompileType CompileType::Dynamic() {
  return CompileType(kCanBeNull, kCannotBeSentinel, kDynamicCid,
                     &Object::dynamic_type());
}

CompileType CompileType::Null() {
  return CompileType(kCanBeNull, kCannotBeSentinel, kNullCid,
                     &Type::ZoneHandle(Type::NullType()));
}

CompileType CompileType::Bool() {
  return CompileType(kCannotBeNull, kCannotBeSentinel, kBoolCid,
                     &Type::ZoneHandle(Type::BoolType()));
}

CompileType CompileType::Int() {
  return FromAbstractType(Type::ZoneHandle(Type::IntType()), kCannotBeNull,
                          kCannotBeSentinel);
}

CompileType CompileType::Int32() {
#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
  return FromCid(kSmiCid);
#else
  return Int();
#endif
}

CompileType CompileType::NullableInt() {
  return FromAbstractType(Type::ZoneHandle(Type::NullableIntType()), kCanBeNull,
                          kCannotBeSentinel);
}

CompileType CompileType::Smi() {
  return CompileType(kCannotBeNull, kCannotBeSentinel, kSmiCid,
                     &Type::ZoneHandle(Type::SmiType()));
}

CompileType CompileType::Double() {
  return CompileType(kCannotBeNull, kCannotBeSentinel, kDoubleCid,
                     &Type::ZoneHandle(Type::Double()));
}

CompileType CompileType::NullableDouble() {
  return FromAbstractType(Type::ZoneHandle(Type::NullableDouble()), kCanBeNull,
                          kCannotBeSentinel);
}

CompileType CompileType::String() {
  return FromAbstractType(Type::ZoneHandle(Type::StringType()), kCannotBeNull,
                          kCannotBeSentinel);
}

intptr_t CompileType::ToCid() {
  if (cid_ == kIllegalCid) {
    // Make sure to initialize cid_ for Null type to consistently return
    // kNullCid.
    if ((type_ != NULL) && type_->IsNullType()) {
      cid_ = kNullCid;
    }
    // Same for sentinel.
    if ((type_ != NULL) && type_->IsSentinelType()) {
      cid_ = kSentinelCid;
    }
  }

  if ((cid_ == kDynamicCid) || (can_be_null_ && (cid_ != kNullCid)) ||
      (can_be_sentinel_ && (cid_ != kSentinelCid))) {
    return kDynamicCid;
  }

  return ToNullableCid();
}

intptr_t CompileType::ToNullableCid() {
  if (cid_ == kIllegalCid) {
    if (type_ == NULL) {
      // Type propagation is turned off or has not yet run.
      return kDynamicCid;
    } else if (type_->IsVoidType()) {
      cid_ = kDynamicCid;
    } else if (type_->IsNullType()) {
      cid_ = kNullCid;
    } else if (type_->IsSentinelType()) {
      cid_ = kSentinelCid;
    } else if (type_->IsFunctionType() || type_->IsDartFunctionType()) {
      cid_ = kClosureCid;
    } else if (type_->type_class_id() != kIllegalCid) {
      const Class& type_class = Class::Handle(type_->type_class());
      Thread* thread = Thread::Current();
      CHA& cha = thread->compiler_state().cha();
      // Don't infer a cid from an abstract type since there can be multiple
      // compatible classes with different cids.
      if (!type_class.is_abstract() && !CHA::IsImplemented(type_class) &&
          !CHA::HasSubclasses(type_class)) {
        if (type_class.IsPrivate()) {
          // Type of a private class cannot change through later loaded libs.
          cid_ = type_class.id();
        } else if (FLAG_use_cha_deopt ||
                   thread->isolate_group()->all_classes_finalized()) {
          if (FLAG_trace_cha) {
            THR_Print("  **(CHA) Compile type not subclassed: %s\n",
                      type_class.ToCString());
          }
          if (FLAG_use_cha_deopt) {
            cha.AddToGuardedClasses(type_class, /*subclass_count=*/0);
          }
          cid_ = type_class.id();
        } else {
          cid_ = kDynamicCid;
        }
      } else {
        cid_ = kDynamicCid;
      }
    } else {
      cid_ = kDynamicCid;
    }
  }

  if (can_be_sentinel_ && (cid_ != kSentinelCid)) {
    return kDynamicCid;
  }

  return cid_;
}

bool CompileType::HasDecidableNullability() {
  return !can_be_null_ || IsNull();
}

bool CompileType::IsNull() {
  return (ToCid() == kNullCid);
}

const AbstractType* CompileType::ToAbstractType() {
  if (type_ == NULL) {
    // Type propagation has not run. Return dynamic-type.
    if (cid_ == kIllegalCid) {
      return &Object::dynamic_type();
    }

    // VM-internal objects don't have a compile-type. Return dynamic-type
    // in this case.
    if ((cid_ < kInstanceCid) || (cid_ == kTypeArgumentsCid)) {
      type_ = &Object::dynamic_type();
      return type_;
    }

    auto IG = IsolateGroup::Current();
    const Class& type_class = Class::Handle(IG->class_table()->At(cid_));
    type_ = &AbstractType::ZoneHandle(type_class.RareType());
  }

  return type_;
}

bool CompileType::IsSubtypeOf(const AbstractType& other) {
  if (other.IsTopTypeForSubtyping()) {
    return true;
  }

  if (IsNone()) {
    return false;
  }

  return ToAbstractType()->IsSubtypeOf(other, Heap::kOld);
}

bool CompileType::IsAssignableTo(const AbstractType& other) {
  if (other.IsTopTypeForSubtyping()) {
    return true;
  }
  if (IsNone()) {
    return false;
  }
  if (is_nullable() && !Instance::NullIsAssignableTo(other)) {
    return false;
  }
  return ToAbstractType()->IsSubtypeOf(other, Heap::kOld);
}

bool CompileType::IsInstanceOf(const AbstractType& other) {
  if (other.IsTopTypeForInstanceOf()) {
    return true;
  }
  if (IsNone() || !other.IsInstantiated()) {
    return false;
  }
  if (is_nullable() && !other.IsNullable()) {
    return false;
  }
  return ToAbstractType()->IsSubtypeOf(other, Heap::kOld);
}

bool CompileType::Specialize(GrowableArray<intptr_t>* class_ids) {
  ToNullableCid();
  if (cid_ != kDynamicCid) {
    class_ids->Add(cid_);
    return true;
  }
  if (type_ != nullptr && type_->type_class_id() != kIllegalCid) {
    const Class& type_class = Class::Handle(type_->type_class());
    if (!CHA::ConcreteSubclasses(type_class, class_ids)) return false;
    if (can_be_null_) {
      class_ids->Add(kNullCid);
    }
    if (can_be_sentinel_) {
      class_ids->Add(kSentinelCid);
    }
  }
  return false;
}

// For the given type conservatively computes whether Smi can potentially
// appear in a location of this type.
//
// If recurse is false this function will not call itself recursively
// to prevent infinite recursion when traversing a cycle in type parameter
// bounds.
static bool CanPotentiallyBeSmi(const AbstractType& type, bool recurse) {
  if (type.IsInstantiated()) {
    return CompileType::Smi().IsAssignableTo(type);
  } else if (type.IsTypeParameter()) {
    // For type parameters look at their bounds (if recurse allows us).
    const auto& param = TypeParameter::Cast(type);
    return !recurse || CanPotentiallyBeSmi(AbstractType::Handle(param.bound()),
                                           /*recurse=*/false);
  } else if (type.HasTypeClass()) {
    // If this is an unstantiated type then it can only potentially be a super
    // type of a Smi if it is either FutureOr<...> or Comparable<...>.
    // In which case we need to look at the type argument to determine whether
    // this location can contain a smi.
    //
    // Note: we are making a simplification here. This approach will yield
    // true for Comparable<T> where T extends int - while in reality Smi is
    // *not* assignable to it (because int implements Comparable<num> and not
    // Comparable<int>).
    if (type.IsFutureOrType() ||
        type.type_class() == CompilerState::Current().ComparableClass().ptr()) {
      // Type may be a TypeRef.
      const auto& args = TypeArguments::Handle(type.arguments());
      const auto& arg0 = AbstractType::Handle(args.TypeAt(0));
      return !recurse || CanPotentiallyBeSmi(arg0, /*recurse=*/true);
    }
    return false;
  }
  return false;
}

bool CompileType::CanBeSmi() {
  // Fast path for known cid.
  if (cid_ != kIllegalCid && cid_ != kDynamicCid) {
    return cid_ == kSmiCid;
  }
  return CanPotentiallyBeSmi(*ToAbstractType(), /*recurse=*/true);
}

void CompileType::PrintTo(BaseTextBuffer* f) const {
  const char* type_name = "?";
  if (IsNone()) {
    f->AddString("T{}");
    return;
  } else if ((cid_ != kIllegalCid) && (cid_ != kDynamicCid)) {
    const Class& cls =
        Class::Handle(IsolateGroup::Current()->class_table()->At(cid_));
    type_name = String::Handle(cls.ScrubbedName()).ToCString();
  } else if (type_ != NULL) {
    type_name = type_->IsDynamicType()
                    ? "*"
                    : String::Handle(type_->ScrubbedName()).ToCString();
  } else if (!is_nullable()) {
    type_name = "!null";
  }

  f->Printf("T{%s%s%s}", type_name, can_be_null_ ? "?" : "",
            can_be_sentinel_ ? "~" : "");
}

const char* CompileType::ToCString() const {
  char buffer[1024];
  BufferFormatter f(buffer, sizeof(buffer));
  PrintTo(&f);
  return Thread::Current()->zone()->MakeCopyOfString(buffer);
}

CompileType* Value::Type() {
  if (reaching_type_ == NULL) {
    reaching_type_ = definition()->Type();
  }
  return reaching_type_;
}

void Value::SetReachingType(CompileType* type) {
  // If [type] is owned but not by the definition which flows into this use
  // then we need to disconect the type from original owner by cloning it.
  // This is done to prevent situations when [type] is updated by its owner
  // but [owner] is no longer connected to this use through def-use chain
  // and as a result type propagator does not recompute type of the current
  // instruction.
  if (type != nullptr && type->owner() != nullptr &&
      type->owner() != definition()) {
    type = new CompileType(*type);
  }
  reaching_type_ = type;
}

void Value::RefineReachingType(CompileType* type) {
  SetReachingType(CompileType::ComputeRefinedType(reaching_type_, type));
}

CompileType PhiInstr::ComputeType() const {
  // Initially type of phis is unknown until type propagation is run
  // for the first time.
  return CompileType::None();
}

bool PhiInstr::RecomputeType() {
  CompileType result = CompileType::None();
  for (intptr_t i = 0; i < InputCount(); i++) {
    if (FLAG_support_il_printer && FLAG_trace_type_propagation) {
      THR_Print("  phi %" Pd " input %" Pd ": v%" Pd " has reaching type %s\n",
                ssa_temp_index(), i, InputAt(i)->definition()->ssa_temp_index(),
                InputAt(i)->Type()->ToCString());
    }
    result.Union(InputAt(i)->Type());
  }

  if (result.IsNone()) {
    ASSERT(Type()->IsNone());
    return false;
  }

  return UpdateType(result);
}

CompileType RedefinitionInstr::ComputeType() const {
  if (constrained_type_ != NULL) {
    // Check if the type associated with this redefinition is more specific
    // than the type of its input. If yes, return it. Otherwise, fall back
    // to the input's 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();
    const bool can_be_sentinel = value()->Type()->can_be_sentinel() &&
                                 constrained_type_->can_be_sentinel();

    // If either type has a concrete cid, stick with it.
    if (value()->Type()->ToNullableCid() != kDynamicCid) {
      return CompileType(is_nullable, can_be_sentinel,
                         value()->Type()->ToNullableCid(), nullptr);
    }
    if (constrained_type_->ToNullableCid() != kDynamicCid) {
      return CompileType(is_nullable, can_be_sentinel,
                         constrained_type_->ToNullableCid(), nullptr);
    }
    if (value()->Type()->IsSubtypeOf(*constrained_type_->ToAbstractType())) {
      return is_nullable ? *value()->Type()
                         : value()->Type()->CopyNonNullable();
    } else {
      return is_nullable ? *constrained_type_
                         : constrained_type_->CopyNonNullable();
    }
  }
  return *value()->Type();
}

bool RedefinitionInstr::RecomputeType() {
  return UpdateType(ComputeType());
}

CompileType CheckNullInstr::ComputeType() const {
  CompileType* type = value()->Type();
  if (type->is_nullable()) {
    CompileType result = type->CopyNonNullable();
    if (!result.IsNone()) {
      return result;
    }
  }
  return *type;
}

bool CheckNullInstr::RecomputeType() {
  return UpdateType(ComputeType());
}

CompileType CheckArrayBoundInstr::ComputeType() const {
  return *index()->Type();
}

bool CheckArrayBoundInstr::RecomputeType() {
  return UpdateType(ComputeType());
}

CompileType GenericCheckBoundInstr::ComputeType() const {
  return *index()->Type();
}

bool GenericCheckBoundInstr::RecomputeType() {
  return UpdateType(ComputeType());
}

CompileType IfThenElseInstr::ComputeType() const {
  return CompileType::FromCid(kSmiCid);
}

CompileType ParameterInstr::ComputeType() const {
  // Note that returning the declared type of the formal parameter would be
  // incorrect, because ParameterInstr is used as input to the type check
  // verifying the run time type of the passed-in parameter and this check would
  // always be wrongly eliminated.
  // However there are parameters that are known to match their declared type:
  // for example receiver.
  GraphEntryInstr* graph_entry = block_->AsGraphEntry();
  if (graph_entry == NULL) {
    if (auto function_entry = block_->AsFunctionEntry()) {
      graph_entry = function_entry->graph_entry();
    } else if (auto osr_entry = block_->AsOsrEntry()) {
      graph_entry = osr_entry->graph_entry();
    } else if (auto catch_entry = block_->AsCatchBlockEntry()) {
      graph_entry = catch_entry->graph_entry();
    } else {
      UNREACHABLE();
    }
  }
  // Parameters at OSR entries have type dynamic.
  //
  // TODO(kmillikin): Use the actual type of the parameter at OSR entry.
  // The code below is not safe for OSR because it doesn't necessarily use
  // the correct scope.
  if (graph_entry->IsCompiledForOsr()) {
    return CompileType::Dynamic();
  }

  const Function& function = graph_entry->parsed_function().function();
  if (function.IsIrregexpFunction()) {
    // In irregexp functions, types of input parameters are known and immutable.
    // Set parameter types here in order to prevent unnecessary CheckClassInstr
    // from being generated.
    switch (index()) {
      case RegExpMacroAssembler::kParamRegExpIndex:
        return CompileType::FromCid(kRegExpCid);
      case RegExpMacroAssembler::kParamStringIndex:
        return CompileType::FromCid(function.string_specialization_cid());
      case RegExpMacroAssembler::kParamStartOffsetIndex:
        return CompileType::FromCid(kSmiCid);
      default:
        UNREACHABLE();
    }
    UNREACHABLE();
    return CompileType::Dynamic();
  }

  // Parameter is the receiver.
  if ((index() == 0) &&
      (function.IsDynamicFunction() || function.IsGenerativeConstructor())) {
    const AbstractType& type =
        graph_entry->parsed_function().RawParameterVariable(0)->type();
    if (type.IsObjectType() || type.IsNullType()) {
      // Receiver can be null.
      return CompileType::FromAbstractType(type, CompileType::kCanBeNull,
                                           CompileType::kCannotBeSentinel);
    }

    // Receiver can't be null but can be an instance of a subclass.
    intptr_t cid = kDynamicCid;

    if (type.type_class_id() != kIllegalCid) {
      Thread* thread = Thread::Current();
      const Class& type_class = Class::Handle(type.type_class());
      if (!CHA::HasSubclasses(type_class)) {
        if (type_class.IsPrivate()) {
          // Private classes can never be subclassed by later loaded libs.
          cid = type_class.id();
        } else {
          if (FLAG_use_cha_deopt ||
              thread->isolate_group()->all_classes_finalized()) {
            if (FLAG_trace_cha) {
              THR_Print(
                  "  **(CHA) Computing exact type of receiver, "
                  "no subclasses: %s\n",
                  type_class.ToCString());
            }
            if (FLAG_use_cha_deopt) {
              thread->compiler_state().cha().AddToGuardedClasses(
                  type_class,
                  /*subclass_count=*/0);
            }
            cid = type_class.id();
          }
        }
      }
    }

    return CompileType(CompileType::kCannotBeNull,
                       CompileType::kCannotBeSentinel, cid, &type);
  }

  const bool is_unchecked_entry_param =
      graph_entry->unchecked_entry() == block_;

  LocalScope* scope = graph_entry->parsed_function().scope();
  // Note: in catch-blocks we have ParameterInstr for each local variable
  // not only for normal parameters.
  const LocalVariable* param = nullptr;
  if (scope != nullptr && (index() < scope->num_variables())) {
    param = scope->VariableAt(index());
  } else if (index() < function.NumParameters()) {
    param = graph_entry->parsed_function().RawParameterVariable(index());
  }
  if (param != nullptr) {
    CompileType* inferred_type = NULL;
    if (!block_->IsCatchBlockEntry()) {
      inferred_type = param->parameter_type();
    }
    // Best bet: use inferred type if it is a concrete class or int.
    if ((inferred_type != nullptr) &&
        ((inferred_type->ToNullableCid() != kDynamicCid) ||
         inferred_type->IsNullableInt())) {
      TraceStrongModeType(this, inferred_type);
      return *inferred_type;
    }
    // If parameter type was checked by caller, then use Dart type annotation,
    // plus non-nullability from inferred type if known.
    // Do not trust static parameter type of 'operator ==' as it is a
    // non-nullable Object but VM handles comparison with null in
    // the callee, so 'operator ==' can take null as an argument.
    if ((function.name() != Symbols::EqualOperator().ptr()) &&
        (param->was_type_checked_by_caller() ||
         (is_unchecked_entry_param &&
          !param->is_explicit_covariant_parameter()))) {
      const bool is_nullable =
          (inferred_type == NULL) || inferred_type->is_nullable();
      TraceStrongModeType(this, param->type());
      return CompileType::FromAbstractType(
          param->type(), is_nullable,
          block_->IsCatchBlockEntry() && param->is_late());
    }
    // Last resort: use inferred non-nullability.
    if (inferred_type != NULL) {
      TraceStrongModeType(this, inferred_type);
      return *inferred_type;
    }
  }

  return CompileType::Dynamic();
}

CompileType PushArgumentInstr::ComputeType() const {
  return CompileType::Dynamic();
}

CompileType ConstantInstr::ComputeType() const {
  if (value().IsNull()) {
    return CompileType::Null();
  }

  intptr_t cid = value().GetClassId();

  if (cid == kSmiCid && !compiler::target::IsSmi(Smi::Cast(value()).Value())) {
    return CompileType(CompileType::kCannotBeNull,
                       CompileType::kCannotBeSentinel, kMintCid,
                       &AbstractType::ZoneHandle(Type::MintType()));
  }

  if ((cid != kTypeArgumentsCid) && value().IsInstance()) {
    // Allocate in old-space since this may be invoked from the
    // background compiler.
    return CompileType(
        cid == kNullCid, cid == kSentinelCid, cid,
        &AbstractType::ZoneHandle(Instance::Cast(value()).GetType(Heap::kOld)));
  } else {
    // Type info for non-instance objects.
    return CompileType::FromCid(cid);
  }
}

CompileType AssertAssignableInstr::ComputeType() const {
  CompileType* value_type = value()->Type();

  const AbstractType* abs_type = &AbstractType::dynamic_type();
  if (dst_type()->BindsToConstant() &&
      dst_type()->BoundConstant().IsAbstractType()) {
    abs_type = &AbstractType::Cast(dst_type()->BoundConstant());
    if (value_type->IsSubtypeOf(*abs_type)) {
      return *value_type;
    }
  }
  return CompileType::FromAbstractType(*abs_type, value_type->is_nullable(),
                                       CompileType::kCannotBeSentinel);
}

bool AssertAssignableInstr::RecomputeType() {
  return UpdateType(ComputeType());
}

CompileType AssertBooleanInstr::ComputeType() const {
  return CompileType::Bool();
}

CompileType BooleanNegateInstr::ComputeType() const {
  return CompileType::Bool();
}

CompileType InstanceOfInstr::ComputeType() const {
  return CompileType::Bool();
}

CompileType StrictCompareInstr::ComputeType() const {
  return CompileType::Bool();
}

CompileType TestSmiInstr::ComputeType() const {
  return CompileType::Bool();
}

CompileType TestCidsInstr::ComputeType() const {
  return CompileType::Bool();
}

CompileType EqualityCompareInstr::ComputeType() const {
  // Used for numeric comparisons only.
  return CompileType::Bool();
}

CompileType RelationalOpInstr::ComputeType() const {
  // Used for numeric comparisons only.
  return CompileType::Bool();
}

CompileType SpecialParameterInstr::ComputeType() const {
  switch (kind()) {
    case kContext:
      return CompileType::FromCid(kContextCid);
    case kTypeArgs:
      return CompileType::FromCid(kTypeArgumentsCid);
    case kArgDescriptor:
      return CompileType::FromCid(kImmutableArrayCid);
    case kException:
      return CompileType(CompileType::kCannotBeNull,
                         CompileType::kCannotBeSentinel, kDynamicCid,
                         &Object::dynamic_type());
    case kStackTrace:
      // We cannot use [kStackTraceCid] here because any kind of object can be
      // used as a stack trace via `new Future.error(..., <obj>)` :-/
      return CompileType::Dynamic();
  }
  UNREACHABLE();
  return CompileType::Dynamic();
}

CompileType CloneContextInstr::ComputeType() const {
  return CompileType(CompileType::kCannotBeNull, CompileType::kCannotBeSentinel,
                     kContextCid, &Object::dynamic_type());
}

CompileType AllocateContextInstr::ComputeType() const {
  return CompileType(CompileType::kCannotBeNull, CompileType::kCannotBeSentinel,
                     kContextCid, &Object::dynamic_type());
}

CompileType AllocateUninitializedContextInstr::ComputeType() const {
  return CompileType(CompileType::kCannotBeNull, CompileType::kCannotBeSentinel,
                     kContextCid, &Object::dynamic_type());
}

CompileType InstanceCallBaseInstr::ComputeType() const {
  // TODO(alexmarkov): calculate type of InstanceCallInstr eagerly
  // (in optimized mode) and avoid keeping separate result_type.
  CompileType* inferred_type = result_type();
  if ((inferred_type != NULL) &&
      (inferred_type->ToNullableCid() != kDynamicCid)) {
    TraceStrongModeType(this, inferred_type);
    return *inferred_type;
  }

  const Function& target = interface_target();
  if (!target.IsNull()) {
    const AbstractType& result_type =
        AbstractType::ZoneHandle(target.result_type());
    // Currently VM doesn't have enough information to instantiate generic
    // result types of interface targets:
    // 1. receiver type inferred by the front-end is not passed to VM.
    // 2. VM collects type arguments through the chain of superclasses but
    // not through implemented interfaces.
    // So treat non-instantiated generic types as dynamic to avoid pretending
    // the type is known.
    // TODO(dartbug.com/30480): instantiate generic result_type
    if (result_type.IsInstantiated()) {
      TraceStrongModeType(this, result_type);
      const bool is_nullable =
          (inferred_type == NULL) || inferred_type->is_nullable();
      return CompileType::FromAbstractType(result_type, is_nullable,
                                           CompileType::kCannotBeSentinel);
    }
  }

  return CompileType::Dynamic();
}

CompileType DispatchTableCallInstr::ComputeType() const {
  // TODO(dartbug.com/40188): Share implementation with InstanceCallBaseInstr.
  const Function& target = interface_target();
  ASSERT(!target.IsNull());
  const auto& result_type = AbstractType::ZoneHandle(target.result_type());
  if (result_type.IsInstantiated()) {
    TraceStrongModeType(this, result_type);
    return CompileType::FromAbstractType(result_type, CompileType::kCanBeNull,
                                         CompileType::kCannotBeSentinel);
  }

  return CompileType::Dynamic();
}

CompileType PolymorphicInstanceCallInstr::ComputeType() const {
  bool is_nullable = CompileType::kCanBeNull;
  if (IsSureToCallSingleRecognizedTarget()) {
    const Function& target = *targets_.TargetAt(0)->target;
    if (target.has_pragma()) {
      const intptr_t cid = MethodRecognizer::ResultCidFromPragma(target);
      if (cid != kDynamicCid) {
        return CompileType::FromCid(cid);
      } else if (MethodRecognizer::HasNonNullableResultTypeFromPragma(target)) {
        is_nullable = CompileType::kCannotBeNull;
      }
    }
  }

  CompileType type = InstanceCallBaseInstr::ComputeType();
  return is_nullable ? type : type.CopyNonNullable();
}

static CompileType ComputeListFactoryType(CompileType* inferred_type,
                                          Value* type_args_value) {
  ASSERT(inferred_type != nullptr);
  const intptr_t cid = inferred_type->ToNullableCid();
  ASSERT(cid != kDynamicCid);
  if ((cid == kGrowableObjectArrayCid || cid == kArrayCid ||
       cid == kImmutableArrayCid) &&
      type_args_value->BindsToConstant()) {
    const auto& type_args =
        type_args_value->BoundConstant().IsNull()
            ? TypeArguments::null_type_arguments()
            : TypeArguments::Cast(type_args_value->BoundConstant());
    const Class& cls =
        Class::Handle(IsolateGroup::Current()->class_table()->At(cid));
    Type& type =
        Type::ZoneHandle(Type::New(cls, type_args, Nullability::kNonNullable));
    ASSERT(type.IsInstantiated());
    type.SetIsFinalized();
    return CompileType(CompileType::kCannotBeNull,
                       CompileType::kCannotBeSentinel, cid, &type);
  }
  return *inferred_type;
}

CompileType StaticCallInstr::ComputeType() const {
  // TODO(alexmarkov): calculate type of StaticCallInstr eagerly
  // (in optimized mode) and avoid keeping separate result_type.
  CompileType* const inferred_type = result_type();
  if (is_known_list_constructor()) {
    return ComputeListFactoryType(inferred_type, ArgumentValueAt(0));
  }
  if ((inferred_type != NULL) &&
      (inferred_type->ToNullableCid() != kDynamicCid)) {
    return *inferred_type;
  }

  bool is_nullable = CompileType::kCanBeNull;
  if (function_.has_pragma()) {
    const intptr_t cid = MethodRecognizer::ResultCidFromPragma(function_);
    if (cid != kDynamicCid) {
      return CompileType::FromCid(cid);
    }
    if (MethodRecognizer::HasNonNullableResultTypeFromPragma(function_)) {
      is_nullable = CompileType::kCannotBeNull;
    }
  }

  const AbstractType& result_type =
      AbstractType::ZoneHandle(function().result_type());
  // TODO(dartbug.com/30480): instantiate generic result_type if possible.
  // Also, consider fixing AbstractType::IsSubtypeOf to handle
  // non-instantiated types properly.
  if (result_type.IsInstantiated()) {
    TraceStrongModeType(this, result_type);
    is_nullable = is_nullable &&
                  (inferred_type == nullptr || inferred_type->is_nullable());
    return CompileType::FromAbstractType(result_type, is_nullable,
                                         CompileType::kCannotBeSentinel);
  }

  return CompileType::Dynamic();
}

CompileType LoadLocalInstr::ComputeType() const {
  if (local().needs_covariant_check_in_method()) {
    // We may not yet have checked the actual type of the parameter value.
    // Assuming that the value has the required type can lead to unsound
    // optimizations. See dartbug.com/43464.
    return CompileType::Dynamic();
  }
  const AbstractType& local_type = local().type();
  TraceStrongModeType(this, local_type);
  return CompileType::FromAbstractType(local_type, CompileType::kCanBeNull,
                                       local().is_late());
}

CompileType DropTempsInstr::ComputeType() const {
  return *value()->Type();
}

CompileType StoreLocalInstr::ComputeType() const {
  // Returns stored value.
  return *value()->Type();
}

CompileType OneByteStringFromCharCodeInstr::ComputeType() const {
  return CompileType::FromCid(kOneByteStringCid);
}

CompileType StringToCharCodeInstr::ComputeType() const {
  return CompileType::FromCid(kSmiCid);
}

CompileType LoadStaticFieldInstr::ComputeType() const {
  const Field& field = this->field();
  bool is_nullable = CompileType::kCanBeNull;
  intptr_t cid = kIllegalCid;  // Abstract type is known, calculate cid lazily.
  AbstractType* abstract_type = &AbstractType::ZoneHandle(field.type());
  TraceStrongModeType(this, *abstract_type);
  ASSERT(field.is_static());
  auto& obj = Object::Handle();
  const bool is_initialized = IsFieldInitialized(&obj);
  if (field.is_final() && is_initialized) {
    if (!obj.IsNull()) {
      is_nullable = CompileType::kCannotBeNull;
      cid = obj.GetClassId();
      abstract_type = nullptr;  // Cid is known, calculate abstract type lazily.
    }
  }
  if ((field.guarded_cid() != kIllegalCid) &&
      (field.guarded_cid() != kDynamicCid)) {
    cid = field.guarded_cid();
    is_nullable = field.is_nullable();
    abstract_type = nullptr;  // Cid is known, calculate abstract type lazily.
  }
  if (field.needs_load_guard()) {
    // Should be kept in sync with Slot::Get.
    DEBUG_ASSERT(IsolateGroup::Current()->HasAttemptedReload());
    return CompileType::Dynamic();
  }
  const bool can_be_sentinel = !calls_initializer() && field.is_late() &&
                               field.is_final() && !field.has_initializer();
  return CompileType(is_nullable, can_be_sentinel, cid, abstract_type);
}

CompileType CreateArrayInstr::ComputeType() const {
  // TODO(fschneider): Add abstract type and type arguments to the compile type.
  return CompileType::FromCid(kArrayCid);
}

CompileType AllocateTypedDataInstr::ComputeType() const {
  return CompileType::FromCid(class_id());
}

CompileType AllocateObjectInstr::ComputeType() const {
  // TODO(vegorov): Incorporate type arguments into the returned type.
  return CompileType::FromCid(cls().id());
}

CompileType AllocateClosureInstr::ComputeType() const {
  const auto& func = known_function();
  if (!func.IsNull()) {
    const auto& sig = FunctionType::ZoneHandle(func.signature());
    return CompileType(CompileType::kCannotBeNull,
                       CompileType::kCannotBeSentinel, kClosureCid, &sig);
  }
  return CompileType::FromCid(kClosureCid);
}

CompileType LoadUntaggedInstr::ComputeType() const {
  return CompileType::Dynamic();
}

CompileType LoadClassIdInstr::ComputeType() const {
  return CompileType::FromCid(kSmiCid);
}

CompileType LoadFieldInstr::ComputeType() const {
  CompileType type = slot().ComputeCompileType();
  if (calls_initializer()) {
    type = type.CopyNonSentinel();
  }
  TraceStrongModeType(this, &type);
  return type;
}

CompileType LoadCodeUnitsInstr::ComputeType() const {
  switch (class_id()) {
    case kOneByteStringCid:
    case kExternalOneByteStringCid:
    case kTwoByteStringCid:
    case kExternalTwoByteStringCid:
      return can_pack_into_smi() ? CompileType::FromCid(kSmiCid)
                                 : CompileType::Int();
    default:
      UNIMPLEMENTED();
      return CompileType::Dynamic();
  }
}

CompileType BinaryUint32OpInstr::ComputeType() const {
  return CompileType::Int32();
}

CompileType ShiftUint32OpInstr::ComputeType() const {
  return CompileType::Int32();
}

CompileType SpeculativeShiftUint32OpInstr::ComputeType() const {
  return CompileType::Int32();
}

CompileType UnaryUint32OpInstr::ComputeType() const {
  return CompileType::Int32();
}

CompileType BinaryInt32OpInstr::ComputeType() const {
  // TODO(vegorov): range analysis information shall be used here.
  return CompileType::Int();
}

CompileType BinarySmiOpInstr::ComputeType() const {
  return CompileType::FromCid(kSmiCid);
}

CompileType UnarySmiOpInstr::ComputeType() const {
  return CompileType::FromCid(kSmiCid);
}

CompileType UnaryDoubleOpInstr::ComputeType() const {
  return CompileType::FromCid(kDoubleCid);
}

CompileType DoubleToSmiInstr::ComputeType() const {
  return CompileType::FromCid(kSmiCid);
}

CompileType ConstraintInstr::ComputeType() const {
  return CompileType::FromCid(kSmiCid);
}

// Note that Int64Op may produce Smi-s as result of an
// appended BoxInt64Instr node.
CompileType BinaryInt64OpInstr::ComputeType() const {
  return CompileType::Int();
}

CompileType ShiftInt64OpInstr::ComputeType() const {
  return CompileType::Int();
}

CompileType SpeculativeShiftInt64OpInstr::ComputeType() const {
  return CompileType::Int();
}

CompileType UnaryInt64OpInstr::ComputeType() const {
  return CompileType::Int();
}

CompileType BoxIntegerInstr::ComputeType() const {
  return ValueFitsSmi() ? CompileType::FromCid(kSmiCid) : CompileType::Int();
}

bool BoxIntegerInstr::RecomputeType() {
  return UpdateType(ComputeType());
}

CompileType UnboxIntegerInstr::ComputeType() const {
  return CompileType::Int();
}

CompileType DoubleToIntegerInstr::ComputeType() const {
  return CompileType::Int();
}

CompileType BinaryDoubleOpInstr::ComputeType() const {
  return CompileType::FromCid(kDoubleCid);
}

CompileType DoubleTestOpInstr::ComputeType() const {
  return CompileType::FromCid(kBoolCid);
}

static const intptr_t simd_op_result_cids[] = {
#define kInt8Cid kSmiCid
#define CASE(Arity, Mask, Name, Args, Result) k##Result##Cid,
    SIMD_OP_LIST(CASE, CASE)
#undef CASE
#undef kWordCid
};

CompileType SimdOpInstr::ComputeType() const {
  return CompileType::FromCid(simd_op_result_cids[kind()]);
}

CompileType MathUnaryInstr::ComputeType() const {
  return CompileType::FromCid(kDoubleCid);
}

CompileType MathMinMaxInstr::ComputeType() const {
  return CompileType::FromCid(result_cid_);
}

CompileType CaseInsensitiveCompareInstr::ComputeType() const {
  return CompileType::FromCid(kBoolCid);
}

CompileType UnboxInstr::ComputeType() const {
  switch (representation()) {
    case kUnboxedFloat:
    case kUnboxedDouble:
      return CompileType::FromCid(kDoubleCid);

    case kUnboxedFloat32x4:
      return CompileType::FromCid(kFloat32x4Cid);

    case kUnboxedFloat64x2:
      return CompileType::FromCid(kFloat64x2Cid);

    case kUnboxedInt32x4:
      return CompileType::FromCid(kInt32x4Cid);

    case kUnboxedInt64:
      return CompileType::Int();

    default:
      UNREACHABLE();
      return CompileType::Dynamic();
  }
}

CompileType BoxInstr::ComputeType() const {
  switch (from_representation()) {
    case kUnboxedFloat:
    case kUnboxedDouble:
      return CompileType::FromCid(kDoubleCid);

    case kUnboxedFloat32x4:
      return CompileType::FromCid(kFloat32x4Cid);

    case kUnboxedFloat64x2:
      return CompileType::FromCid(kFloat64x2Cid);

    case kUnboxedInt32x4:
      return CompileType::FromCid(kInt32x4Cid);

    default:
      UNREACHABLE();
      return CompileType::Dynamic();
  }
}

CompileType Int32ToDoubleInstr::ComputeType() const {
  return CompileType::FromCid(kDoubleCid);
}

CompileType SmiToDoubleInstr::ComputeType() const {
  return CompileType::FromCid(kDoubleCid);
}

CompileType Int64ToDoubleInstr::ComputeType() const {
  return CompileType::FromCid(kDoubleCid);
}

CompileType DoubleToDoubleInstr::ComputeType() const {
  return CompileType::FromCid(kDoubleCid);
}

CompileType FloatToDoubleInstr::ComputeType() const {
  return CompileType::FromCid(kDoubleCid);
}

CompileType DoubleToFloatInstr::ComputeType() const {
  // Type is double when converted back.
  return CompileType::FromCid(kDoubleCid);
}

CompileType InvokeMathCFunctionInstr::ComputeType() const {
  return CompileType::FromCid(kDoubleCid);
}

CompileType TruncDivModInstr::ComputeType() const {
  return CompileType::Dynamic();
}

CompileType ExtractNthOutputInstr::ComputeType() const {
  return CompileType::FromCid(definition_cid_);
}

static AbstractTypePtr ExtractElementTypeFromArrayType(
    const AbstractType& array_type) {
  if (array_type.IsTypeParameter()) {
    return ExtractElementTypeFromArrayType(
        AbstractType::Handle(TypeParameter::Cast(array_type).bound()));
  }
  if (!array_type.IsType()) {
    return Object::dynamic_type().ptr();
  }
  const intptr_t cid = array_type.type_class_id();
  if (cid == kGrowableObjectArrayCid || cid == kArrayCid ||
      cid == kImmutableArrayCid ||
      array_type.type_class() ==
          IsolateGroup::Current()->object_store()->list_class()) {
    const auto& type_args = TypeArguments::Handle(array_type.arguments());
    return type_args.TypeAtNullSafe(Array::kElementTypeTypeArgPos);
  }
  return Object::dynamic_type().ptr();
}

static AbstractTypePtr GetElementTypeFromArray(Value* array) {
  // Sometimes type of definition may contain a static type
  // which is useful to extract element type, but reaching type
  // only has a cid. So try out type of definition, if any.
  if (array->definition()->HasType()) {
    auto& elem_type = AbstractType::Handle(ExtractElementTypeFromArrayType(
        *(array->definition()->Type()->ToAbstractType())));
    if (!elem_type.IsDynamicType()) {
      return elem_type.ptr();
    }
  }
  return ExtractElementTypeFromArrayType(*(array->Type()->ToAbstractType()));
}

static CompileType ComputeArrayElementType(Value* array) {
  // 1. Try to extract element type from array value.
  auto& elem_type = AbstractType::Handle(GetElementTypeFromArray(array));
  if (!elem_type.IsDynamicType()) {
    return CompileType::FromAbstractType(elem_type, CompileType::kCanBeNull,
                                         CompileType::kCannotBeSentinel);
  }

  // 2. Array value may be loaded from GrowableObjectArray.data.
  // Unwrap and try again.
  if (auto* load_field = array->definition()->AsLoadField()) {
    if (load_field->slot().IsIdentical(Slot::GrowableObjectArray_data())) {
      array = load_field->instance();
      elem_type = GetElementTypeFromArray(array);
      if (!elem_type.IsDynamicType()) {
        return CompileType::FromAbstractType(elem_type, CompileType::kCanBeNull,
                                             CompileType::kCannotBeSentinel);
      }
    }
  }

  // 3. If array was loaded from a Dart field, use field's static type.
  // Unlike propagated type (which could be cid), static type may contain
  // type arguments which can be used to figure out element type.
  if (auto* load_field = array->definition()->AsLoadField()) {
    if (load_field->slot().IsDartField()) {
      elem_type =
          ExtractElementTypeFromArrayType(load_field->slot().static_type());
    }
  }
  return CompileType::FromAbstractType(elem_type, CompileType::kCanBeNull,
                                       CompileType::kCannotBeSentinel);
}

CompileType LoadIndexedInstr::ComputeType() const {
  switch (class_id_) {
    case kArrayCid:
    case kImmutableArrayCid:
      if (result_type_ != nullptr) {
        // The original call knew something.
        return *result_type_;
      }
      return ComputeArrayElementType(array());

    case kTypeArgumentsCid:
      return CompileType::FromAbstractType(Object::dynamic_type(),
                                           CompileType::kCannotBeNull,
                                           CompileType::kCannotBeSentinel);

    case kTypedDataFloat32ArrayCid:
    case kTypedDataFloat64ArrayCid:
      return CompileType::FromCid(kDoubleCid);

    case kTypedDataFloat32x4ArrayCid:
      return CompileType::FromCid(kFloat32x4Cid);

    case kTypedDataInt32x4ArrayCid:
      return CompileType::FromCid(kInt32x4Cid);

    case kTypedDataFloat64x2ArrayCid:
      return CompileType::FromCid(kFloat64x2Cid);

    case kTypedDataInt8ArrayCid:
    case kTypedDataUint8ArrayCid:
    case kTypedDataUint8ClampedArrayCid:
    case kExternalTypedDataUint8ArrayCid:
    case kExternalTypedDataUint8ClampedArrayCid:
    case kTypedDataInt16ArrayCid:
    case kTypedDataUint16ArrayCid:
    case kOneByteStringCid:
    case kTwoByteStringCid:
    case kExternalOneByteStringCid:
    case kExternalTwoByteStringCid:
      return CompileType::FromCid(kSmiCid);

    case kTypedDataInt32ArrayCid:
    case kTypedDataUint32ArrayCid:
      return CompileType::Int32();

    case kTypedDataInt64ArrayCid:
    case kTypedDataUint64ArrayCid:
      return CompileType::Int();

    default:
      UNIMPLEMENTED();
      return CompileType::Dynamic();
  }
}

bool LoadIndexedInstr::RecomputeType() {
  if ((class_id_ == kArrayCid) || (class_id_ == kImmutableArrayCid)) {
    // Array element type computation depends on computed
    // types of other instructions and may change over time.
    return UpdateType(ComputeType());
  }
  return false;
}

}  // namespace dart
