// Copyright (c) 2016, 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/object.h"

#include "platform/unaligned.h"
#include "vm/code_patcher.h"
#include "vm/dart_entry.h"
#include "vm/hash_table.h"
#include "vm/isolate_reload.h"
#include "vm/log.h"
#include "vm/object_store.h"
#include "vm/resolver.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"

namespace dart {

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

DECLARE_FLAG(bool, trace_reload);
DECLARE_FLAG(bool, trace_reload_verbose);
DECLARE_FLAG(bool, two_args_smi_icd);

void CallSiteResetter::ZeroEdgeCounters(const Function& function) {
  ic_data_array_ = function.ic_data_array();
  if (ic_data_array_.IsNull()) {
    return;
  }
  ASSERT(ic_data_array_.Length() > 0);
  edge_counters_ ^=
      ic_data_array_.At(Function::ICDataArrayIndices::kEdgeCounters);
  if (edge_counters_.IsNull()) {
    return;
  }
  // Fill edge counters array with zeros.
  for (intptr_t i = 0; i < edge_counters_.Length(); i++) {
    edge_counters_.SetAt(i, Object::smi_zero());
  }
}

CallSiteResetter::CallSiteResetter(Zone* zone)
    : zone_(zone),
      instrs_(Instructions::Handle(zone)),
      pool_(ObjectPool::Handle(zone)),
      object_(Object::Handle(zone)),
      name_(String::Handle(zone)),
      new_cls_(Class::Handle(zone)),
      new_lib_(Library::Handle(zone)),
      new_function_(Function::Handle(zone)),
      new_field_(Field::Handle(zone)),
      entries_(Array::Handle(zone)),
      old_target_(Function::Handle(zone)),
      new_target_(Function::Handle(zone)),
      caller_(Function::Handle(zone)),
      args_desc_array_(Array::Handle(zone)),
      ic_data_array_(Array::Handle(zone)),
      edge_counters_(Array::Handle(zone)),
      descriptors_(PcDescriptors::Handle(zone)),
      ic_data_(ICData::Handle(zone)) {}

void CallSiteResetter::ResetCaches(const Code& code) {
  // Iterate over the Code's object pool and reset all ICDatas.
  // SubtypeTestCaches are reset during the same heap traversal as type
  // testing stub deoptimization.
#ifdef TARGET_ARCH_IA32
  // IA32 does not have an object pool, but, we can iterate over all
  // embedded objects by using the variable length data section.
  if (!code.is_alive()) {
    return;
  }
  instrs_ = code.instructions();
  ASSERT(!instrs_.IsNull());
  uword base_address = instrs_.PayloadStart();
  intptr_t offsets_length = code.pointer_offsets_length();
  const int32_t* offsets = code.untag()->data();
  for (intptr_t i = 0; i < offsets_length; i++) {
    int32_t offset = offsets[i];
    ObjectPtr* object_ptr = reinterpret_cast<ObjectPtr*>(base_address + offset);
    ObjectPtr raw_object = LoadUnaligned(object_ptr);
    if (!raw_object->IsHeapObject()) {
      continue;
    }
    object_ = raw_object;
    if (object_.IsICData()) {
      Reset(ICData::Cast(object_));
    }
  }
#else
  pool_ = code.object_pool();
  ASSERT(!pool_.IsNull());
  ResetCaches(pool_);
#endif
}

static void FindICData(const Array& ic_data_array,
                       intptr_t deopt_id,
                       ICData* ic_data) {
  // ic_data_array is sorted because of how it is constructed in
  // Function::SaveICDataMap.
  intptr_t lo = Function::ICDataArrayIndices::kFirstICData;
  intptr_t hi = ic_data_array.Length() - 1;
  while (lo <= hi) {
    intptr_t mid = (hi - lo + 1) / 2 + lo;
    ASSERT(mid >= lo);
    ASSERT(mid <= hi);
    *ic_data ^= ic_data_array.At(mid);
    if (ic_data->deopt_id() == deopt_id) {
      return;
    } else if (ic_data->deopt_id() > deopt_id) {
      hi = mid - 1;
    } else {
      lo = mid + 1;
    }
  }
  FATAL("Missing deopt id %" Pd "\n", deopt_id);
}

void CallSiteResetter::ResetSwitchableCalls(const Code& code) {
  if (code.is_optimized()) {
    return;  // No switchable calls in optimized code.
  }

  object_ = code.owner();
  if (!object_.IsFunction()) {
    return;  // No switchable calls in stub code.
  }
  const Function& function = Function::Cast(object_);

  if (function.kind() == UntaggedFunction::kIrregexpFunction) {
    // Regex matchers do not support breakpoints or stepping, and they only call
    // core library functions that cannot change due to reload. As a performance
    // optimization, avoid this matching of ICData to PCs for these functions'
    // large number of instance calls.
    ASSERT(!function.is_debuggable());
    return;
  }

  ic_data_array_ = function.ic_data_array();
  if (ic_data_array_.IsNull()) {
    // The megamorphic miss stub and some recognized function doesn't populate
    // their ic_data_array. Check this only happens for functions without IC
    // calls.
#if defined(DEBUG)
    descriptors_ = code.pc_descriptors();
    PcDescriptors::Iterator iter(descriptors_, UntaggedPcDescriptors::kIcCall);
    while (iter.MoveNext()) {
      FATAL("%s has IC calls but no ic_data_array\n",
            function.ToFullyQualifiedCString());
    }
#endif
    return;
  }

  descriptors_ = code.pc_descriptors();
  PcDescriptors::Iterator iter(descriptors_, UntaggedPcDescriptors::kIcCall);
  while (iter.MoveNext()) {
    uword pc = code.PayloadStart() + iter.PcOffset();
    CodePatcher::GetInstanceCallAt(pc, code, &object_);
    // This check both avoids unnecessary patching to reduce log spam and
    // prevents patching over breakpoint stubs.
    if (!object_.IsICData()) {
      FindICData(ic_data_array_, iter.DeoptId(), &ic_data_);
      ASSERT(ic_data_.rebind_rule() == ICData::kInstance);
      ASSERT(ic_data_.NumArgsTested() == 1);
      const Code& stub =
          ic_data_.is_tracking_exactness()
              ? StubCode::OneArgCheckInlineCacheWithExactnessCheck()
              : StubCode::OneArgCheckInlineCache();
      CodePatcher::PatchInstanceCallAt(pc, code, ic_data_, stub);
      if (FLAG_trace_ic) {
        OS::PrintErr("Instance call at %" Px
                     " resetting to polymorphic dispatch, %s\n",
                     pc, ic_data_.ToCString());
      }
    }
  }
}

void CallSiteResetter::ResetCaches(const ObjectPool& pool) {
  for (intptr_t i = 0; i < pool.Length(); i++) {
    ObjectPool::EntryType entry_type = pool.TypeAt(i);
    if (entry_type != ObjectPool::EntryType::kTaggedObject) {
      continue;
    }
    object_ = pool.ObjectAt(i);
    if (object_.IsICData()) {
      Reset(ICData::Cast(object_));
    }
  }
}

void Class::CopyStaticFieldValues(ProgramReloadContext* reload_context,
                                  const Class& old_cls) const {
  const Array& old_field_list = Array::Handle(old_cls.fields());
  Field& old_field = Field::Handle();
  String& old_name = String::Handle();

  const Array& field_list = Array::Handle(fields());
  Field& field = Field::Handle();
  String& name = String::Handle();

  for (intptr_t i = 0; i < field_list.Length(); i++) {
    field = Field::RawCast(field_list.At(i));
    name = field.name();
    // Find the corresponding old field, if it exists, and migrate
    // over the field value.
    for (intptr_t j = 0; j < old_field_list.Length(); j++) {
      old_field = Field::RawCast(old_field_list.At(j));
      old_name = old_field.name();
      if (name.Equals(old_name)) {
        if (field.is_static()) {
          // We only copy values if requested and if the field is not a const
          // field. We let const fields be updated with a reload.
          if (!field.is_const()) {
            // Make new field point to the old field value so that both
            // old and new code see and update same value.
            reload_context->isolate_group()->FreeStaticField(field);
            field.set_field_id_unsafe(old_field.field_id());
          }
          reload_context->AddStaticFieldMapping(old_field, field);
        }
      }
    }
  }
}

void Class::CopyCanonicalConstants(const Class& old_cls) const {
#if defined(DEBUG)
  {
    // Class has no canonical constants allocated.
    const Array& my_constants = Array::Handle(constants());
    ASSERT(my_constants.IsNull() || my_constants.Length() == 0);
  }
#endif  // defined(DEBUG).
  // Copy old constants into new class.
  const Array& old_constants = Array::Handle(old_cls.constants());
  if (old_constants.IsNull() || old_constants.Length() == 0) {
    return;
  }
  TIR_Print("Copied %" Pd " canonical constants for class `%s`\n",
            old_constants.Length(), ToCString());
  set_constants(old_constants);
}

void Class::CopyDeclarationType(const Class& old_cls) const {
  const Type& old_declaration_type = Type::Handle(old_cls.declaration_type());
  if (old_declaration_type.IsNull()) {
    return;
  }
  set_declaration_type(old_declaration_type);
}

class EnumMapTraits {
 public:
  static bool ReportStats() { return false; }
  static const char* Name() { return "EnumMapTraits"; }

  static bool IsMatch(const Object& a, const Object& b) {
    return a.ptr() == b.ptr();
  }

  static uword Hash(const Object& obj) {
    ASSERT(obj.IsString());
    return String::Cast(obj).Hash();
  }
};

void Class::PatchFieldsAndFunctions() const {
  // Move all old functions and fields to a patch class so that they
  // still refer to their original script.
  const auto& kernel_info = KernelProgramInfo::Handle(KernelProgramInfo());
  const PatchClass& patch = PatchClass::Handle(
      PatchClass::New(*this, kernel_info, Script::Handle(script())));
  ASSERT(!patch.IsNull());
  const Library& lib = Library::Handle(library());
  patch.set_kernel_library_index(lib.kernel_library_index());

  const Array& funcs = Array::Handle(current_functions());
  Function& func = Function::Handle();
  Object& owner = Object::Handle();
  for (intptr_t i = 0; i < funcs.Length(); i++) {
    func = Function::RawCast(funcs.At(i));
    if ((func.token_pos() == TokenPosition::kMinSource) ||
        func.IsClosureFunction()) {
      // Eval functions do not need to have their script updated.
      //
      // Closure functions refer to the parent's script which we can
      // rely on being updated for us, if necessary.
      continue;
    }

    // If the source for this function is already patched, leave it alone.
    owner = func.RawOwner();
    ASSERT(!owner.IsNull());
    if (!owner.IsPatchClass()) {
      ASSERT(owner.ptr() == this->ptr());
      func.set_owner(patch);
    }
  }

  Thread* thread = Thread::Current();
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  const Array& field_list = Array::Handle(fields());
  Field& field = Field::Handle();
  for (intptr_t i = 0; i < field_list.Length(); i++) {
    field = Field::RawCast(field_list.At(i));
    owner = field.RawOwner();
    ASSERT(!owner.IsNull());
    if (!owner.IsPatchClass()) {
      ASSERT(owner.ptr() == this->ptr());
      field.set_owner(patch);
    }
    field.ForceDynamicGuardedCidAndLength();
  }
}

void Class::MigrateImplicitStaticClosures(ProgramReloadContext* irc,
                                          const Class& new_cls) const {
  const Array& funcs = Array::Handle(current_functions());
  Thread* thread = Thread::Current();
  Function& old_func = Function::Handle();
  String& selector = String::Handle();
  Function& new_func = Function::Handle();
  Closure& old_closure = Closure::Handle();
  Closure& new_closure = Closure::Handle();
  for (intptr_t i = 0; i < funcs.Length(); i++) {
    old_func ^= funcs.At(i);
    if (old_func.is_static() && old_func.HasImplicitClosureFunction()) {
      selector = old_func.name();
      new_func = Resolver::ResolveFunction(thread->zone(), new_cls, selector);
      if (!new_func.IsNull() && new_func.is_static()) {
        old_func = old_func.ImplicitClosureFunction();
        old_closure = old_func.ImplicitStaticClosure();
        new_func = new_func.ImplicitClosureFunction();
        new_closure = new_func.ImplicitStaticClosure();
        if (old_closure.IsCanonical()) {
          new_closure.SetCanonical();
        }
        irc->AddBecomeMapping(old_closure, new_closure);
      }
    }
  }
}

class EnumClassConflict : public ClassReasonForCancelling {
 public:
  EnumClassConflict(Zone* zone, const Class& from, const Class& to)
      : ClassReasonForCancelling(zone, from, to) {}

  StringPtr ToString() {
    return String::NewFormatted(
        from_.is_enum_class()
            ? "Enum class cannot be redefined to be a non-enum class: %s"
            : "Class cannot be redefined to be a enum class: %s",
        from_.ToCString());
  }
};

class EnsureFinalizedError : public ClassReasonForCancelling {
 public:
  EnsureFinalizedError(Zone* zone,
                       const Class& from,
                       const Class& to,
                       const Error& error)
      : ClassReasonForCancelling(zone, from, to), error_(error) {}

 private:
  const Error& error_;

  ErrorPtr ToError() { return error_.ptr(); }

  StringPtr ToString() { return String::New(error_.ToErrorCString()); }
};

class DeeplyImmutableChange : public ClassReasonForCancelling {
 public:
  DeeplyImmutableChange(Zone* zone, const Class& from, const Class& to)
      : ClassReasonForCancelling(zone, from, to) {}

 private:
  StringPtr ToString() {
    return String::NewFormatted(
        "Classes cannot change their @pragma('vm:deeply-immutable'): %s",
        from_.ToCString());
  }
};

class ConstToNonConstClass : public ClassReasonForCancelling {
 public:
  ConstToNonConstClass(Zone* zone, const Class& from, const Class& to)
      : ClassReasonForCancelling(zone, from, to) {}

 private:
  StringPtr ToString() {
    return String::NewFormatted("Const class cannot become non-const: %s",
                                from_.ToCString());
  }
};

class ConstClassFieldRemoved : public ClassReasonForCancelling {
 public:
  ConstClassFieldRemoved(Zone* zone, const Class& from, const Class& to)
      : ClassReasonForCancelling(zone, from, to) {}

 private:
  StringPtr ToString() {
    return String::NewFormatted("Const class cannot remove fields: %s",
                                from_.ToCString());
  }
};

class NativeFieldsConflict : public ClassReasonForCancelling {
 public:
  NativeFieldsConflict(Zone* zone, const Class& from, const Class& to)
      : ClassReasonForCancelling(zone, from, to) {}

 private:
  StringPtr ToString() {
    return String::NewFormatted("Number of native fields changed in %s",
                                from_.ToCString());
  }
};

class TypeParametersChanged : public ClassReasonForCancelling {
 public:
  TypeParametersChanged(Zone* zone, const Class& from, const Class& to)
      : ClassReasonForCancelling(zone, from, to) {}

  StringPtr ToString() {
    return String::NewFormatted(
        "Limitation: type parameters have changed for %s", from_.ToCString());
  }

  void AppendTo(JSONArray* array) {
    JSONObject jsobj(array);
    jsobj.AddProperty("type", "ReasonForCancellingReload");
    jsobj.AddProperty("kind", "TypeParametersChanged");
    jsobj.AddProperty("class", to_);
    jsobj.AddProperty("message",
                      "Limitation: changing type parameters "
                      "does not work with hot reload.");
  }
};

class PreFinalizedConflict : public ClassReasonForCancelling {
 public:
  PreFinalizedConflict(Zone* zone, const Class& from, const Class& to)
      : ClassReasonForCancelling(zone, from, to) {}

 private:
  StringPtr ToString() {
    return String::NewFormatted(
        "Original class ('%s') is prefinalized and replacement class "
        "('%s') is not ",
        from_.ToCString(), to_.ToCString());
  }
};

class InstanceSizeConflict : public ClassReasonForCancelling {
 public:
  InstanceSizeConflict(Zone* zone, const Class& from, const Class& to)
      : ClassReasonForCancelling(zone, from, to) {}

 private:
  StringPtr ToString() {
    return String::NewFormatted("Instance size mismatch between '%s' (%" Pd
                                ") and replacement "
                                "'%s' ( %" Pd ")",
                                from_.ToCString(), from_.host_instance_size(),
                                to_.ToCString(), to_.host_instance_size());
  }
};

// This is executed before iterating over the instances.
void Class::CheckReload(const Class& replacement,
                        ProgramReloadContext* context) const {
  ASSERT(ProgramReloadContext::IsSameClass(*this, replacement));

  if (!is_declaration_loaded()) {
    // The old class hasn't been used in any meaningful way, so the VM is okay
    // with any change.
    return;
  }

  // Ensure is_enum_class etc have been set.
  replacement.EnsureDeclarationLoaded();

  // Class cannot change enum property.
  if (is_enum_class() != replacement.is_enum_class()) {
    context->group_reload_context()->AddReasonForCancelling(
        new (context->zone())
            EnumClassConflict(context->zone(), *this, replacement));
    return;
  }

  if (is_finalized()) {
    // Make sure the declaration types parameter count matches for the two
    // classes.
    // ex. class A<int,B> {} cannot be replace with class A<B> {}.
    auto group_context = context->group_reload_context();
    if (NumTypeParameters() != replacement.NumTypeParameters()) {
      group_context->AddReasonForCancelling(
          new (context->zone())
              TypeParametersChanged(context->zone(), *this, replacement));
      return;
    }
  }

  if (is_finalized() || is_allocate_finalized()) {
    auto thread = Thread::Current();

    // Ensure the replacement class is also finalized.
    const Error& error = Error::Handle(
        is_allocate_finalized() ? replacement.EnsureIsAllocateFinalized(thread)
                                : replacement.EnsureIsFinalized(thread));
    if (!error.IsNull()) {
      context->group_reload_context()->AddReasonForCancelling(
          new (context->zone())
              EnsureFinalizedError(context->zone(), *this, replacement, error));
      return;  // No reason to check other properties.
    }
    ASSERT(replacement.is_finalized());
    TIR_Print("Finalized replacement class for %s\n", ToCString());
  }

  if (is_deeply_immutable() != replacement.is_deeply_immutable()) {
    context->group_reload_context()->AddReasonForCancelling(
        new (context->zone())
            DeeplyImmutableChange(context->zone(), *this, replacement));
    return;  // No reason to check other properties.
  }

  if (is_finalized() && is_const() && (constants() != Array::null()) &&
      (Array::LengthOf(constants()) > 0)) {
    // Consts can't become non-consts.
    if (!replacement.is_const()) {
      context->group_reload_context()->AddReasonForCancelling(
          new (context->zone())
              ConstToNonConstClass(context->zone(), *this, replacement));
      return;
    }

    // Consts can't lose fields.
    bool field_removed = false;
    const Array& old_fields = Array::Handle(
        OffsetToFieldMap(IsolateGroup::Current()->heap_walk_class_table()));
    const Array& new_fields = Array::Handle(replacement.OffsetToFieldMap());
    if (new_fields.Length() < old_fields.Length()) {
      field_removed = true;
    } else {
      Field& old_field = Field::Handle();
      Field& new_field = Field::Handle();
      String& old_name = String::Handle();
      String& new_name = String::Handle();
      for (intptr_t i = 0, n = old_fields.Length(); i < n; i++) {
        old_field ^= old_fields.At(i);
        new_field ^= new_fields.At(i);
        if (old_field.IsNull()) {
          continue;
        }
        if (new_field.IsNull()) {
          field_removed = true;
          break;
        }
        old_name = old_field.name();
        new_name = new_field.name();
        if (!old_name.Equals(new_name)) {
          field_removed = true;
          break;
        }
      }
    }
    if (field_removed) {
      context->group_reload_context()->AddReasonForCancelling(
          new (context->zone())
              ConstClassFieldRemoved(context->zone(), *this, replacement));
      return;
    }
  }

  // Native field count cannot change.
  if (num_native_fields() != replacement.num_native_fields()) {
    context->group_reload_context()->AddReasonForCancelling(
        new (context->zone())
            NativeFieldsConflict(context->zone(), *this, replacement));
    return;
  }

  // Just checking.
  ASSERT(is_enum_class() == replacement.is_enum_class());
  ASSERT(num_native_fields() == replacement.num_native_fields());

  if (is_finalized()) {
    if (!CanReloadFinalized(replacement, context)) return;
  }
  if (is_prefinalized()) {
    if (!CanReloadPreFinalized(replacement, context)) return;
  }
  TIR_Print("Class `%s` can be reloaded (%" Pd " and %" Pd ")\n", ToCString(),
            id(), replacement.id());
}

void Class::MarkFieldBoxedDuringReload(ClassTable* class_table,
                                       const Field& field) const {
  if (!field.is_unboxed()) {
    return;
  }

  field.set_is_unboxed_unsafe(false);

  // Make sure to update the bitmap used for scanning.
  auto unboxed_fields_map = class_table->GetUnboxedFieldsMapAt(id());
  const auto start_index = field.HostOffset() >> kCompressedWordSizeLog2;
  const auto end_index =
      start_index + (Class::UnboxedFieldSizeInBytesByCid(field.guarded_cid()) >>
                     kCompressedWordSizeLog2);
  ASSERT(unboxed_fields_map.Get(start_index));
  for (intptr_t i = start_index; i < end_index; i++) {
    unboxed_fields_map.Clear(i);
  }
  class_table->SetUnboxedFieldsMapAt(id(), unboxed_fields_map);
}

bool Class::RequiresInstanceMorphing(ClassTable* class_table,
                                     const Class& replacement) const {
  if (!is_allocate_finalized()) {
    // No instances of this class exists on the heap - nothing to morph.
    return false;
  }

  // Get the field maps for both classes. These field maps walk the class
  // hierarchy.
  auto isolate_group = IsolateGroup::Current();

  // heap_walk_class_table is the original class table before it was
  // updated by reloading sources.
  const Array& fields =
      Array::Handle(OffsetToFieldMap(isolate_group->heap_walk_class_table()));
  const Array& replacement_fields =
      Array::Handle(replacement.OffsetToFieldMap());

  // Check that the size of the instance is the same.
  if (fields.Length() != replacement_fields.Length()) return true;

  // Check that we have the same next field offset. This check is not
  // redundant with the one above because the instance OffsetToFieldMap
  // array length is based on the instance size (which may be aligned up).
  if (host_next_field_offset() != replacement.host_next_field_offset()) {
    return true;
  }

  // Verify that field names / offsets match across the entire hierarchy.
  Field& field = Field::Handle();
  String& field_name = String::Handle();
  Field& replacement_field = Field::Handle();
  String& replacement_field_name = String::Handle();

  for (intptr_t i = 0; i < fields.Length(); i++) {
    if (fields.At(i) == Field::null()) {
      ASSERT(replacement_fields.At(i) == Field::null());
      continue;
    }
    field = Field::RawCast(fields.At(i));
    replacement_field = Field::RawCast(replacement_fields.At(i));
    field_name = field.name();
    replacement_field_name = replacement_field.name();
    if (!field_name.Equals(replacement_field_name)) return true;
    if (field.is_unboxed() && !replacement_field.is_unboxed()) {
      return true;
    }
    if (field.is_unboxed() && (field.type() != replacement_field.type())) {
      return true;
    }
    if (!field.is_unboxed() && replacement_field.is_unboxed()) {
      // No actual morphing is required in this case but we need to mark
      // the field boxed.
      replacement.MarkFieldBoxedDuringReload(class_table, replacement_field);
    }
    if (field.needs_load_guard()) {
      ASSERT(!field.is_unboxed());
      ASSERT(!replacement_field.is_unboxed());
      replacement_field.set_needs_load_guard(true);
    }
  }
  return false;
}

bool Class::CanReloadFinalized(const Class& replacement,
                               ProgramReloadContext* context) const {
  // Make sure the declaration types argument count matches for the two classes.
  // ex. class A<int,B> {} cannot be replace with class A<B> {}.
  auto group_context = context->group_reload_context();
  auto class_table = group_context->isolate_group()->class_table();
  if (NumTypeArguments() != replacement.NumTypeArguments()) {
    group_context->AddReasonForCancelling(
        new (context->zone())
            TypeParametersChanged(context->zone(), *this, replacement));
    return false;
  }
  if (RequiresInstanceMorphing(class_table, replacement)) {
    ASSERT(id() == replacement.id());
    const classid_t cid = id();
    // We unconditionally create an instance morpher. As a side effect of
    // building the morpher, we will mark all new fields as guarded on load.
    auto instance_morpher = InstanceMorpher::CreateFromClassDescriptors(
        context->zone(), class_table, *this, replacement);
    group_context->EnsureHasInstanceMorpherFor(cid, instance_morpher);
  }
  return true;
}

bool Class::CanReloadPreFinalized(const Class& replacement,
                                  ProgramReloadContext* context) const {
  // The replacement class must also prefinalized.
  if (!replacement.is_prefinalized()) {
    context->group_reload_context()->AddReasonForCancelling(
        new (context->zone())
            PreFinalizedConflict(context->zone(), *this, replacement));
    return false;
  }
  // Check the instance sizes are equal.
  if (host_instance_size() != replacement.host_instance_size()) {
    context->group_reload_context()->AddReasonForCancelling(
        new (context->zone())
            InstanceSizeConflict(context->zone(), *this, replacement));
    return false;
  }
  return true;
}

void Library::CheckReload(const Library& replacement,
                          ProgramReloadContext* context) const {
  // Carry over the loaded bit of any deferred prefixes.
  Object& object = Object::Handle();
  LibraryPrefix& prefix = LibraryPrefix::Handle();
  LibraryPrefix& original_prefix = LibraryPrefix::Handle();
  String& name = String::Handle();
  String& original_name = String::Handle();
  DictionaryIterator it(replacement);
  while (it.HasNext()) {
    object = it.GetNext();
    if (!object.IsLibraryPrefix()) continue;
    prefix ^= object.ptr();
    if (!prefix.is_deferred_load()) continue;

    name = prefix.name();
    DictionaryIterator original_it(*this);
    while (original_it.HasNext()) {
      object = original_it.GetNext();
      if (!object.IsLibraryPrefix()) continue;
      original_prefix ^= object.ptr();
      if (!original_prefix.is_deferred_load()) continue;
      original_name = original_prefix.name();
      if (!name.Equals(original_name)) continue;

      // The replacement of the old prefix with the new prefix
      // in Isolate::loaded_prefixes_set_ implicitly carried
      // the loaded state over to the new prefix.
      context->AddBecomeMapping(original_prefix, prefix);
    }
  }
}

void CallSiteResetter::Reset(const ICData& ic) {
  ICData::RebindRule rule = ic.rebind_rule();
  if (rule == ICData::kInstance) {
    const intptr_t num_args = ic.NumArgsTested();
    const intptr_t len = ic.Length();
    // We need at least one non-sentinel entry to require a check
    // for the smi fast path case.
    if (num_args == 2 && len >= 2) {
      if (ic.IsImmutable()) {
        return;
      }
      name_ = ic.target_name();
      const Class& smi_class = Class::Handle(zone_, Smi::Class());
      const Function& smi_op_target = Function::Handle(
          zone_, Resolver::ResolveDynamicAnyArgs(zone_, smi_class, name_,
                                                 /*allow_add=*/true));
      GrowableArray<intptr_t> class_ids(2);
      Function& target = Function::Handle(zone_);
      ic.GetCheckAt(0, &class_ids, &target);
      if ((target.ptr() == smi_op_target.ptr()) && (class_ids[0] == kSmiCid) &&
          (class_ids[1] == kSmiCid)) {
        // The smi fast path case, preserve the initial entry but reset the
        // count.
        ic.ClearCountAt(0, *this);
        ic.TruncateTo(/*num_checks=*/1, *this);
        return;
      }
      // Fall back to the normal behavior with cached empty ICData arrays.
    }
    ic.Clear(*this);
    ic.set_is_megamorphic(false);
    return;
  } else if (rule == ICData::kNoRebind || rule == ICData::kNSMDispatch) {
    // TODO(30877) we should account for addition/removal of NSM.
    // Don't rebind dispatchers.
    return;
  } else if (rule == ICData::kStatic || rule == ICData::kSuper) {
    old_target_ = ic.GetTargetAt(0);
    if (old_target_.IsNull()) {
      FATAL("old_target is nullptr.\n");
    }
    name_ = old_target_.name();

    if (rule == ICData::kStatic) {
      ASSERT(old_target_.is_static() ||
             old_target_.kind() == UntaggedFunction::kConstructor);
      // This can be incorrect if the call site was an unqualified invocation.
      new_cls_ = old_target_.Owner();
      new_target_ = Resolver::ResolveFunction(zone_, new_cls_, name_);
      if (new_target_.kind() != old_target_.kind()) {
        new_target_ = Function::null();
      }
    } else {
      // Super call.
      caller_ = ic.Owner();
      ASSERT(!caller_.is_static());
      new_cls_ = caller_.Owner();
      new_cls_ = new_cls_.SuperClass();
      new_target_ = Resolver::ResolveDynamicAnyArgs(zone_, new_cls_, name_,
                                                    /*allow_add=*/true);
    }
    args_desc_array_ = ic.arguments_descriptor();
    ArgumentsDescriptor args_desc(args_desc_array_);
    if (new_target_.IsNull() ||
        !new_target_.AreValidArguments(args_desc, nullptr)) {
      // TODO(rmacnak): Patch to a NSME stub.
      VTIR_Print("Cannot rebind static call to %s from %s\n",
                 old_target_.ToCString(),
                 Object::Handle(zone_, ic.Owner()).ToCString());
      return;
    }
    ic.ClearAndSetStaticTarget(new_target_, *this);
  } else {
    FATAL("Unexpected rebind rule.");
  }
}

#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

}  // namespace dart
