/* Copyright (C) 2016 The Android Open Source Project
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file implements interfaces from the file jvmti.h. This implementation
 * is licensed under the same terms as the file jvmti.h.  The
 * copyright and license information for the file jvmti.h follows.
 *
 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "ti_redefine.h"

#include <algorithm>
#include <atomic>
#include <iterator>
#include <limits>
#include <sstream>
#include <string_view>
#include <unordered_map>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>

#include "alloc_manager.h"
#include "android-base/macros.h"
#include "android-base/thread_annotations.h"
#include "art_field-inl.h"
#include "art_field.h"
#include "art_jvmti.h"
#include "art_method-inl.h"
#include "art_method.h"
#include "base/array_ref.h"
#include "base/casts.h"
#include "base/enums.h"
#include "base/globals.h"
#include "base/iteration_range.h"
#include "base/length_prefixed_array.h"
#include "base/locks.h"
#include "base/stl_util.h"
#include "base/utils.h"
#include "class_linker-inl.h"
#include "class_linker.h"
#include "class_root-inl.h"
#include "class_status.h"
#include "debugger.h"
#include "dex/art_dex_file_loader.h"
#include "dex/class_accessor-inl.h"
#include "dex/class_accessor.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
#include "dex/dex_file_types.h"
#include "dex/primitive.h"
#include "dex/signature-inl.h"
#include "dex/signature.h"
#include "events-inl.h"
#include "events.h"
#include "gc/allocation_listener.h"
#include "gc/heap.h"
#include "gc/heap-inl.h"
#include "gc/heap-visit-objects-inl.h"
#include "handle.h"
#include "handle_scope.h"
#include "instrumentation.h"
#include "intern_table.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
#include "jni/jni_env_ext-inl.h"
#include "jni/jni_id_manager.h"
#include "jvmti.h"
#include "jvmti_allocator.h"
#include "linear_alloc-inl.h"
#include "mirror/array-alloc-inl.h"
#include "mirror/array.h"
#include "mirror/class-alloc-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class-refvisitor-inl.h"
#include "mirror/class.h"
#include "mirror/class_ext-inl.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/dex_cache.h"
#include "mirror/executable-inl.h"
#include "mirror/field-inl.h"
#include "mirror/field.h"
#include "mirror/method.h"
#include "mirror/method_handle_impl-inl.h"
#include "mirror/object.h"
#include "mirror/object_array-alloc-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object_array.h"
#include "mirror/string.h"
#include "mirror/var_handle.h"
#include "nativehelper/scoped_local_ref.h"
#include "non_debuggable_classes.h"
#include "obj_ptr.h"
#include "object_lock.h"
#include "reflective_value_visitor.h"
#include "runtime.h"
#include "runtime_globals.h"
#include "scoped_thread_state_change.h"
#include "stack.h"
#include "thread.h"
#include "thread_list.h"
#include "ti_breakpoint.h"
#include "ti_class_definition.h"
#include "ti_class_loader.h"
#include "ti_heap.h"
#include "ti_logging.h"
#include "ti_thread.h"
#include "transform.h"
#include "verifier/class_verifier.h"
#include "verifier/verifier_enums.h"
#include "well_known_classes-inl.h"
#include "write_barrier.h"

namespace openjdkjvmti {

// Debug check to force us to directly check we saw all methods and fields exactly once directly.
// Normally we don't need to do this since if any are missing the count will be different
constexpr bool kCheckAllMethodsSeenOnce = art::kIsDebugBuild;

using android::base::StringPrintf;

// A helper that fills in a classes obsolete_methods_ and obsolete_dex_caches_ classExt fields as
// they are created. This ensures that we can always call any method of an obsolete ArtMethod object
// almost as soon as they are created since the GetObsoleteDexCache method will succeed.
class ObsoleteMap {
 public:
  art::ArtMethod* FindObsoleteVersion(art::ArtMethod* original) const
      REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
    auto method_pair = id_map_.find(original);
    if (method_pair != id_map_.end()) {
      art::ArtMethod* res = obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
          method_pair->second, art::kRuntimePointerSize);
      DCHECK(res != nullptr);
      return res;
    } else {
      return nullptr;
    }
  }

  void RecordObsolete(art::ArtMethod* original, art::ArtMethod* obsolete)
      REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
    DCHECK(original != nullptr);
    DCHECK(obsolete != nullptr);
    int32_t slot = next_free_slot_++;
    DCHECK_LT(slot, obsolete_methods_->GetLength());
    DCHECK(nullptr ==
           obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(slot, art::kRuntimePointerSize));
    DCHECK(nullptr == obsolete_dex_caches_->Get(slot));
    obsolete_methods_->SetElementPtrSize(slot, obsolete, art::kRuntimePointerSize);
    obsolete_dex_caches_->Set(slot, original_dex_cache_);
    id_map_.insert({original, slot});
  }

  ObsoleteMap(art::ObjPtr<art::mirror::PointerArray> obsolete_methods,
              art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches,
              art::ObjPtr<art::mirror::DexCache> original_dex_cache)
      : next_free_slot_(0),
        obsolete_methods_(obsolete_methods),
        obsolete_dex_caches_(obsolete_dex_caches),
        original_dex_cache_(original_dex_cache) {
    // Figure out where the first unused slot in the obsolete_methods_ array is.
    while (obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
        next_free_slot_, art::kRuntimePointerSize) != nullptr) {
      DCHECK(obsolete_dex_caches_->Get(next_free_slot_) != nullptr);
      next_free_slot_++;
    }
    // Check that the same slot in obsolete_dex_caches_ is free.
    DCHECK(obsolete_dex_caches_->Get(next_free_slot_) == nullptr);
  }

  struct ObsoleteMethodPair {
    art::ArtMethod* old_method;
    art::ArtMethod* obsolete_method;
  };

  class ObsoleteMapIter {
   public:
    using iterator_category = std::forward_iterator_tag;
    using value_type = ObsoleteMethodPair;
    using difference_type = ptrdiff_t;
    using pointer = void;    // Unsupported.
    using reference = void;  // Unsupported.

    ObsoleteMethodPair operator*() const
        REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
      art::ArtMethod* obsolete = map_->obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
          iter_->second, art::kRuntimePointerSize);
      DCHECK(obsolete != nullptr);
      return { iter_->first, obsolete };
    }

    bool operator==(ObsoleteMapIter other) const {
      return map_ == other.map_ && iter_ == other.iter_;
    }

    bool operator!=(ObsoleteMapIter other) const {
      return !(*this == other);
    }

    ObsoleteMapIter operator++(int) {
      ObsoleteMapIter retval = *this;
      ++(*this);
      return retval;
    }

    ObsoleteMapIter operator++() {
      ++iter_;
      return *this;
    }

   private:
    ObsoleteMapIter(const ObsoleteMap* map,
                    std::unordered_map<art::ArtMethod*, int32_t>::const_iterator iter)
        : map_(map), iter_(iter) {}

    const ObsoleteMap* map_;
    std::unordered_map<art::ArtMethod*, int32_t>::const_iterator iter_;

    friend class ObsoleteMap;
  };

  ObsoleteMapIter end() const {
    return ObsoleteMapIter(this, id_map_.cend());
  }

  ObsoleteMapIter begin() const {
    return ObsoleteMapIter(this, id_map_.cbegin());
  }

 private:
  int32_t next_free_slot_;
  std::unordered_map<art::ArtMethod*, int32_t> id_map_;
  // Pointers to the fields in mirror::ClassExt. These can be held as ObjPtr since this is only used
  // when we have an exclusive mutator_lock_ (i.e. all threads are suspended).
  art::ObjPtr<art::mirror::PointerArray> obsolete_methods_;
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches_;
  art::ObjPtr<art::mirror::DexCache> original_dex_cache_;
};

// This visitor walks thread stacks and allocates and sets up the obsolete methods. It also does
// some basic soundness checks that the obsolete method is valid.
class ObsoleteMethodStackVisitor : public art::StackVisitor {
 protected:
  ObsoleteMethodStackVisitor(
      art::Thread* thread,
      art::LinearAlloc* allocator,
      const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
      ObsoleteMap* obsolete_maps)
        : StackVisitor(thread,
                       /*context=*/nullptr,
                       StackVisitor::StackWalkKind::kIncludeInlinedFrames),
          allocator_(allocator),
          obsoleted_methods_(obsoleted_methods),
          obsolete_maps_(obsolete_maps) { }

  ~ObsoleteMethodStackVisitor() override {}

 public:
  // Returns true if we successfully installed obsolete methods on this thread, filling
  // obsolete_maps_ with the translations if needed. Returns false and fills error_msg if we fail.
  // The stack is cleaned up when we fail.
  static void UpdateObsoleteFrames(
      art::Thread* thread,
      art::LinearAlloc* allocator,
      const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
      ObsoleteMap* obsolete_maps) REQUIRES(art::Locks::mutator_lock_) {
    ObsoleteMethodStackVisitor visitor(thread,
                                       allocator,
                                       obsoleted_methods,
                                       obsolete_maps);
    visitor.WalkStack();
  }

  bool VisitFrame() override REQUIRES(art::Locks::mutator_lock_) {
    art::ScopedAssertNoThreadSuspension snts("Fixing up the stack for obsolete methods.");
    art::ArtMethod* old_method = GetMethod();
    if (obsoleted_methods_.find(old_method) != obsoleted_methods_.end()) {
      // We cannot ensure that the right dex file is used in inlined frames so we don't support
      // redefining them.
      DCHECK(!IsInInlinedFrame()) << "Inlined frames are not supported when using redefinition: "
                                  << old_method->PrettyMethod() << " is inlined into "
                                  << GetOuterMethod()->PrettyMethod();
      art::ArtMethod* new_obsolete_method = obsolete_maps_->FindObsoleteVersion(old_method);
      if (new_obsolete_method == nullptr) {
        // Create a new Obsolete Method and put it in the list.
        art::Runtime* runtime = art::Runtime::Current();
        art::ClassLinker* cl = runtime->GetClassLinker();
        auto ptr_size = cl->GetImagePointerSize();
        const size_t method_size = art::ArtMethod::Size(ptr_size);
        auto* method_storage = allocator_->Alloc(art::Thread::Current(),
                                                 method_size,
                                                 art::LinearAllocKind::kArtMethod);
        CHECK(method_storage != nullptr) << "Unable to allocate storage for obsolete version of '"
                                         << old_method->PrettyMethod() << "'";
        new_obsolete_method = new (method_storage) art::ArtMethod();
        new_obsolete_method->CopyFrom(old_method, ptr_size);
        DCHECK_EQ(new_obsolete_method->GetDeclaringClass(), old_method->GetDeclaringClass());
        new_obsolete_method->SetIsObsolete();
        new_obsolete_method->SetDontCompile();
        cl->SetEntryPointsForObsoleteMethod(new_obsolete_method);
        obsolete_maps_->RecordObsolete(old_method, new_obsolete_method);
      }
      DCHECK(new_obsolete_method != nullptr);
      SetMethod(new_obsolete_method);
    }
    return true;
  }

 private:
  // The linear allocator we should use to make new methods.
  art::LinearAlloc* allocator_;
  // The set of all methods which could be obsoleted.
  const std::unordered_set<art::ArtMethod*>& obsoleted_methods_;
  // A map from the original to the newly allocated obsolete method for frames on this thread. The
  // values in this map are added to the obsolete_methods_ (and obsolete_dex_caches_) fields of
  // the redefined classes ClassExt as it is filled.
  ObsoleteMap* obsolete_maps_;
};

template <RedefinitionType kType>
jvmtiError
Redefiner::IsModifiableClassGeneric(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
  if (env == nullptr) {
    return ERR(INVALID_ENVIRONMENT);
  }
  art::Thread* self = art::Thread::Current();
  art::ScopedObjectAccess soa(self);
  art::StackHandleScope<1> hs(self);
  art::ObjPtr<art::mirror::Object> obj(self->DecodeJObject(klass));
  if (obj.IsNull() || !obj->IsClass()) {
    return ERR(INVALID_CLASS);
  }
  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(obj->AsClass()));
  std::string err_unused;
  *is_redefinable =
      Redefiner::GetClassRedefinitionError<kType>(h_klass, &err_unused) != ERR(UNMODIFIABLE_CLASS)
          ? JNI_TRUE
          : JNI_FALSE;
  return OK;
}

jvmtiError
Redefiner::IsStructurallyModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
  return Redefiner::IsModifiableClassGeneric<RedefinitionType::kStructural>(
      env, klass, is_redefinable);
}

jvmtiError Redefiner::IsModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
  return Redefiner::IsModifiableClassGeneric<RedefinitionType::kNormal>(env, klass, is_redefinable);
}

template <RedefinitionType kType>
jvmtiError Redefiner::GetClassRedefinitionError(jclass klass, /*out*/ std::string* error_msg) {
  art::Thread* self = art::Thread::Current();
  art::ScopedObjectAccess soa(self);
  art::StackHandleScope<1> hs(self);
  art::ObjPtr<art::mirror::Object> obj(self->DecodeJObject(klass));
  if (obj.IsNull() || !obj->IsClass()) {
    return ERR(INVALID_CLASS);
  }
  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(obj->AsClass()));
  return Redefiner::GetClassRedefinitionError<kType>(h_klass, error_msg);
}

template <RedefinitionType kType>
jvmtiError Redefiner::GetClassRedefinitionError(art::Handle<art::mirror::Class> klass,
                                                /*out*/ std::string* error_msg) {
  art::Thread* self = art::Thread::Current();
  if (!klass->IsResolved()) {
    // It's only a problem to try to retransform/redefine a unprepared class if it's happening on
    // the same thread as the class-linking process. If it's on another thread we will be able to
    // wait for the preparation to finish and continue from there.
    if (klass->GetLockOwnerThreadId() == self->GetThreadId()) {
      *error_msg = "Modification of class " + klass->PrettyClass() +
          " from within the classes ClassLoad callback is not supported to prevent deadlocks." +
          " Please use ClassFileLoadHook directly instead.";
      return ERR(INTERNAL);
    } else {
      LOG(WARNING) << klass->PrettyClass() << " is not yet resolved. Attempting to transform "
                   << "it could cause arbitrary length waits as the class is being resolved.";
    }
  }
  if (klass->IsPrimitive()) {
    *error_msg = "Modification of primitive classes is not supported";
    return ERR(UNMODIFIABLE_CLASS);
  } else if (klass->IsInterface()) {
    *error_msg = "Modification of Interface classes is currently not supported";
    return ERR(UNMODIFIABLE_CLASS);
  } else if (klass->IsStringClass()) {
    *error_msg = "Modification of String class is not supported";
    return ERR(UNMODIFIABLE_CLASS);
  } else if (klass->IsArrayClass()) {
    *error_msg = "Modification of Array classes is not supported";
    return ERR(UNMODIFIABLE_CLASS);
  } else if (klass->IsProxyClass()) {
    *error_msg = "Modification of proxy classes is not supported";
    return ERR(UNMODIFIABLE_CLASS);
  }

  for (jclass c : art::NonDebuggableClasses::GetNonDebuggableClasses()) {
    if (klass.Get() == self->DecodeJObject(c)->AsClass()) {
      *error_msg = "Class might have stack frames that cannot be made obsolete";
      return ERR(UNMODIFIABLE_CLASS);
    }
  }

  if (kType == RedefinitionType::kStructural) {
    // Class initialization interacts really badly with structural redefinition since we need to
    // make the old class obsolete. We currently just blanket don't allow it.
    // TODO It might be nice to allow this at some point.
    if (klass->IsInitializing() &&
       !klass->IsInitialized() &&
        klass->GetClinitThreadId() == self->GetTid()) {
      // We are in the class-init running on this thread.
      *error_msg = "Modification of class " + klass->PrettyClass() + " during class" +
                   " initialization is not allowed.";
      return ERR(INTERNAL);
    }
    if (!art::Runtime::Current()->GetClassLinker()->EnsureInitialized(
            self, klass, /*can_init_fields=*/true, /*can_init_parents=*/true)) {
      self->AssertPendingException();
      *error_msg = "Class " + klass->PrettyClass() + " failed initialization. Structural" +
                   " redefinition of erroneous classes is not allowed. Failure was: " +
                   self->GetException()->Dump();
      self->ClearException();
      return ERR(INVALID_CLASS);
    }
    if (klass->IsMirrored()) {
      std::string pc(klass->PrettyClass());
      *error_msg = StringPrintf("Class %s is a mirror class and cannot be structurally redefined.",
                                pc.c_str());
      return ERR(UNMODIFIABLE_CLASS);
    }
    // Check Thread specifically since it's not a root but too many things reach into it with Unsafe
    // too allow structural redefinition.
    if (klass->IsAssignableFrom(art::WellKnownClasses::java_lang_Thread.Get())) {
      *error_msg =
          "java.lang.Thread has fields accessed using sun.misc.unsafe directly. It is not "
          "safe to structurally redefine it.";
      return ERR(UNMODIFIABLE_CLASS);
    }
    auto has_pointer_marker =
        [](art::ObjPtr<art::mirror::Class> k) REQUIRES_SHARED(art::Locks::mutator_lock_) {
          // Check for fields/methods which were returned before moving to index jni id type.
          // TODO We might want to rework how this is done. Once full redefinition is implemented we
          // will need to check any subtypes too.
          art::ObjPtr<art::mirror::ClassExt> ext(k->GetExtData());
          if (!ext.IsNull()) {
            if (ext->HasInstanceFieldPointerIdMarker() || ext->HasMethodPointerIdMarker() ||
                ext->HasStaticFieldPointerIdMarker()) {
              return true;
            }
          }
          return false;
        };
    if (has_pointer_marker(klass.Get())) {
      *error_msg =
          StringPrintf("%s has active pointer jni-ids and cannot be redefined structurally",
                       klass->PrettyClass().c_str());
      return ERR(UNMODIFIABLE_CLASS);
    }
    jvmtiError res = OK;
    art::ClassFuncVisitor cfv(
      [&](art::ObjPtr<art::mirror::Class> k) REQUIRES_SHARED(art::Locks::mutator_lock_) {
        // if there is any class 'K' that is a subtype (i.e. extends) klass and has pointer-jni-ids
        // we cannot structurally redefine the class 'k' since we would structurally redefine the
        // subtype.
        if (k->IsLoaded() && klass->IsAssignableFrom(k) && has_pointer_marker(k)) {
          *error_msg = StringPrintf(
              "%s has active pointer jni-ids from subtype %s and cannot be redefined structurally",
              klass->PrettyClass().c_str(),
              k->PrettyClass().c_str());
          res = ERR(UNMODIFIABLE_CLASS);
          return false;
        }
        return true;
      });
    art::Runtime::Current()->GetClassLinker()->VisitClasses(&cfv);
    return res;
  }
  return OK;
}

template jvmtiError Redefiner::GetClassRedefinitionError<RedefinitionType::kNormal>(
    art::Handle<art::mirror::Class> klass, /*out*/ std::string* error_msg);
template jvmtiError Redefiner::GetClassRedefinitionError<RedefinitionType::kStructural>(
    art::Handle<art::mirror::Class> klass, /*out*/ std::string* error_msg);

// Moves dex data to an anonymous, read-only mmap'd region.
art::MemMap Redefiner::MoveDataToMemMap(const std::string& original_location,
                                        art::ArrayRef<const unsigned char> data,
                                        std::string* error_msg) {
  std::string modified_location = StringPrintf("%s-transformed", original_location.c_str());
  // A dangling multi-dex location appended to bootclasspath can cause inaccuracy in oat file
  // validation. For simplicity, just convert it to a normal location.
  size_t pos = modified_location.find(art::DexFileLoader::kMultiDexSeparator);
  if (pos != std::string::npos) {
    modified_location[pos] = '-';
  }
  art::MemMap map = art::MemMap::MapAnonymous(
      modified_location.c_str(),
      data.size(),
      PROT_READ|PROT_WRITE,
      /*low_4gb=*/ false,
      error_msg);
  if (LIKELY(map.IsValid())) {
    memcpy(map.Begin(), data.data(), data.size());
    // Make the dex files mmap read only. This matches how other DexFiles are mmaped and prevents
    // programs from corrupting it.
    map.Protect(PROT_READ);
  }
  return map;
}

Redefiner::ClassRedefinition::ClassRedefinition(
    Redefiner* driver,
    jclass klass,
    const art::DexFile* redefined_dex_file,
    const char* class_sig,
    art::ArrayRef<const unsigned char> orig_dex_file) :
      driver_(driver),
      klass_(klass),
      dex_file_(redefined_dex_file),
      class_sig_(class_sig),
      original_dex_file_(orig_dex_file) {
  lock_acquired_ = GetMirrorClass()->MonitorTryEnter(driver_->self_) != nullptr;
}

Redefiner::ClassRedefinition::~ClassRedefinition() {
  if (driver_ != nullptr && lock_acquired_) {
    GetMirrorClass()->MonitorExit(driver_->self_);
  }
  if (art::kIsDebugBuild) {
    if (dex_file_ != nullptr) {
      art::Thread* self = art::Thread::Current();
      art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
      CHECK(!cl->IsDexFileRegistered(self, *dex_file_));
    }
  }
}

template<RedefinitionType kType>
jvmtiError Redefiner::RedefineClassesGeneric(jvmtiEnv* jenv,
                                             jint class_count,
                                             const jvmtiClassDefinition* definitions) {
  art::Runtime* runtime = art::Runtime::Current();
  art::Thread* self = art::Thread::Current();
  ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
  if (env == nullptr) {
    JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE env was null!";
    return ERR(INVALID_ENVIRONMENT);
  } else if (class_count < 0) {
    JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE class_count was less then 0";
    return ERR(ILLEGAL_ARGUMENT);
  } else if (class_count == 0) {
    // We don't actually need to do anything. Just return OK.
    return OK;
  } else if (definitions == nullptr) {
    JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE null definitions!";
    return ERR(NULL_POINTER);
  }
  std::string error_msg;
  std::vector<ArtClassDefinition> def_vector;
  def_vector.reserve(class_count);
  for (jint i = 0; i < class_count; i++) {
    jvmtiError res = Redefiner::GetClassRedefinitionError<RedefinitionType::kNormal>(
        definitions[i].klass, &error_msg);
    if (res != OK) {
      JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE " << error_msg;
      return res;
    }
    ArtClassDefinition def;
    res = def.Init(self, definitions[i]);
    if (res != OK) {
      JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE bad definition " << i;
      return res;
    }
    def_vector.push_back(std::move(def));
  }
  // Call all the transformation events.
  Transformer::RetransformClassesDirect<kType>(self, &def_vector);
  if (kType == RedefinitionType::kStructural) {
    Transformer::RetransformClassesDirect<RedefinitionType::kNormal>(self, &def_vector);
  }
  jvmtiError res = RedefineClassesDirect(env, runtime, self, def_vector, kType, &error_msg);
  if (res != OK) {
    JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE " << error_msg;
  }
  return res;
}

jvmtiError Redefiner::StructurallyRedefineClasses(jvmtiEnv* jenv,
                                                  jint class_count,
                                                  const jvmtiClassDefinition* definitions) {
  ArtJvmTiEnv* art_env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
  if (art_env == nullptr) {
    return ERR(INVALID_ENVIRONMENT);
  } else if (art_env->capabilities.can_redefine_classes != 1) {
    return ERR(MUST_POSSESS_CAPABILITY);
  }
  return RedefineClassesGeneric<RedefinitionType::kStructural>(jenv, class_count, definitions);
}

jvmtiError Redefiner::RedefineClasses(jvmtiEnv* jenv,
                                      jint class_count,
                                      const jvmtiClassDefinition* definitions) {
  return RedefineClassesGeneric<RedefinitionType::kNormal>(jenv, class_count, definitions);
}

jvmtiError Redefiner::StructurallyRedefineClassDirect(jvmtiEnv* env,
                                                      jclass klass,
                                                      const unsigned char* data,
                                                      jint data_size) {
  if (env == nullptr) {
    return ERR(INVALID_ENVIRONMENT);
  } else if (ArtJvmTiEnv::AsArtJvmTiEnv(env)->capabilities.can_redefine_classes != 1) {
    JVMTI_LOG(INFO, env) << "Does not have can_redefine_classes cap!";
    return ERR(MUST_POSSESS_CAPABILITY);
  }
  std::vector<ArtClassDefinition> acds;
  ArtClassDefinition acd;
  jvmtiError err = acd.Init(
      art::Thread::Current(),
      jvmtiClassDefinition{ .klass = klass, .class_byte_count = data_size, .class_bytes = data });
  if (err != OK) {
    return err;
  }
  acds.push_back(std::move(acd));
  std::string err_msg;
  err = RedefineClassesDirect(ArtJvmTiEnv::AsArtJvmTiEnv(env),
                              art::Runtime::Current(),
                              art::Thread::Current(),
                              acds,
                              RedefinitionType::kStructural,
                              &err_msg);
  if (err != OK) {
    JVMTI_LOG(WARNING, env) << "Failed structural redefinition: " << err_msg;
  }
  return err;
}

jvmtiError Redefiner::RedefineClassesDirect(ArtJvmTiEnv* env,
                                            art::Runtime* runtime,
                                            art::Thread* self,
                                            const std::vector<ArtClassDefinition>& definitions,
                                            RedefinitionType type,
                                            std::string* error_msg) {
  DCHECK(env != nullptr);
  if (definitions.size() == 0) {
    // We don't actually need to do anything. Just return OK.
    return OK;
  }
  // We need to fiddle with the verification class flags. To do this we need to make sure there are
  // no concurrent redefinitions of the same class at the same time. For simplicity and because
  // this is not expected to be a common occurrence we will just wrap the whole thing in a TOP-level
  // lock.

  // Stop JIT for the duration of this redefine since the JIT might concurrently compile a method we
  // are going to redefine.
  // TODO We should prevent user-code suspensions to make sure this isn't held for too long.
  art::jit::ScopedJitSuspend suspend_jit;
  // Get shared mutator lock so we can lock all the classes.
  art::ScopedObjectAccess soa(self);
  Redefiner r(env, runtime, self, type, error_msg);
  for (const ArtClassDefinition& def : definitions) {
    // Only try to transform classes that have been modified.
    if (def.IsModified()) {
      jvmtiError res = r.AddRedefinition(env, def);
      if (res != OK) {
        return res;
      }
    }
  }
  return r.Run();
}

jvmtiError Redefiner::AddRedefinition(ArtJvmTiEnv* env, const ArtClassDefinition& def) {
  std::string original_dex_location;
  jvmtiError ret = OK;
  if ((ret = GetClassLocation(env, def.GetClass(), &original_dex_location))) {
    *error_msg_ = "Unable to get original dex file location!";
    return ret;
  }
  char* generic_ptr_unused = nullptr;
  char* signature_ptr = nullptr;
  if ((ret = env->GetClassSignature(def.GetClass(), &signature_ptr, &generic_ptr_unused)) != OK) {
    *error_msg_ = "Unable to get class signature!";
    return ret;
  }
  JvmtiUniquePtr<char> generic_unique_ptr(MakeJvmtiUniquePtr(env, generic_ptr_unused));
  JvmtiUniquePtr<char> signature_unique_ptr(MakeJvmtiUniquePtr(env, signature_ptr));
  art::MemMap map = MoveDataToMemMap(original_dex_location, def.GetDexData(), error_msg_);
  std::ostringstream os;
  if (!map.IsValid()) {
    os << "Failed to create anonymous mmap for modified dex file of class " << def.GetName()
       << "in dex file " << original_dex_location << " because: " << *error_msg_;
    *error_msg_ = os.str();
    return ERR(OUT_OF_MEMORY);
  }
  if (map.Size() < sizeof(art::DexFile::Header)) {
    *error_msg_ = "Could not read dex file header because dex_data was too short";
    return ERR(INVALID_CLASS_FORMAT);
  }
  std::string name = map.GetName();
  uint32_t checksum = reinterpret_cast<const art::DexFile::Header*>(map.Begin())->checksum_;
  const art::ArtDexFileLoader dex_file_loader;
  std::unique_ptr<const art::DexFile> dex_file(dex_file_loader.Open(name,
                                                                    checksum,
                                                                    std::move(map),
                                                                    /*verify=*/true,
                                                                    /*verify_checksum=*/true,
                                                                    error_msg_));
  if (dex_file.get() == nullptr) {
    os << "Unable to load modified dex file for " << def.GetName() << ": " << *error_msg_;
    *error_msg_ = os.str();
    return ERR(INVALID_CLASS_FORMAT);
  }
  redefinitions_.push_back(
      Redefiner::ClassRedefinition(this,
                                   def.GetClass(),
                                   dex_file.release(),
                                   signature_ptr,
                                   def.GetNewOriginalDexFile()));
  return OK;
}

art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::GetMirrorClass() {
  return driver_->self_->DecodeJObject(klass_)->AsClass();
}

art::ObjPtr<art::mirror::ClassLoader> Redefiner::ClassRedefinition::GetClassLoader() {
  return GetMirrorClass()->GetClassLoader();
}

art::mirror::DexCache* Redefiner::ClassRedefinition::CreateNewDexCache(
    art::Handle<art::mirror::ClassLoader> loader) {
  art::StackHandleScope<2> hs(driver_->self_);
  art::ClassLinker* cl = driver_->runtime_->GetClassLinker();
  art::Handle<art::mirror::DexCache> cache(hs.NewHandle(
      art::ObjPtr<art::mirror::DexCache>::DownCast(
          art::GetClassRoot<art::mirror::DexCache>(cl)->AllocObject(driver_->self_))));
  if (cache.IsNull()) {
    driver_->self_->AssertPendingOOMException();
    return nullptr;
  }
  art::Handle<art::mirror::String> location(hs.NewHandle(
      cl->GetInternTable()->InternStrong(dex_file_->GetLocation().c_str())));
  if (location.IsNull()) {
    driver_->self_->AssertPendingOOMException();
    return nullptr;
  }
  art::WriterMutexLock mu(driver_->self_, *art::Locks::dex_lock_);
  cache->SetLocation(location.Get());
  cache->Initialize(dex_file_.get(), loader.Get());
  return cache.Get();
}

void Redefiner::RecordFailure(jvmtiError result,
                              const std::string& class_sig,
                              const std::string& error_msg) {
  *error_msg_ = StringPrintf("Unable to perform redefinition of '%s': %s",
                             class_sig.c_str(),
                             error_msg.c_str());
  result_ = result;
}

art::mirror::Object* Redefiner::ClassRedefinition::AllocateOrGetOriginalDexFile() {
  // If we have been specifically given a new set of bytes use that
  if (original_dex_file_.size() != 0) {
    return art::mirror::ByteArray::AllocateAndFill(
        driver_->self_,
        reinterpret_cast<const signed char*>(original_dex_file_.data()),
        original_dex_file_.size()).Ptr();
  }

  // See if we already have one set.
  art::ObjPtr<art::mirror::ClassExt> ext(GetMirrorClass()->GetExtData());
  if (!ext.IsNull()) {
    art::ObjPtr<art::mirror::Object> old_original_dex_file(ext->GetOriginalDexFile());
    if (!old_original_dex_file.IsNull()) {
      // We do. Use it.
      return old_original_dex_file.Ptr();
    }
  }

  // return the current dex_cache which has the dex file in it.
  art::ObjPtr<art::mirror::DexCache> current_dex_cache(GetMirrorClass()->GetDexCache());
  // TODO Handle this or make it so it cannot happen.
  if (current_dex_cache->GetDexFile()->NumClassDefs() != 1) {
    LOG(WARNING) << "Current dex file has more than one class in it. Calling RetransformClasses "
                 << "on this class might fail if no transformations are applied to it!";
  }
  return current_dex_cache.Ptr();
}

struct CallbackCtx {
  ObsoleteMap* obsolete_map;
  art::LinearAlloc* allocator;
  std::unordered_set<art::ArtMethod*> obsolete_methods;

  explicit CallbackCtx(ObsoleteMap* map, art::LinearAlloc* alloc)
      : obsolete_map(map), allocator(alloc) {}
};

void DoAllocateObsoleteMethodsCallback(art::Thread* t, void* vdata) NO_THREAD_SAFETY_ANALYSIS {
  CallbackCtx* data = reinterpret_cast<CallbackCtx*>(vdata);
  ObsoleteMethodStackVisitor::UpdateObsoleteFrames(t,
                                                   data->allocator,
                                                   data->obsolete_methods,
                                                   data->obsolete_map);
}

// This creates any ArtMethod* structures needed for obsolete methods and ensures that the stack is
// updated so they will be run.
// TODO Rewrite so we can do this only once regardless of how many redefinitions there are.
void Redefiner::ClassRedefinition::FindAndAllocateObsoleteMethods(
    art::ObjPtr<art::mirror::Class> art_klass) {
  DCHECK(!IsStructuralRedefinition());
  art::ScopedAssertNoThreadSuspension ns("No thread suspension during thread stack walking");
  art::ObjPtr<art::mirror::ClassExt> ext = art_klass->GetExtData();
  CHECK(ext->GetObsoleteMethods() != nullptr);
  art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
  // This holds pointers to the obsolete methods map fields which are updated as needed.
  ObsoleteMap map(ext->GetObsoleteMethods(), ext->GetObsoleteDexCaches(), art_klass->GetDexCache());
  CallbackCtx ctx(&map, linker->GetAllocatorForClassLoader(art_klass->GetClassLoader()));
  // Add all the declared methods to the map
  for (auto& m : art_klass->GetDeclaredMethods(art::kRuntimePointerSize)) {
    if (m.IsIntrinsic()) {
      LOG(WARNING) << "Redefining intrinsic method " << m.PrettyMethod() << ". This may cause the "
                   << "unexpected use of the original definition of " << m.PrettyMethod() << "in "
                   << "methods that have already been compiled.";
    }
    // It is possible to simply filter out some methods where they cannot really become obsolete,
    // such as native methods and keep their original (possibly optimized) implementations. We don't
    // do this, however, since we would need to mark these functions (still in the classes
    // declared_methods array) as obsolete so we will find the correct dex file to get meta-data
    // from (for example about stack-frame size). Furthermore we would be unable to get some useful
    // error checking from the interpreter which ensure we don't try to start executing obsolete
    // methods.
    ctx.obsolete_methods.insert(&m);
  }
  {
    art::MutexLock mu(driver_->self_, *art::Locks::thread_list_lock_);
    art::ThreadList* list = art::Runtime::Current()->GetThreadList();
    list->ForEach(DoAllocateObsoleteMethodsCallback, static_cast<void*>(&ctx));
    // After we've done walking all threads' stacks and updating method pointers on them,
    // update JIT data structures (used by the stack walk above) to point to the new methods.
    art::jit::Jit* jit = art::Runtime::Current()->GetJit();
    if (jit != nullptr) {
      for (const ObsoleteMap::ObsoleteMethodPair& it : *ctx.obsolete_map) {
        // Notify the JIT we are making this obsolete method. It will update the jit's internal
        // structures to keep track of the new obsolete method.
        jit->GetCodeCache()->MoveObsoleteMethod(it.old_method, it.obsolete_method);
      }
    }
  }
}

namespace {
template <typename T> struct SignatureType {};
template <> struct SignatureType<art::ArtField> { using type = std::string_view; };
template <> struct SignatureType<art::ArtMethod> { using type = art::Signature; };

template <typename T> struct NameAndSignature {
 public:
  using SigType = typename SignatureType<T>::type;

  NameAndSignature(const art::DexFile* dex_file, uint32_t id);

  NameAndSignature(const std::string_view& name, const SigType& sig) : name_(name), sig_(sig) {}

  bool operator==(const NameAndSignature<T>& o) {
    return name_ == o.name_ && sig_ == o.sig_;
  }

  std::ostream& dump(std::ostream& os) const {
    return os << "'" << name_ << "' (sig: " << sig_ << ")";
  }

  std::string ToString() const {
    std::ostringstream os;
    os << *this;
    return os.str();
  }

  std::string_view name_;
  SigType sig_;
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const NameAndSignature<T>& nas) {
  return nas.dump(os);
}

using FieldNameAndSignature = NameAndSignature<art::ArtField>;
template <>
FieldNameAndSignature::NameAndSignature(const art::DexFile* dex_file, uint32_t id)
    : FieldNameAndSignature(dex_file->GetFieldName(dex_file->GetFieldId(id)),
                            dex_file->GetFieldTypeDescriptor(dex_file->GetFieldId(id))) {}

using MethodNameAndSignature = NameAndSignature<art::ArtMethod>;
template <>
MethodNameAndSignature::NameAndSignature(const art::DexFile* dex_file, uint32_t id)
    : MethodNameAndSignature(dex_file->GetMethodName(dex_file->GetMethodId(id)),
                             dex_file->GetMethodSignature(dex_file->GetMethodId(id))) {}

}  // namespace

void Redefiner::ClassRedefinition::RecordNewMethodAdded() {
  DCHECK(driver_->IsStructuralRedefinition());
  added_methods_ = true;
}
void Redefiner::ClassRedefinition::RecordNewFieldAdded() {
  DCHECK(driver_->IsStructuralRedefinition());
  added_fields_ = true;
}

bool Redefiner::ClassRedefinition::CheckMethods() {
  art::StackHandleScope<1> hs(driver_->self_);
  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
  DCHECK_EQ(dex_file_->NumClassDefs(), 1u);

  // Make sure we have the same number of methods (or the same or greater if we're structural).
  art::ClassAccessor accessor(*dex_file_, dex_file_->GetClassDef(0));
  uint32_t num_new_method = accessor.NumMethods();
  uint32_t num_old_method = h_klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size();
  const bool is_structural = driver_->IsStructuralRedefinition();
  if (!is_structural && num_new_method != num_old_method) {
    bool bigger = num_new_method > num_old_method;
    RecordFailure(bigger ? ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED)
                         : ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED),
                  StringPrintf("Total number of declared methods changed from %d to %d",
                               num_old_method,
                               num_new_method));
    return false;
  }

  // Skip all of the fields. We should have already checked this.
  // Check each of the methods. NB we don't need to specifically check for removals since the 2 dex
  // files have the same number of methods, which means there must be an equal amount of additions
  // and removals. We should have already checked the fields.
  const art::DexFile& old_dex_file = h_klass->GetDexFile();
  art::ClassAccessor old_accessor(old_dex_file, *h_klass->GetClassDef());
  // We need this to check for methods going missing in structural cases.
  std::vector<bool> seen_old_methods(
      (kCheckAllMethodsSeenOnce || is_structural) ? old_accessor.NumMethods() : 0, false);
  const auto old_methods = old_accessor.GetMethods();
  for (const art::ClassAccessor::Method& new_method : accessor.GetMethods()) {
    // Get the data on the method we are searching for
    MethodNameAndSignature new_method_id(dex_file_.get(), new_method.GetIndex());
    const auto old_iter =
        std::find_if(old_methods.cbegin(), old_methods.cend(), [&](const auto& current_old_method) {
          MethodNameAndSignature old_method_id(&old_dex_file, current_old_method.GetIndex());
          return old_method_id == new_method_id;
        });

    if (!new_method.IsStaticOrDirect()) {
      RecordHasVirtualMembers();
    }
    if (old_iter == old_methods.cend()) {
      if (is_structural) {
        RecordNewMethodAdded();
      } else {
        RecordFailure(
            ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED),
            StringPrintf("Unknown virtual method %s was added!", new_method_id.ToString().c_str()));
        return false;
      }
    } else if (new_method.GetAccessFlags() != old_iter->GetAccessFlags()) {
      RecordFailure(
          ERR(UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED),
          StringPrintf("method %s had different access flags", new_method_id.ToString().c_str()));
      return false;
    } else if (kCheckAllMethodsSeenOnce || is_structural) {
      // We only need this if we are structural.
      size_t off = std::distance(old_methods.cbegin(), old_iter);
      DCHECK(!seen_old_methods[off])
          << "field at " << off << "("
          << MethodNameAndSignature(&old_dex_file, old_iter->GetIndex()) << ") already seen?";
      seen_old_methods[off] = true;
    }
  }
  if ((kCheckAllMethodsSeenOnce || is_structural) &&
      !std::all_of(seen_old_methods.cbegin(), seen_old_methods.cend(), [](auto x) { return x; })) {
    DCHECK(is_structural) << "We should have hit an earlier failure before getting here!";
    auto first_fail =
        std::find_if(seen_old_methods.cbegin(), seen_old_methods.cend(), [](auto x) { return !x; });
    auto off = std::distance(seen_old_methods.cbegin(), first_fail);
    auto fail = old_methods.cbegin();
    std::advance(fail, off);
    RecordFailure(
        ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED),
        StringPrintf("Method %s missing!",
                     MethodNameAndSignature(&old_dex_file, fail->GetIndex()).ToString().c_str()));
    return false;
  }
  return true;
}

bool Redefiner::ClassRedefinition::CheckFields() {
  art::StackHandleScope<1> hs(driver_->self_);
  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
  DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
  art::ClassAccessor new_accessor(*dex_file_, dex_file_->GetClassDef(0));

  const art::DexFile& old_dex_file = h_klass->GetDexFile();
  art::ClassAccessor old_accessor(old_dex_file, *h_klass->GetClassDef());
  // Instance and static fields can be differentiated by their flags so no need to check them
  // separately.
  std::vector<bool> seen_old_fields(old_accessor.NumFields(), false);
  const auto old_fields = old_accessor.GetFields();
  for (const art::ClassAccessor::Field& new_field : new_accessor.GetFields()) {
    // Get the data on the method we are searching for
    FieldNameAndSignature new_field_id(dex_file_.get(), new_field.GetIndex());
    const auto old_iter =
        std::find_if(old_fields.cbegin(), old_fields.cend(), [&](const auto& old_iter) {
          FieldNameAndSignature old_field_id(&old_dex_file, old_iter.GetIndex());
          return old_field_id == new_field_id;
        });
    if (!new_field.IsStatic()) {
      RecordHasVirtualMembers();
    }
    if (old_iter == old_fields.cend()) {
      if (driver_->IsStructuralRedefinition()) {
        RecordNewFieldAdded();
      } else {
        RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
                      StringPrintf("Unknown field %s added!", new_field_id.ToString().c_str()));
        return false;
      }
    } else if (new_field.GetAccessFlags() != old_iter->GetAccessFlags()) {
      RecordFailure(
          ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
          StringPrintf("Field %s had different access flags", new_field_id.ToString().c_str()));
      return false;
    } else {
      size_t off = std::distance(old_fields.cbegin(), old_iter);
      DCHECK(!seen_old_fields[off])
          << "field at " << off << "(" << FieldNameAndSignature(&old_dex_file, old_iter->GetIndex())
          << ") already seen?";
      seen_old_fields[off] = true;
    }
  }
  if (!std::all_of(seen_old_fields.cbegin(), seen_old_fields.cend(), [](auto x) { return x; })) {
    auto first_fail =
        std::find_if(seen_old_fields.cbegin(), seen_old_fields.cend(), [](auto x) { return !x; });
    auto off = std::distance(seen_old_fields.cbegin(), first_fail);
    auto fail = old_fields.cbegin();
    std::advance(fail, off);
    RecordFailure(
        ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
        StringPrintf("Field %s is missing!",
                     FieldNameAndSignature(&old_dex_file, fail->GetIndex()).ToString().c_str()));
    return false;
  }
  return true;
}

bool Redefiner::ClassRedefinition::CheckClass() {
  art::StackHandleScope<1> hs(driver_->self_);
  // Easy check that only 1 class def is present.
  if (dex_file_->NumClassDefs() != 1) {
    RecordFailure(ERR(ILLEGAL_ARGUMENT),
                  StringPrintf("Expected 1 class def in dex file but found %d",
                               dex_file_->NumClassDefs()));
    return false;
  }
  // Get the ClassDef from the new DexFile.
  // Since the dex file has only a single class def the index is always 0.
  const art::dex::ClassDef& def = dex_file_->GetClassDef(0);
  // Get the class as it is now.
  art::Handle<art::mirror::Class> current_class(hs.NewHandle(GetMirrorClass()));

  // Check whether the class object has been successfully acquired.
  if (!lock_acquired_) {
      std::string storage;
      RecordFailure(ERR(INTERNAL),
                    StringPrintf("Failed to lock class object '%s'",
                                 current_class->GetDescriptor(&storage)));
      return false;
  }

  // Check the access flags didn't change.
  if (def.GetJavaAccessFlags() != (current_class->GetAccessFlags() & art::kAccValidClassFlags)) {
    RecordFailure(ERR(UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED),
                  "Cannot change modifiers of class by redefinition");
    return false;
  }

  // Check class name.
  // These should have been checked by the dexfile verifier on load.
  DCHECK_NE(def.class_idx_, art::dex::TypeIndex::Invalid()) << "Invalid type index";
  const char* descriptor = dex_file_->StringByTypeIdx(def.class_idx_);
  DCHECK(descriptor != nullptr) << "Invalid dex file structure!";
  if (!current_class->DescriptorEquals(descriptor)) {
    std::string storage;
    RecordFailure(ERR(NAMES_DONT_MATCH),
                  StringPrintf("expected file to contain class called '%s' but found '%s'!",
                               current_class->GetDescriptor(&storage),
                               descriptor));
    return false;
  }
  if (current_class->IsObjectClass()) {
    if (def.superclass_idx_ != art::dex::TypeIndex::Invalid()) {
      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass added!");
      return false;
    }
  } else {
    const char* super_descriptor = dex_file_->StringByTypeIdx(def.superclass_idx_);
    DCHECK(descriptor != nullptr) << "Invalid dex file structure!";
    if (!current_class->GetSuperClass()->DescriptorEquals(super_descriptor)) {
      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass changed");
      return false;
    }
  }
  const art::dex::TypeList* interfaces = dex_file_->GetInterfacesList(def);
  if (interfaces == nullptr) {
    if (current_class->NumDirectInterfaces() != 0) {
      // TODO Support this for kStructural.
      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added");
      return false;
    }
  } else {
    DCHECK(!current_class->IsProxyClass());
    const art::dex::TypeList* current_interfaces = current_class->GetInterfaceTypeList();
    if (current_interfaces == nullptr || current_interfaces->Size() != interfaces->Size()) {
      // TODO Support this for kStructural.
      RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added or removed");
      return false;
    }
    // The order of interfaces is (barely) meaningful so we error if it changes.
    const art::DexFile& orig_dex_file = current_class->GetDexFile();
    for (uint32_t i = 0; i < interfaces->Size(); i++) {
      if (strcmp(
            dex_file_->StringByTypeIdx(interfaces->GetTypeItem(i).type_idx_),
            orig_dex_file.StringByTypeIdx(current_interfaces->GetTypeItem(i).type_idx_)) != 0) {
        RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED),
                      "Interfaces changed or re-ordered");
        return false;
      }
    }
  }
  return true;
}

bool Redefiner::ClassRedefinition::CheckRedefinable() {
  std::string err;
  art::StackHandleScope<1> hs(driver_->self_);

  art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
  jvmtiError res;
  if (driver_->type_ == RedefinitionType::kStructural && this->IsStructuralRedefinition()) {
    res = Redefiner::GetClassRedefinitionError<RedefinitionType::kStructural>(h_klass, &err);
  } else {
    res = Redefiner::GetClassRedefinitionError<RedefinitionType::kNormal>(h_klass, &err);
  }
  if (res != OK) {
    RecordFailure(res, err);
    return false;
  } else {
    return true;
  }
}

bool Redefiner::ClassRedefinition::CheckRedefinitionIsValid() {
  return CheckClass() && CheckFields() && CheckMethods() && CheckRedefinable();
}

class RedefinitionDataIter;

// A wrapper that lets us hold onto the arbitrary sized data needed for redefinitions in a
// reasonable way. This adds no fields to the normal ObjectArray. By doing this we can avoid
// having to deal with the fact that we need to hold an arbitrary number of references live.
class RedefinitionDataHolder {
 public:
  enum DataSlot : int32_t {
    kSlotSourceClassLoader = 0,
    kSlotJavaDexFile = 1,
    kSlotNewDexFileCookie = 2,
    kSlotNewDexCache = 3,
    kSlotMirrorClass = 4,
    kSlotOrigDexFile = 5,
    kSlotOldObsoleteMethods = 6,
    kSlotOldDexCaches = 7,
    kSlotNewClassObject = 8,
    kSlotOldInstanceObjects = 9,
    kSlotNewInstanceObjects = 10,
    kSlotOldClasses = 11,
    kSlotNewClasses = 12,

    // Must be last one.
    kNumSlots = 13,
  };

  // This needs to have a HandleScope passed in that is capable of creating a new Handle without
  // overflowing. Only one handle will be created. This object has a lifetime identical to that of
  // the passed in handle-scope.
  RedefinitionDataHolder(art::StackHandleScope<1>* hs,
                         art::Runtime* runtime,
                         art::Thread* self,
                         std::vector<Redefiner::ClassRedefinition>* redefinitions)
      REQUIRES_SHARED(art::Locks::mutator_lock_) :
    arr_(hs->NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
        self,
        art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>(runtime->GetClassLinker()),
        redefinitions->size() * kNumSlots))),
    redefinitions_(redefinitions),
    initialized_(redefinitions_->size(), false),
    actually_structural_(redefinitions_->size(), false),
    initial_structural_(redefinitions_->size(), false) {}

  ~RedefinitionDataHolder() REQUIRES_SHARED(art::Locks::mutator_lock_);

  bool IsNull() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return arr_.IsNull();
  }

  art::ObjPtr<art::mirror::ClassLoader> GetSourceClassLoader(jint klass_index) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::ClassLoader>::DownCast(
        GetSlot(klass_index, kSlotSourceClassLoader));
  }
  art::ObjPtr<art::mirror::Object> GetJavaDexFile(jint klass_index) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return GetSlot(klass_index, kSlotJavaDexFile);
  }
  art::ObjPtr<art::mirror::LongArray> GetNewDexFileCookie(jint klass_index) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::LongArray>::DownCast(
        GetSlot(klass_index, kSlotNewDexFileCookie));
  }
  art::ObjPtr<art::mirror::DexCache> GetNewDexCache(jint klass_index) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::DexCache>::DownCast(GetSlot(klass_index, kSlotNewDexCache));
  }
  art::ObjPtr<art::mirror::Class> GetMirrorClass(jint klass_index) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::Class>::DownCast(GetSlot(klass_index, kSlotMirrorClass));
  }

  art::ObjPtr<art::mirror::Object> GetOriginalDexFile(jint klass_index) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::Object>::DownCast(GetSlot(klass_index, kSlotOrigDexFile));
  }

  art::ObjPtr<art::mirror::PointerArray> GetOldObsoleteMethods(jint klass_index) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::PointerArray>::DownCast(
        GetSlot(klass_index, kSlotOldObsoleteMethods));
  }

  art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> GetOldDexCaches(
      jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>>::DownCast(
        GetSlot(klass_index, kSlotOldDexCaches));
  }

  art::ObjPtr<art::mirror::Class> GetNewClassObject(jint klass_index) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::Class>::DownCast(GetSlot(klass_index, kSlotNewClassObject));
  }

  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetOldInstanceObjects(
      jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>>::DownCast(
        GetSlot(klass_index, kSlotOldInstanceObjects));
  }

  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetNewInstanceObjects(
      jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>>::DownCast(
        GetSlot(klass_index, kSlotNewInstanceObjects));
  }
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetOldClasses(jint klass_index) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>>::DownCast(
        GetSlot(klass_index, kSlotOldClasses));
  }
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetNewClasses(jint klass_index) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>>::DownCast(
        GetSlot(klass_index, kSlotNewClasses));
  }
  bool IsInitialized(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return initialized_[klass_index];
  }
  bool IsActuallyStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return actually_structural_[klass_index];
  }

  bool IsInitialStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return initial_structural_[klass_index];
  }

  void SetSourceClassLoader(jint klass_index, art::ObjPtr<art::mirror::ClassLoader> loader)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotSourceClassLoader, loader);
  }
  void SetJavaDexFile(jint klass_index, art::ObjPtr<art::mirror::Object> dexfile)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotJavaDexFile, dexfile);
  }
  void SetNewDexFileCookie(jint klass_index, art::ObjPtr<art::mirror::LongArray> cookie)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotNewDexFileCookie, cookie);
  }
  void SetNewDexCache(jint klass_index, art::ObjPtr<art::mirror::DexCache> cache)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotNewDexCache, cache);
  }
  void SetMirrorClass(jint klass_index, art::ObjPtr<art::mirror::Class> klass)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotMirrorClass, klass);
  }
  void SetOriginalDexFile(jint klass_index, art::ObjPtr<art::mirror::Object> bytes)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotOrigDexFile, bytes);
  }
  void SetOldObsoleteMethods(jint klass_index, art::ObjPtr<art::mirror::PointerArray> methods)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotOldObsoleteMethods, methods);
  }
  void SetOldDexCaches(jint klass_index,
                       art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> caches)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotOldDexCaches, caches);
  }

  void SetNewClassObject(jint klass_index, art::ObjPtr<art::mirror::Class> klass)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotNewClassObject, klass);
  }

  void SetOldInstanceObjects(jint klass_index,
                             art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotOldInstanceObjects, objs);
  }
  void SetNewInstanceObjects(jint klass_index,
                             art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotNewInstanceObjects, objs);
  }
  void SetOldClasses(jint klass_index,
                     art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotOldClasses, klasses);
  }
  void SetNewClasses(jint klass_index,
                     art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    SetSlot(klass_index, kSlotNewClasses, klasses);
  }
  void SetInitialized(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    initialized_[klass_index] = true;
  }
  void SetActuallyStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    actually_structural_[klass_index] = true;
  }
  void SetInitialStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    initial_structural_[klass_index] = true;
  }
  int32_t Length() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return arr_->GetLength() / kNumSlots;
  }

  std::vector<Redefiner::ClassRedefinition>* GetRedefinitions()
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return redefinitions_;
  }

  bool operator==(const RedefinitionDataHolder& other) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return arr_.Get() == other.arr_.Get();
  }

  bool operator!=(const RedefinitionDataHolder& other) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return !(*this == other);
  }

  RedefinitionDataIter begin() REQUIRES_SHARED(art::Locks::mutator_lock_);
  RedefinitionDataIter end() REQUIRES_SHARED(art::Locks::mutator_lock_);

 private:
  mutable art::Handle<art::mirror::ObjectArray<art::mirror::Object>> arr_;
  std::vector<Redefiner::ClassRedefinition>* redefinitions_;
  // Used to mark a particular redefinition as fully initialized.
  std::vector<bool> initialized_;
  // Used to mark a redefinition as 'actually' structural. That is either the redefinition is
  // structural or a superclass is.
  std::vector<bool> actually_structural_;
  // Used to mark a redefinition as the initial structural redefinition. This redefinition will take
  // care of updating all of its subtypes.
  std::vector<bool> initial_structural_;

  art::ObjPtr<art::mirror::Object> GetSlot(jint klass_index, DataSlot slot) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    DCHECK_LT(klass_index, Length());
    return arr_->Get((kNumSlots * klass_index) + slot);
  }

  void SetSlot(jint klass_index,
               DataSlot slot,
               art::ObjPtr<art::mirror::Object> obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    DCHECK(!art::Runtime::Current()->IsActiveTransaction());
    DCHECK_LT(klass_index, Length());
    arr_->Set<false>((kNumSlots * klass_index) + slot, obj);
  }

  DISALLOW_COPY_AND_ASSIGN(RedefinitionDataHolder);
};

class RedefinitionDataIter {
 public:
  RedefinitionDataIter(int32_t idx, RedefinitionDataHolder& holder) : idx_(idx), holder_(holder) {}

  RedefinitionDataIter(const RedefinitionDataIter&) = default;
  RedefinitionDataIter(RedefinitionDataIter&&) = default;
  // Assignments are deleted because holder_ is a reference.
  RedefinitionDataIter& operator=(const RedefinitionDataIter&) = delete;
  RedefinitionDataIter& operator=(RedefinitionDataIter&&) = delete;

  bool operator==(const RedefinitionDataIter& other) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return idx_ == other.idx_ && holder_ == other.holder_;
  }

  bool operator!=(const RedefinitionDataIter& other) const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return !(*this == other);
  }

  RedefinitionDataIter operator++() {  // Value after modification.
    idx_++;
    return *this;
  }

  RedefinitionDataIter operator++(int) {
    RedefinitionDataIter temp = *this;
    idx_++;
    return temp;
  }

  RedefinitionDataIter operator+(ssize_t delta) const {
    RedefinitionDataIter temp = *this;
    temp += delta;
    return temp;
  }

  RedefinitionDataIter& operator+=(ssize_t delta) {
    idx_ += delta;
    return *this;
  }

  // Compat for STL iterators.
  RedefinitionDataIter& operator*() {
    return *this;
  }

  Redefiner::ClassRedefinition& GetRedefinition() REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return (*holder_.GetRedefinitions())[idx_];
  }

  RedefinitionDataHolder& GetHolder() {
    return holder_;
  }

  art::ObjPtr<art::mirror::ClassLoader> GetSourceClassLoader() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetSourceClassLoader(idx_);
  }
  art::ObjPtr<art::mirror::Object> GetJavaDexFile() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetJavaDexFile(idx_);
  }
  art::ObjPtr<art::mirror::LongArray> GetNewDexFileCookie() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetNewDexFileCookie(idx_);
  }
  art::ObjPtr<art::mirror::DexCache> GetNewDexCache() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetNewDexCache(idx_);
  }
  art::ObjPtr<art::mirror::Class> GetMirrorClass() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetMirrorClass(idx_);
  }
  art::ObjPtr<art::mirror::Object> GetOriginalDexFile() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetOriginalDexFile(idx_);
  }
  art::ObjPtr<art::mirror::PointerArray> GetOldObsoleteMethods() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetOldObsoleteMethods(idx_);
  }
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> GetOldDexCaches() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetOldDexCaches(idx_);
  }

  art::ObjPtr<art::mirror::Class> GetNewClassObject() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetNewClassObject(idx_);
  }

  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetOldInstanceObjects() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetOldInstanceObjects(idx_);
  }
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetNewInstanceObjects() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetNewInstanceObjects(idx_);
  }
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetOldClasses() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetOldClasses(idx_);
  }
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetNewClasses() const
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.GetNewClasses(idx_);
  }
  bool IsInitialized() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.IsInitialized(idx_);
  }
  bool IsActuallyStructural() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.IsActuallyStructural(idx_);
  }
  bool IsInitialStructural() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return holder_.IsInitialStructural(idx_);
  }
  int32_t GetIndex() const {
    return idx_;
  }

  void SetSourceClassLoader(art::mirror::ClassLoader* loader)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetSourceClassLoader(idx_, loader);
  }
  void SetJavaDexFile(art::ObjPtr<art::mirror::Object> dexfile)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetJavaDexFile(idx_, dexfile);
  }
  void SetNewDexFileCookie(art::ObjPtr<art::mirror::LongArray> cookie)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetNewDexFileCookie(idx_, cookie);
  }
  void SetNewDexCache(art::ObjPtr<art::mirror::DexCache> cache)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetNewDexCache(idx_, cache);
  }
  void SetMirrorClass(art::ObjPtr<art::mirror::Class> klass)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetMirrorClass(idx_, klass);
  }
  void SetOriginalDexFile(art::ObjPtr<art::mirror::Object> bytes)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetOriginalDexFile(idx_, bytes);
  }
  void SetOldObsoleteMethods(art::ObjPtr<art::mirror::PointerArray> methods)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetOldObsoleteMethods(idx_, methods);
  }
  void SetOldDexCaches(art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> caches)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetOldDexCaches(idx_, caches);
  }
  void SetNewClassObject(art::ObjPtr<art::mirror::Class> klass)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetNewClassObject(idx_, klass);
  }
  void SetOldInstanceObjects(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetOldInstanceObjects(idx_, objs);
  }
  void SetNewInstanceObjects(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetNewInstanceObjects(idx_, objs);
  }
  void SetOldClasses(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetOldClasses(idx_, klasses);
  }
  void SetNewClasses(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetNewClasses(idx_, klasses);
  }
  void SetInitialized() REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetInitialized(idx_);
  }
  void SetActuallyStructural() REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetActuallyStructural(idx_);
  }
  void SetInitialStructural() REQUIRES_SHARED(art::Locks::mutator_lock_) {
    holder_.SetInitialStructural(idx_);
  }

 private:
  int32_t idx_;
  RedefinitionDataHolder& holder_;
};

RedefinitionDataIter RedefinitionDataHolder::begin() {
  return RedefinitionDataIter(0, *this);
}

RedefinitionDataIter RedefinitionDataHolder::end() {
  return RedefinitionDataIter(Length(), *this);
}

RedefinitionDataHolder::~RedefinitionDataHolder() {
  art::Thread* self = art::Thread::Current();
  art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
  for (RedefinitionDataIter data = begin(); data != end(); ++data) {
    art::ObjPtr<art::mirror::DexCache> dex_cache = data.GetNewDexCache();
    // When redefinition fails, the dex file will be deleted in the
    // `ClassRedefinition` destructor. To avoid having a heap `DexCache` pointing
    // to a dangling pointer, we clear the entries of those dex caches that are
    // not registered in the runtime.
    if (dex_cache != nullptr &&
        dex_cache->GetDexFile() != nullptr &&
        !cl->IsDexFileRegistered(self, *dex_cache->GetDexFile())) {
      dex_cache->ResetNativeArrays();
      dex_cache->SetDexFile(nullptr);
    }
  }
}

bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& iter) {
  DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
  art::StackHandleScope<3> hs(driver_->self_);
  std::string error;
  // TODO Make verification log level lower
  art::verifier::FailureKind failure =
      art::verifier::ClassVerifier::VerifyClass(driver_->self_,
                                                /*verifier_deps=*/nullptr,
                                                dex_file_.get(),
                                                hs.NewHandle(iter.GetNewClassObject() != nullptr
                                                                ? iter.GetNewClassObject()
                                                                : iter.GetMirrorClass()),
                                                hs.NewHandle(iter.GetNewDexCache()),
                                                hs.NewHandle(GetClassLoader()),
                                                /*class_def=*/ dex_file_->GetClassDef(0),
                                                /*callbacks=*/ nullptr,
                                                /*log_level=*/
                                                art::verifier::HardFailLogMode::kLogWarning,
                                                art::Runtime::Current()->GetTargetSdkVersion(),
                                                &error);
  if (failure == art::verifier::FailureKind::kHardFailure) {
    RecordFailure(ERR(FAILS_VERIFICATION), "Failed to verify class. Error was: " + error);
    return false;
  }
  return true;
}

// Looks through the previously allocated cookies to see if we need to update them with another new
// dexfile. This is so that even if multiple classes with the same classloader are redefined at
// once they are all added to the classloader.
bool Redefiner::ClassRedefinition::AllocateAndRememberNewDexFileCookie(
    art::Handle<art::mirror::ClassLoader> source_class_loader,
    art::Handle<art::mirror::Object> dex_file_obj,
    /*out*/RedefinitionDataIter* cur_data) {
  art::StackHandleScope<2> hs(driver_->self_);
  art::MutableHandle<art::mirror::LongArray> old_cookie(
      hs.NewHandle<art::mirror::LongArray>(nullptr));
  bool has_older_cookie = false;
  // See if we already have a cookie that a previous redefinition got from the same classloader
  // and the same JavaDex file.
  for (auto old_data = cur_data->GetHolder().begin(); old_data != *cur_data; ++old_data) {
    if (old_data.GetSourceClassLoader() == source_class_loader.Get() &&
        old_data.GetJavaDexFile() == dex_file_obj.Get()) {
      // Since every instance of this JavaDex file should have the same cookie associated with it we
      // can stop looking here.
      has_older_cookie = true;
      old_cookie.Assign(old_data.GetNewDexFileCookie());
      break;
    }
  }
  if (old_cookie.IsNull()) {
    // No older cookie. Get it directly from the dex_file_obj
    // We should not have seen this classloader elsewhere.
    CHECK(!has_older_cookie);
    old_cookie.Assign(ClassLoaderHelper::GetDexFileCookie(dex_file_obj));
  }
  // Use the old cookie to generate the new one with the new DexFile* added in.
  art::Handle<art::mirror::LongArray>
      new_cookie(hs.NewHandle(ClassLoaderHelper::AllocateNewDexFileCookie(driver_->self_,
                                                                          old_cookie,
                                                                          dex_file_.get())));
  // Make sure the allocation worked.
  if (new_cookie.IsNull()) {
    return false;
  }

  // Save the cookie.
  cur_data->SetNewDexFileCookie(new_cookie.Get());
  // If there are other copies of the same classloader and the same JavaDex file we need to
  // make sure that we all have the same cookie.
  if (has_older_cookie) {
    for (auto old_data = cur_data->GetHolder().begin(); old_data != *cur_data; ++old_data) {
      // We will let the GC take care of the cookie we allocated for this one.
      if (old_data.GetSourceClassLoader() == source_class_loader.Get() &&
          old_data.GetJavaDexFile() == dex_file_obj.Get()) {
        old_data.SetNewDexFileCookie(new_cookie.Get());
      }
    }
  }

  return true;
}

bool CompareClasses(art::ObjPtr<art::mirror::Class> l, art::ObjPtr<art::mirror::Class> r)
    REQUIRES_SHARED(art::Locks::mutator_lock_) {
  auto parents = [](art::ObjPtr<art::mirror::Class> c) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    uint32_t res = 0;
    while (!c->IsObjectClass()) {
      res++;
      c = c->GetSuperClass();
    }
    return res;
  };
  return parents(l.Ptr()) < parents(r.Ptr());
}

bool Redefiner::ClassRedefinition::CollectAndCreateNewInstances(
    /*out*/ RedefinitionDataIter* cur_data) {
  if (!cur_data->IsInitialStructural()) {
    // An earlier structural redefinition already remade all the instances.
    return true;
  }
  art::gc::Heap* heap = driver_->runtime_->GetHeap();
  art::VariableSizedHandleScope hs(driver_->self_);
  art::Handle<art::mirror::Class> old_klass(hs.NewHandle(cur_data->GetMirrorClass()));
  std::vector<art::Handle<art::mirror::Object>> old_instances;
  auto is_instance = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return obj->InstanceOf(old_klass.Get());
  };
  heap->VisitObjects([&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    if (is_instance(obj)) {
      old_instances.push_back(hs.NewHandle(obj));
    }
  });
  VLOG(plugin) << "Collected " << old_instances.size() << " instances to recreate!";
  art::Handle<art::mirror::ObjectArray<art::mirror::Class>> old_classes_arr(
      hs.NewHandle(cur_data->GetOldClasses()));
  art::Handle<art::mirror::ObjectArray<art::mirror::Class>> new_classes_arr(
      hs.NewHandle(cur_data->GetNewClasses()));
  DCHECK_EQ(old_classes_arr->GetLength(), new_classes_arr->GetLength());
  DCHECK_GT(old_classes_arr->GetLength(), 0);
  art::Handle<art::mirror::Class> obj_array_class(
      hs.NewHandle(art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>(
          driver_->runtime_->GetClassLinker())));
  art::Handle<art::mirror::ObjectArray<art::mirror::Object>> old_instances_arr(
      hs.NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
          driver_->self_, obj_array_class.Get(), old_instances.size())));
  if (old_instances_arr.IsNull()) {
    driver_->self_->AssertPendingOOMException();
    driver_->self_->ClearException();
    RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate old_instance arrays!");
    return false;
  }
  for (uint32_t i = 0; i < old_instances.size(); ++i) {
    old_instances_arr->Set(i, old_instances[i].Get());
  }
  cur_data->SetOldInstanceObjects(old_instances_arr.Get());

  art::Handle<art::mirror::ObjectArray<art::mirror::Object>> new_instances_arr(
      hs.NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
          driver_->self_, obj_array_class.Get(), old_instances.size())));
  if (new_instances_arr.IsNull()) {
    driver_->self_->AssertPendingOOMException();
    driver_->self_->ClearException();
    RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate new_instance arrays!");
    return false;
  }
  for (auto pair : art::ZipCount(art::IterationRange(old_instances.begin(), old_instances.end()))) {
    art::Handle<art::mirror::Object> hinstance(pair.first);
    int32_t i = pair.second;
    auto iterator = art::ZipLeft(old_classes_arr.Iterate<art::mirror::Class>(),
                                 new_classes_arr.Iterate<art::mirror::Class>());
    auto it = std::find_if(iterator.begin(),
                           iterator.end(),
                           [&](auto class_pair) REQUIRES_SHARED(art::Locks::mutator_lock_) {
                             return class_pair.first == hinstance->GetClass();
                           });
    DCHECK(it != iterator.end()) << "Unable to find class pair for "
                                 << hinstance->GetClass()->PrettyClass() << " (instance " << i
                                 << ")";
    auto [_, new_type] = *it;
    // Make sure when allocating the new instance we don't add it's finalizer since we will directly
    // replace the old object in the finalizer reference. If we added it here to we would call
    // finalize twice.
    // NB If a type is changed from being non-finalizable to finalizable the finalizers on any
    //    objects created before the redefine will never be called. This is (sort of) allowable by
    //    the spec and greatly simplifies implementation.
    // TODO Make it so we will always call all finalizers, even if the object when it was created
    // wasn't finalizable. To do this we need to be careful of handling failure correctly and making
    // sure that objects aren't finalized multiple times and that instances of failed redefinitions
    // aren't finalized.
    art::ObjPtr<art::mirror::Object> new_instance(
        new_type->Alloc</*kIsInstrumented=*/true,
                        art::mirror::Class::AddFinalizer::kNoAddFinalizer,
                        /*kCheckAddFinalizer=*/false>(
            driver_->self_, driver_->runtime_->GetHeap()->GetCurrentAllocator()));
    if (new_instance.IsNull()) {
      driver_->self_->AssertPendingOOMException();
      driver_->self_->ClearException();
      std::string msg(
          StringPrintf("Could not allocate instance %d of %zu", i, old_instances.size()));
      RecordFailure(ERR(OUT_OF_MEMORY), msg);
      return false;
    }
    new_instances_arr->Set(i, new_instance);
  }
  cur_data->SetNewInstanceObjects(new_instances_arr.Get());
  return true;
}

bool Redefiner::ClassRedefinition::FinishRemainingCommonAllocations(
    /*out*/RedefinitionDataIter* cur_data) {
  art::StackHandleScope<2> hs(driver_->self_);
  cur_data->SetMirrorClass(GetMirrorClass());
  // This shouldn't allocate
  art::Handle<art::mirror::ClassLoader> loader(hs.NewHandle(GetClassLoader()));
  // The bootclasspath is handled specially so it doesn't have a j.l.DexFile.
  if (!art::ClassLinker::IsBootClassLoader(loader.Get())) {
    cur_data->SetSourceClassLoader(loader.Get());
    art::Handle<art::mirror::Object> dex_file_obj(hs.NewHandle(
        ClassLoaderHelper::FindSourceDexFileObject(driver_->self_, loader)));
    cur_data->SetJavaDexFile(dex_file_obj.Get());
    if (dex_file_obj == nullptr) {
      RecordFailure(ERR(INTERNAL), "Unable to find dex file!");
      return false;
    }
    // Allocate the new dex file cookie.
    if (!AllocateAndRememberNewDexFileCookie(loader, dex_file_obj, cur_data)) {
      driver_->self_->AssertPendingOOMException();
      driver_->self_->ClearException();
      RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate dex file array for class loader");
      return false;
    }
  }
  cur_data->SetNewDexCache(CreateNewDexCache(loader));
  if (cur_data->GetNewDexCache() == nullptr) {
    driver_->self_->AssertPendingException();
    driver_->self_->ClearException();
    RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate DexCache");
    return false;
  }

  // We won't always need to set this field.
  cur_data->SetOriginalDexFile(AllocateOrGetOriginalDexFile());
  if (cur_data->GetOriginalDexFile() == nullptr) {
    driver_->self_->AssertPendingOOMException();
    driver_->self_->ClearException();
    RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate array for original dex file");
    return false;
  }
  return true;
}

bool Redefiner::ClassRedefinition::FinishNewClassAllocations(RedefinitionDataHolder &holder,
                                                             RedefinitionDataIter *cur_data) {
  if (cur_data->IsInitialized() || !cur_data->IsActuallyStructural()) {
    cur_data->SetInitialized();
    return true;
  }

  art::VariableSizedHandleScope hs(driver_->self_);
  // If we weren't the lowest structural redef the superclass would have already initialized us.
  CHECK(IsStructuralRedefinition());
  CHECK(cur_data->IsInitialStructural()) << "Should have already been initialized by supertype";
  auto setup_single_redefinition =
      [this](RedefinitionDataIter* data, art::Handle<art::mirror::Class> super_class)
          REQUIRES_SHARED(art::Locks::mutator_lock_) -> art::ObjPtr<art::mirror::Class> {
    art::StackHandleScope<3> chs(driver_->self_);
    art::Handle<art::mirror::Class> nc(
        chs.NewHandle(AllocateNewClassObject(chs.NewHandle(data->GetMirrorClass()),
                                             super_class,
                                             chs.NewHandle(data->GetNewDexCache()),
                                             /*dex_class_def_index*/ 0)));
    if (nc.IsNull()) {
      return nullptr;
    }

    data->SetNewClassObject(nc.Get());
    data->SetInitialized();
    return nc.Get();
  };

  std::vector<art::Handle<art::mirror::Class>> old_types;
  {
    art::gc::Heap* heap = driver_->runtime_->GetHeap();
    art::Handle<art::mirror::Class>
        old_klass(hs.NewHandle(cur_data->GetMirrorClass()));
    if (setup_single_redefinition(cur_data, hs.NewHandle(old_klass->GetSuperClass())).IsNull()) {
      return false;
    }
    auto is_subtype = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
      // We've already waited for class defines to be finished and paused them. All classes should be
      // either resolved or error. We don't need to do anything with error classes, since they cannot
      // be accessed in any observable way.
      return obj->IsClass() && obj->AsClass()->IsResolved() &&
            old_klass->IsAssignableFrom(obj->AsClass());
    };
    heap->VisitObjects([&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
      if (is_subtype(obj)) {
        old_types.push_back(hs.NewHandle(obj->AsClass()));
      }
    });
    DCHECK_GT(old_types.size(), 0u) << "Expected to find at least old_klass!";
    VLOG(plugin) << "Found " << old_types.size() << " types that are/are subtypes of "
                << old_klass->PrettyClass();
  }

  art::Handle<art::mirror::Class> cls_array_class(
      hs.NewHandle(art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Class>>(
          driver_->runtime_->GetClassLinker())));
  art::Handle<art::mirror::ObjectArray<art::mirror::Class>> old_classes_arr(
      hs.NewHandle(art::mirror::ObjectArray<art::mirror::Class>::Alloc(
          driver_->self_, cls_array_class.Get(), old_types.size())));
  if (old_classes_arr.IsNull()) {
    driver_->self_->AssertPendingOOMException();
    driver_->self_->ClearException();
    RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate old_classes arrays!");
    return false;
  }
  // Sort the old_types topologically.
  {
    art::ScopedAssertNoThreadSuspension sants("Sort classes");
    // Sort them by the distance to the base-class. This ensures that any class occurs before any of
    // its subtypes.
    std::sort(old_types.begin(),
              old_types.end(),
              [](auto& l, auto& r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
                return CompareClasses(l.Get(), r.Get());
              });
  }
  for (uint32_t i = 0; i < old_types.size(); ++i) {
    DCHECK(!old_types[i].IsNull()) << i;
    old_classes_arr->Set(i, old_types[i].Get());
  }
  cur_data->SetOldClasses(old_classes_arr.Get());
  DCHECK_GT(old_classes_arr->GetLength(), 0);

  art::Handle<art::mirror::ObjectArray<art::mirror::Class>> new_classes_arr(
      hs.NewHandle(art::mirror::ObjectArray<art::mirror::Class>::Alloc(
          driver_->self_, cls_array_class.Get(), old_types.size())));
  if (new_classes_arr.IsNull()) {
    driver_->self_->AssertPendingOOMException();
    driver_->self_->ClearException();
    RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate new_classes arrays!");
    return false;
  }

  art::MutableHandle<art::mirror::DexCache> dch(hs.NewHandle<art::mirror::DexCache>(nullptr));
  art::MutableHandle<art::mirror::Class> superclass(hs.NewHandle<art::mirror::Class>(nullptr));
  for (size_t i = 0; i < old_types.size(); i++) {
    art::Handle<art::mirror::Class>& old_type = old_types[i];
    if (old_type.Get() == cur_data->GetMirrorClass()) {
      CHECK_EQ(i, 0u) << "original class not at index 0. Bad sort!";
      new_classes_arr->Set(i, cur_data->GetNewClassObject());
      continue;
    } else {
      auto old_super = std::find_if(old_types.begin(),
                                    old_types.begin() + i,
                                    [&](art::Handle<art::mirror::Class>& v)
                                        REQUIRES_SHARED(art::Locks::mutator_lock_) {
                                          return v.Get() == old_type->GetSuperClass();
                                        });
      // Only the GetMirrorClass should not be in this list.
      CHECK(old_super != old_types.begin() + i)
          << "from first " << i << " could not find super of " << old_type->PrettyClass()
          << " expected to find " << old_type->GetSuperClass()->PrettyClass();
      superclass.Assign(new_classes_arr->Get(std::distance(old_types.begin(), old_super)));
      auto new_redef = std::find_if(
          *cur_data + 1, holder.end(), [&](auto it) REQUIRES_SHARED(art::Locks::mutator_lock_) {
            return it.GetMirrorClass() == old_type.Get();
          });
      art::ObjPtr<art::mirror::Class> new_type;
      if (new_redef == holder.end()) {
        // We aren't also redefining this subclass. Just allocate a new class and continue.
        dch.Assign(old_type->GetDexCache());
        new_type =
            AllocateNewClassObject(old_type, superclass, dch, old_type->GetDexClassDefIndex());
      } else {
        // This subclass is also being redefined. We need to use its new dex-file to load the new
        // class.
        CHECK(new_redef.IsActuallyStructural());
        CHECK(!new_redef.IsInitialStructural());
        new_type = setup_single_redefinition(&new_redef, superclass);
      }
      if (new_type == nullptr) {
        VLOG(plugin) << "Failed to load new version of class " << old_type->PrettyClass()
                     << " for structural redefinition!";
        return false;
      }
      new_classes_arr->Set(i, new_type);
    }
  }
  cur_data->SetNewClasses(new_classes_arr.Get());
  return true;
}

uint32_t Redefiner::ClassRedefinition::GetNewClassSize(art::ClassAccessor& accessor) {
  uint32_t num_8bit_static_fields = 0;
  uint32_t num_16bit_static_fields = 0;
  uint32_t num_32bit_static_fields = 0;
  uint32_t num_64bit_static_fields = 0;
  uint32_t num_ref_static_fields = 0;
  for (const art::ClassAccessor::Field& f : accessor.GetStaticFields()) {
    std::string_view desc(accessor.GetDexFile().GetFieldTypeDescriptor(
        accessor.GetDexFile().GetFieldId(f.GetIndex())));
    if (desc[0] == 'L' || desc[0] == '[') {
      num_ref_static_fields++;
    } else if (desc == "Z" || desc == "B") {
      num_8bit_static_fields++;
    } else if (desc == "C" || desc == "S") {
      num_16bit_static_fields++;
    } else if (desc == "I" || desc == "F") {
      num_32bit_static_fields++;
    } else if (desc == "J" || desc == "D") {
      num_64bit_static_fields++;
    } else {
      LOG(FATAL) << "Unknown type descriptor! " << desc;
    }
  }

  return art::mirror::Class::ComputeClassSize(/*has_embedded_vtable=*/ false,
                                              /*num_vtable_entries=*/ 0,
                                              num_8bit_static_fields,
                                              num_16bit_static_fields,
                                              num_32bit_static_fields,
                                              num_64bit_static_fields,
                                              num_ref_static_fields,
                                              art::kRuntimePointerSize);
}

art::ObjPtr<art::mirror::Class>
Redefiner::ClassRedefinition::AllocateNewClassObject(art::Handle<art::mirror::DexCache> cache) {
  art::StackHandleScope<2> hs(driver_->self_);
  art::Handle<art::mirror::Class> old_class(hs.NewHandle(GetMirrorClass()));
  art::Handle<art::mirror::Class> super_class(hs.NewHandle(old_class->GetSuperClass()));
  return AllocateNewClassObject(old_class, super_class, cache, /*dex_class_def_index*/0);
}

art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::AllocateNewClassObject(
    art::Handle<art::mirror::Class> old_class,
    art::Handle<art::mirror::Class> super_class,
    art::Handle<art::mirror::DexCache> cache,
    uint16_t dex_class_def_index) {
  // This is a stripped down DefineClass. We don't want to use DefineClass directly because it needs
  // to perform a lot of extra steps to tell the ClassTable and the jit and everything about a new
  // class. For now we will need to rely on our tests catching any issues caused by changes in how
  // class_linker sets up classes.
  // TODO Unify/move this into ClassLinker maybe.
  art::StackHandleScope<3> hs(driver_->self_);
  art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
  const art::DexFile* dex_file = cache->GetDexFile();
  art::ClassAccessor accessor(*dex_file, dex_class_def_index);
  art::Handle<art::mirror::Class> new_class(hs.NewHandle(linker->AllocClass(
      driver_->self_, GetNewClassSize(accessor))));
  if (new_class.IsNull()) {
    driver_->self_->AssertPendingOOMException();
    RecordFailure(
        ERR(OUT_OF_MEMORY),
        "Unable to allocate class object for redefinition of " + old_class->PrettyClass());
    driver_->self_->ClearException();
    return nullptr;
  }
  new_class->SetDexCache(cache.Get());
  linker->SetupClass(*dex_file,
                     dex_file->GetClassDef(dex_class_def_index),
                     new_class,
                     old_class->GetClassLoader());

  // Make sure we are ready for linking. The lock isn't really needed since this isn't visible to
  // other threads but the linker expects it.
  art::ObjectLock<art::mirror::Class> lock(driver_->self_, new_class);
  new_class->SetClinitThreadId(driver_->self_->GetTid());
  // Make sure we have a valid empty iftable even if there are errors.
  new_class->SetIfTable(art::GetClassRoot<art::mirror::Object>(linker)->GetIfTable());
  linker->LoadClass(
      driver_->self_, *dex_file, dex_file->GetClassDef(dex_class_def_index), new_class);
  // NB. We know the interfaces and supers didn't change! :)
  art::MutableHandle<art::mirror::Class> linked_class(hs.NewHandle<art::mirror::Class>(nullptr));
  art::Handle<art::mirror::ObjectArray<art::mirror::Class>> proxy_ifaces(
      hs.NewHandle<art::mirror::ObjectArray<art::mirror::Class>>(nullptr));
  // No changing hierarchy so everything is loaded.
  new_class->SetSuperClass(super_class.Get());
  art::mirror::Class::SetStatus(new_class, art::ClassStatus::kLoaded, nullptr);
  if (!linker->LinkClass(driver_->self_, nullptr, new_class, proxy_ifaces, &linked_class)) {
    std::ostringstream oss;
    oss << "failed to link class due to "
        << (driver_->self_->IsExceptionPending() ? driver_->self_->GetException()->Dump()
                                                 : " unknown");
    RecordFailure(ERR(INTERNAL), oss.str());
    driver_->self_->ClearException();
    return nullptr;
  }
  // Everything is already resolved.
  art::ObjectLock<art::mirror::Class> objlock(driver_->self_, linked_class);
  // Mark the class as initialized.
  CHECK(old_class->IsResolved())
      << "Attempting to redefine an unresolved class " << old_class->PrettyClass()
      << " status=" << old_class->GetStatus();
  CHECK(linked_class->IsResolved());
  if (old_class->ShouldSkipHiddenApiChecks()) {
    // Match skip hiddenapi flag
    linked_class->SetSkipHiddenApiChecks();
  }
  if (old_class->IsInitialized()) {
    // We already verified the class earlier. No need to do it again.
    linker->ForceClassInitialized(driver_->self_, linked_class);
  } else if (old_class->GetStatus() > linked_class->GetStatus()) {
    // We want to match the old status.
    art::mirror::Class::SetStatus(linked_class, old_class->GetStatus(), driver_->self_);
  }
  // Make sure we have ext-data space for method & field ids. We won't know if we need them until
  // it's too late to create them.
  // TODO We might want to remove these arrays if they're not needed.
  if (!art::mirror::Class::EnsureInstanceFieldIds(linked_class) ||
      !art::mirror::Class::EnsureStaticFieldIds(linked_class) ||
      !art::mirror::Class::EnsureMethodIds(linked_class)) {
    driver_->self_->AssertPendingOOMException();
    driver_->self_->ClearException();
    RecordFailure(
        ERR(OUT_OF_MEMORY),
        "Unable to allocate jni-id arrays for redefinition of " + old_class->PrettyClass());
    return nullptr;
  }
  // Finish setting up methods.
  linked_class->VisitMethods([&](art::ArtMethod* m) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(m, /* aot_code= */ nullptr);
    m->SetNotIntrinsic();
    DCHECK(m->IsCopied() || m->GetDeclaringClass() == linked_class.Get())
        << m->PrettyMethod()
        << " m->GetDeclaringClass(): " << m->GetDeclaringClass()->PrettyClass()
        << " != linked_class.Get(): " << linked_class->PrettyClass();
  }, art::kRuntimePointerSize);
  if (art::kIsDebugBuild) {
    linked_class->VisitFields([&](art::ArtField* f) REQUIRES_SHARED(art::Locks::mutator_lock_) {
      DCHECK_EQ(f->GetDeclaringClass(), linked_class.Get());
    });
  }
  // Reset ClinitThreadId back to the thread that loaded the old class. This is needed if we are in
  // the middle of initializing a class.
  linked_class->SetClinitThreadId(old_class->GetClinitThreadId());
  return linked_class.Get();
}

void Redefiner::ClassRedefinition::UnregisterJvmtiBreakpoints() {
  BreakpointUtil::RemoveBreakpointsInClass(driver_->env_, GetMirrorClass().Ptr());
}

void Redefiner::UnregisterAllBreakpoints() {
  for (Redefiner::ClassRedefinition& redef : redefinitions_) {
    redef.UnregisterJvmtiBreakpoints();
  }
}

bool Redefiner::CheckAllRedefinitionAreValid() {
  for (Redefiner::ClassRedefinition& redef : redefinitions_) {
    if (!redef.CheckRedefinitionIsValid()) {
      return false;
    }
  }
  return true;
}

void Redefiner::RestoreObsoleteMethodMapsIfUnneeded(RedefinitionDataHolder& holder) {
  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
    data.GetRedefinition().RestoreObsoleteMethodMapsIfUnneeded(&data);
  }
}

void Redefiner::MarkStructuralChanges(RedefinitionDataHolder& holder) {
  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
    if (data.IsActuallyStructural()) {
      // A superclass was structural and it marked all subclasses already. No need to do anything.
      CHECK(!data.IsInitialStructural());
    } else if (data.GetRedefinition().IsStructuralRedefinition()) {
      data.SetActuallyStructural();
      data.SetInitialStructural();
      // Go over all potential subtypes and mark any that are actually subclasses as structural.
      for (RedefinitionDataIter sub_data = data + 1; sub_data != holder.end(); ++sub_data) {
        if (sub_data.GetRedefinition().GetMirrorClass()->IsSubClass(
                data.GetRedefinition().GetMirrorClass())) {
          sub_data.SetActuallyStructural();
        }
      }
    }
  }
}

bool Redefiner::EnsureAllClassAllocationsFinished(RedefinitionDataHolder& holder) {
  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
    if (!data.GetRedefinition().EnsureClassAllocationsFinished(&data)) {
      return false;
    }
  }
  return true;
}

bool Redefiner::CollectAndCreateNewInstances(RedefinitionDataHolder& holder) {
  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
    // Allocate the data this redefinition requires.
    if (!data.GetRedefinition().CollectAndCreateNewInstances(&data)) {
      return false;
    }
  }
  return true;
}

bool Redefiner::FinishAllNewClassAllocations(RedefinitionDataHolder& holder) {
  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
    // Allocate the data this redefinition requires.
    if (!data.GetRedefinition().FinishNewClassAllocations(holder, &data)) {
      return false;
    }
  }
  return true;
}

bool Redefiner::FinishAllRemainingCommonAllocations(RedefinitionDataHolder& holder) {
  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
    // Allocate the data this redefinition requires.
    if (!data.GetRedefinition().FinishRemainingCommonAllocations(&data)) {
      return false;
    }
  }
  return true;
}

void Redefiner::ClassRedefinition::ReleaseDexFile() {
  if (art::kIsDebugBuild) {
    art::Thread* self = art::Thread::Current();
    art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
    CHECK(cl->IsDexFileRegistered(self, *dex_file_));
  }
  dex_file_.release();  // NOLINT b/117926937
}

void Redefiner::ReleaseAllDexFiles() {
  for (Redefiner::ClassRedefinition& redef : redefinitions_) {
    redef.ReleaseDexFile();
  }
}

bool Redefiner::CheckAllClassesAreVerified(RedefinitionDataHolder& holder) {
  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
    if (!data.GetRedefinition().CheckVerification(data)) {
      return false;
    }
  }
  return true;
}

class ScopedDisableConcurrentAndMovingGc {
 public:
  ScopedDisableConcurrentAndMovingGc(art::gc::Heap* heap, art::Thread* self)
      : heap_(heap), self_(self) {
    if (heap_->IsGcConcurrentAndMoving()) {
      heap_->IncrementDisableMovingGC(self_);
    }
  }

  ~ScopedDisableConcurrentAndMovingGc() {
    if (heap_->IsGcConcurrentAndMoving()) {
      heap_->DecrementDisableMovingGC(self_);
    }
  }
 private:
  art::gc::Heap* heap_;
  art::Thread* self_;
};

class ClassDefinitionPauser : public art::ClassLoadCallback {
 public:
  explicit ClassDefinitionPauser(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_)
      : self_(self),
        is_running_(false),
        barrier_(0),
        release_mu_("SuspendClassDefinition lock", art::kGenericBottomLock),
        release_barrier_(0),
        release_cond_("SuspendClassDefinition condvar", release_mu_),
        count_(0),
        release_(false) {
    art::Locks::mutator_lock_->AssertSharedHeld(self_);
  }
  ~ClassDefinitionPauser() REQUIRES_SHARED(art::Locks::mutator_lock_) {
    art::Locks::mutator_lock_->AssertSharedHeld(self_);
    CHECK(release_) << "Must call Release()";
  }
  void Release() REQUIRES(art::Locks::mutator_lock_) {
    if (is_running_) {
      art::Locks::mutator_lock_->AssertExclusiveHeld(self_);
      uint32_t count;
      // Wake up everything.
      {
        art::MutexLock mu(self_, release_mu_);
        release_ = true;
        // We have an exclusive mutator so all threads must be suspended and therefore they've
        // either already incremented this count_ or they are stuck somewhere before it.
        count = count_;
        release_cond_.Broadcast(self_);
      }
      // Wait for all threads to leave this structs code.
      VLOG(plugin) << "Resuming " << count << " threads paused before class-allocation!";
      release_barrier_.Increment</*locks=*/art::Barrier::kAllowHoldingLocks>(self_, count);
    } else {
      release_ = true;
    }
  }
  void BeginDefineClass() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    art::Thread* this_thread = art::Thread::Current();
    if (this_thread == self_) {
      // Allow the redefining thread to do whatever.
      return;
    }
    if (this_thread->GetDefineClassCount() != 0) {
      // We are in the middle of a recursive define-class. Don't suspend now allow it to finish.
      VLOG(plugin) << "Recursive DefineClass in " << *this_thread
                   << " allowed to proceed despite class-def pause initiated by " << *self_;
      return;
    }
    // If we are suspended (no mutator-lock) then the pausing thread could do everything before the
    // count_++ including destroying this object, causing UAF/deadlock.
    art::Locks::mutator_lock_->AssertSharedHeld(this_thread);
    ++count_;
    art::ScopedThreadSuspension sts(this_thread, art::ThreadState::kSuspended);
    {
      art::MutexLock mu(this_thread, release_mu_);
      VLOG(plugin) << "Suspending " << *this_thread << " due to class definition. class-def pause "
                   << "initiated by " << *self_;
      while (!release_) {
        release_cond_.Wait(this_thread);
      }
    }
    release_barrier_.Pass(this_thread);
  }

  void EndDefineClass() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    art::Thread* this_thread = art::Thread::Current();
    if (this_thread == self_) {
      // Allow the redefining thread to do whatever.
      return;
    }
    if (this_thread->GetDefineClassCount() == 0) {
      // We are done with defining classes.
      barrier_.Pass(this_thread);
    }
  }

  void ClassLoad(art::Handle<art::mirror::Class> klass ATTRIBUTE_UNUSED) override {}
  void ClassPrepare(art::Handle<art::mirror::Class> klass1 ATTRIBUTE_UNUSED,
                    art::Handle<art::mirror::Class> klass2 ATTRIBUTE_UNUSED) override {}

  void SetRunning() {
    is_running_ = true;
  }
  void WaitFor(uint32_t t) REQUIRES(!art::Locks::mutator_lock_) {
    barrier_.Increment(self_, t);
  }

 private:
  art::Thread* self_;
  bool is_running_;
  art::Barrier barrier_;
  art::Mutex release_mu_;
  art::Barrier release_barrier_;
  art::ConditionVariable release_cond_;
  std::atomic<uint32_t> count_;
  bool release_;
};

class ScopedSuspendClassLoading {
 public:
  ScopedSuspendClassLoading(art::Thread* self, art::Runtime* runtime, RedefinitionDataHolder& h)
      REQUIRES_SHARED(art::Locks::mutator_lock_)
      : self_(self), runtime_(runtime), pauser_() {
    if (std::any_of(h.begin(), h.end(), [](auto r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
          return r.GetRedefinition().IsStructuralRedefinition();
        })) {
      VLOG(plugin) << "Pausing Class loading for structural redefinition.";
      pauser_.emplace(self);
      {
        art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
        uint32_t in_progress_defines = 0;
        {
          art::ScopedSuspendAll ssa(__FUNCTION__);
          pauser_->SetRunning();
          runtime_->GetRuntimeCallbacks()->AddClassLoadCallback(&pauser_.value());
          art::MutexLock mu(self_, *art::Locks::thread_list_lock_);
          runtime_->GetThreadList()->ForEach([&](art::Thread* t) {
            if (t != self_ && t->GetDefineClassCount() != 0) {
              in_progress_defines++;
            }
          });
          VLOG(plugin) << "Waiting for " << in_progress_defines
                       << " in progress class-loads to finish";
        }
        pauser_->WaitFor(in_progress_defines);
      }
    }
  }
  ~ScopedSuspendClassLoading() {
    if (pauser_.has_value()) {
      art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
      art::ScopedSuspendAll ssa(__FUNCTION__);
      pauser_->Release();
      runtime_->GetRuntimeCallbacks()->RemoveClassLoadCallback(&pauser_.value());
    }
  }

 private:
  art::Thread* self_;
  art::Runtime* runtime_;
  std::optional<ClassDefinitionPauser> pauser_;
};

class ScopedSuspendAllocations {
 public:
  ScopedSuspendAllocations(art::Runtime* runtime, RedefinitionDataHolder& h)
      REQUIRES_SHARED(art::Locks::mutator_lock_)
      : paused_(false) {
    if (std::any_of(h.begin(),
                    h.end(),
                    [](auto r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
                      return r.GetRedefinition().IsStructuralRedefinition();
                    })) {
      VLOG(plugin) << "Pausing allocations for structural redefinition.";
      paused_ = true;
      AllocationManager::Get()->PauseAllocations(art::Thread::Current());
      // Collect garbage so we don't need to recreate as much.
      runtime->GetHeap()->CollectGarbage(/*clear_soft_references=*/false);
    }
  }

  ~ScopedSuspendAllocations() REQUIRES_SHARED(art::Locks::mutator_lock_) {
    if (paused_) {
      AllocationManager::Get()->ResumeAllocations(art::Thread::Current());
    }
  }

 private:
  bool paused_;

  DISALLOW_COPY_AND_ASSIGN(ScopedSuspendAllocations);
};

jvmtiError Redefiner::Run() {
  art::StackHandleScope<1> hs(self_);
  // Sort the redefinitions_ array topologically by class. This makes later steps easier since we
  // know that every class precedes all of its supertypes.
  std::sort(redefinitions_.begin(),
            redefinitions_.end(),
            [&](auto& l, auto& r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
              return CompareClasses(l.GetMirrorClass(), r.GetMirrorClass());
            });
  // Allocate an array to hold onto all java temporary objects associated with this
  // redefinition. We will let this be collected after the end of this function.
  RedefinitionDataHolder holder(&hs, runtime_, self_, &redefinitions_);
  if (holder.IsNull()) {
    self_->AssertPendingOOMException();
    self_->ClearException();
    RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate storage for temporaries");
    return result_;
  }

  // First we just allocate the ClassExt and its fields that we need. These can be updated
  // atomically without any issues (since we allocate the map arrays as empty).
  if (!CheckAllRedefinitionAreValid()) {
    return result_;
  }
  // Mark structural changes.
  MarkStructuralChanges(holder);
  // Now we pause class loading. If we are doing a structural redefinition we will need to get an
  // accurate picture of the classes loaded and having loads in the middle would make that
  // impossible. This only pauses class-loading if we actually have at least one structural
  // redefinition.
  ScopedSuspendClassLoading suspend_class_load(self_, runtime_, holder);
  if (!EnsureAllClassAllocationsFinished(holder) ||
      !FinishAllRemainingCommonAllocations(holder) ||
      !FinishAllNewClassAllocations(holder) ||
      !CheckAllClassesAreVerified(holder)) {
    return result_;
  }

  ScopedSuspendAllocations suspend_alloc(runtime_, holder);
  if (!CollectAndCreateNewInstances(holder)) {
    return result_;
  }

  // At this point we can no longer fail without corrupting the runtime state.
  for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
    art::ClassLinker* cl = runtime_->GetClassLinker();
    if (data.GetSourceClassLoader() == nullptr) {
      // AppendToBootClassPath includes dex file registration.
      const art::DexFile& dex_file = data.GetRedefinition().GetDexFile();
      runtime_->AppendToBootClassPath(
          dex_file.GetLocation(), dex_file.GetLocation(), {{&dex_file, data.GetNewDexCache()}});
    } else {
      cl->RegisterExistingDexCache(data.GetNewDexCache(), data.GetSourceClassLoader());
    }
    DCHECK_EQ(cl->FindDexCache(self_, data.GetRedefinition().GetDexFile()), data.GetNewDexCache());
  }
  UnregisterAllBreakpoints();

  {
    // Disable GC and wait for it to be done if we are a moving GC.  This is fine since we are done
    // allocating so no deadlocks.
    ScopedDisableConcurrentAndMovingGc sdcamgc(runtime_->GetHeap(), self_);

    // Do transition to final suspension
    // TODO We might want to give this its own suspended state!
    // TODO This isn't right. We need to change state without any chance of suspend ideally!
    art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
    art::ScopedSuspendAll ssa("Final installation of redefined Classes!", /*long_suspend=*/true);
    for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
      art::ScopedAssertNoThreadSuspension nts("Updating runtime objects for redefinition");
      ClassRedefinition& redef = data.GetRedefinition();
      if (data.GetSourceClassLoader() != nullptr) {
        ClassLoaderHelper::UpdateJavaDexFile(data.GetJavaDexFile(), data.GetNewDexFileCookie());
      }
      redef.UpdateClass(data);
    }
    RestoreObsoleteMethodMapsIfUnneeded(holder);
    // TODO We should check for if any of the redefined methods are intrinsic methods here and, if
    // any are, force a full-world deoptimization before finishing redefinition. If we don't do this
    // then methods that have been jitted prior to the current redefinition being applied might
    // continue to use the old versions of the intrinsics!
    // TODO Do the dex_file release at a more reasonable place. This works but it muddles who really
    // owns the DexFile and when ownership is transferred.
    ReleaseAllDexFiles();
  }
  return OK;
}

void Redefiner::ClassRedefinition::UpdateMethods(art::ObjPtr<art::mirror::Class> mclass,
                                                 const art::dex::ClassDef& class_def) {
  art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
  art::PointerSize image_pointer_size = linker->GetImagePointerSize();
  const art::dex::TypeId& declaring_class_id = dex_file_->GetTypeId(class_def.class_idx_);
  const art::DexFile& old_dex_file = mclass->GetDexFile();
  // Update methods.
  for (art::ArtMethod& method : mclass->GetDeclaredMethods(image_pointer_size)) {
    const art::dex::StringId* new_name_id = dex_file_->FindStringId(method.GetName());
    art::dex::TypeIndex method_return_idx =
        dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(method.GetReturnTypeDescriptor()));
    const auto* old_type_list = method.GetParameterTypeList();
    std::vector<art::dex::TypeIndex> new_type_list;
    for (uint32_t i = 0; old_type_list != nullptr && i < old_type_list->Size(); i++) {
      new_type_list.push_back(
          dex_file_->GetIndexForTypeId(
              *dex_file_->FindTypeId(
                  old_dex_file.GetTypeDescriptor(
                      old_dex_file.GetTypeId(
                          old_type_list->GetTypeItem(i).type_idx_)))));
    }
    const art::dex::ProtoId* proto_id = dex_file_->FindProtoId(method_return_idx, new_type_list);
    CHECK(proto_id != nullptr || old_type_list == nullptr);
    const art::dex::MethodId* method_id = dex_file_->FindMethodId(declaring_class_id,
                                                                  *new_name_id,
                                                                  *proto_id);
    CHECK(method_id != nullptr);
    uint32_t dex_method_idx = dex_file_->GetIndexForMethodId(*method_id);
    method.SetDexMethodIndex(dex_method_idx);
    driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(&method, /*aot_code=*/ nullptr);
    if (method.HasCodeItem()) {
      method.SetCodeItem(
          dex_file_->GetCodeItem(dex_file_->FindCodeItemOffset(class_def, dex_method_idx)),
          dex_file_->IsCompactDexFile());
    }
    // Clear all the intrinsics related flags.
    method.SetNotIntrinsic();
  }
}

void Redefiner::ClassRedefinition::UpdateFields(art::ObjPtr<art::mirror::Class> mclass) {
  // TODO The IFields & SFields pointers should be combined like the methods_ arrays were.
  for (auto fields_iter : {mclass->GetIFields(), mclass->GetSFields()}) {
    for (art::ArtField& field : fields_iter) {
      std::string declaring_class_name;
      const art::dex::TypeId* new_declaring_id =
          dex_file_->FindTypeId(field.GetDeclaringClass()->GetDescriptor(&declaring_class_name));
      const art::dex::StringId* new_name_id = dex_file_->FindStringId(field.GetName());
      const art::dex::TypeId* new_type_id = dex_file_->FindTypeId(field.GetTypeDescriptor());
      CHECK(new_name_id != nullptr && new_type_id != nullptr && new_declaring_id != nullptr);
      const art::dex::FieldId* new_field_id =
          dex_file_->FindFieldId(*new_declaring_id, *new_name_id, *new_type_id);
      CHECK(new_field_id != nullptr);
      uint32_t new_field_index = dex_file_->GetIndexForFieldId(*new_field_id);
      // We only need to update the index since the other data in the ArtField cannot be updated.
      field.SetDexFieldIndex(new_field_index);
    }
  }
}

void Redefiner::ClassRedefinition::CollectNewFieldAndMethodMappings(
    const RedefinitionDataIter& data,
    std::map<art::ArtMethod*, art::ArtMethod*>* method_map,
    std::map<art::ArtField*, art::ArtField*>* field_map) {
  for (auto [new_cls, old_cls] :
       art::ZipLeft(data.GetNewClasses()->Iterate(), data.GetOldClasses()->Iterate())) {
    for (art::ArtField& f : old_cls->GetSFields()) {
      (*field_map)[&f] = new_cls->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor());
    }
    for (art::ArtField& f : old_cls->GetIFields()) {
      (*field_map)[&f] = new_cls->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor());
    }
    auto new_methods = new_cls->GetMethods(art::kRuntimePointerSize);
    for (art::ArtMethod& m : old_cls->GetMethods(art::kRuntimePointerSize)) {
      // No support for finding methods in this way since it's generally not needed. Just do it the
      // easy way.
      auto nm_iter = std::find_if(
          new_methods.begin(),
          new_methods.end(),
          [&](art::ArtMethod& cand) REQUIRES_SHARED(art::Locks::mutator_lock_) {
            return cand.GetNameView() == m.GetNameView() && cand.GetSignature() == m.GetSignature();
          });
      CHECK(nm_iter != new_methods.end())
          << "Could not find redefined version of " << m.PrettyMethod();
      (*method_map)[&m] = &(*nm_iter);
    }
  }
}

static void CopyField(art::ObjPtr<art::mirror::Object> target,
                      art::ArtField* new_field,
                      art::ObjPtr<art::mirror::Object> source,
                      art::ArtField& old_field) REQUIRES(art::Locks::mutator_lock_) {
  art::Primitive::Type ftype = old_field.GetTypeAsPrimitiveType();
  CHECK_EQ(ftype, new_field->GetTypeAsPrimitiveType())
      << old_field.PrettyField() << " vs " << new_field->PrettyField();
  if (ftype == art::Primitive::kPrimNot) {
    new_field->SetObject<false>(target, old_field.GetObject(source));
  } else {
    switch (ftype) {
#define UPDATE_FIELD(TYPE)                                            \
  case art::Primitive::kPrim##TYPE:                                   \
    new_field->Set##TYPE<false>(target, old_field.Get##TYPE(source)); \
    break
      UPDATE_FIELD(Int);
      UPDATE_FIELD(Float);
      UPDATE_FIELD(Long);
      UPDATE_FIELD(Double);
      UPDATE_FIELD(Short);
      UPDATE_FIELD(Char);
      UPDATE_FIELD(Byte);
      UPDATE_FIELD(Boolean);
      case art::Primitive::kPrimNot:
      case art::Primitive::kPrimVoid:
        LOG(FATAL) << "Unexpected field with type " << ftype << " found!";
        UNREACHABLE();
#undef UPDATE_FIELD
    }
  }
}

static void CopyFields(bool is_static,
                       art::ObjPtr<art::mirror::Object> target,
                       art::ObjPtr<art::mirror::Class> target_class,
                       art::ObjPtr<art::mirror::Object> source,
                       art::ObjPtr<art::mirror::Class> source_class)
    REQUIRES(art::Locks::mutator_lock_) {
  DCHECK(!source_class->IsObjectClass() && !target_class->IsObjectClass())
      << "Should not be overriding object class fields. Target: " << target_class->PrettyClass()
      << " Source: " << source_class->PrettyClass();
  for (art::ArtField& f : (is_static ? source_class->GetSFields() : source_class->GetIFields())) {
    art::ArtField* new_field =
        (is_static ? target_class->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor())
                   : target_class->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor()));
    CHECK(new_field != nullptr) << "could not find new version of " << f.PrettyField();
    CopyField(target, new_field, source, f);
  }
  if (!is_static && !target_class->GetSuperClass()->IsObjectClass()) {
    CopyFields(
        is_static, target, target_class->GetSuperClass(), source, source_class->GetSuperClass());
  }
}

static void ClearField(art::ObjPtr<art::mirror::Object> target, art::ArtField& field)
    REQUIRES(art::Locks::mutator_lock_) {
  art::Primitive::Type ftype = field.GetTypeAsPrimitiveType();
  if (ftype == art::Primitive::kPrimNot) {
    field.SetObject<false>(target, nullptr);
  } else {
    switch (ftype) {
#define UPDATE_FIELD(TYPE)             \
  case art::Primitive::kPrim##TYPE:    \
    field.Set##TYPE<false>(target, 0); \
    break
      UPDATE_FIELD(Int);
      UPDATE_FIELD(Float);
      UPDATE_FIELD(Long);
      UPDATE_FIELD(Double);
      UPDATE_FIELD(Short);
      UPDATE_FIELD(Char);
      UPDATE_FIELD(Byte);
      UPDATE_FIELD(Boolean);
      case art::Primitive::kPrimNot:
      case art::Primitive::kPrimVoid:
        LOG(FATAL) << "Unexpected field with type " << ftype << " found!";
        UNREACHABLE();
#undef UPDATE_FIELD
    }
  }
}

static void ClearFields(bool is_static,
                        art::ObjPtr<art::mirror::Object> target,
                        art::ObjPtr<art::mirror::Class> target_class)
    REQUIRES(art::Locks::mutator_lock_) {
  DCHECK(!target_class->IsObjectClass());
  for (art::ArtField& f : (is_static ? target_class->GetSFields() : target_class->GetIFields())) {
    ClearField(target, f);
  }
  if (!is_static && !target_class->GetSuperClass()->IsObjectClass()) {
    ClearFields(is_static, target, target_class->GetSuperClass());
  }
}

static void CopyAndClearFields(bool is_static,
                               art::ObjPtr<art::mirror::Object> target,
                               art::ObjPtr<art::mirror::Class> target_class,
                               art::ObjPtr<art::mirror::Object> source,
                               art::ObjPtr<art::mirror::Class> source_class)
    REQUIRES(art::Locks::mutator_lock_) {
  // Copy all non-j.l.Object fields
  CopyFields(is_static, target, target_class, source, source_class);
  // Copy the lock-word.
  target->SetLockWord(source->GetLockWord(false), false);
  // Clear (reset) the old one.
  source->SetLockWord(art::LockWord::Default(), false);
  art::WriteBarrier::ForEveryFieldWrite(target);

  // Clear the fields from the old class. We don't need it anymore.
  ClearFields(is_static, source, source_class);
  art::WriteBarrier::ForEveryFieldWrite(source);
}

void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDataIter& holder) {
  DCHECK(holder.IsActuallyStructural());
  DCHECK(holder.IsInitialStructural());
  // LETS GO. We've got all new class structures so no need to do all the updating of the stacks.
  // Instead we need to update everything else.
  // Just replace the class and be done with it.
  art::Locks::mutator_lock_->AssertExclusiveHeld(driver_->self_);
  art::ClassLinker* cl = driver_->runtime_->GetClassLinker();
  art::ScopedAssertNoThreadSuspension sants(__FUNCTION__);
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> new_classes(holder.GetNewClasses());
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> old_classes(holder.GetOldClasses());
  // Collect mappings from old to new fields/methods
  std::map<art::ArtMethod*, art::ArtMethod*> method_map;
  std::map<art::ArtField*, art::ArtField*> field_map;
  CollectNewFieldAndMethodMappings(holder, &method_map, &field_map);
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> new_instances(
      holder.GetNewInstanceObjects());
  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> old_instances(
      holder.GetOldInstanceObjects());
  // Once we do the ReplaceReferences old_classes will have the new_classes in it. We want to keep
  // ahold of the old classes so copy them now.
  std::vector<art::ObjPtr<art::mirror::Class>> old_classes_vec(old_classes->Iterate().begin(),
                                                               old_classes->Iterate().end());
  // Copy over the static fields of the class and all the instance fields.
  for (auto [new_class, old_class] : art::ZipLeft(new_classes->Iterate(), old_classes->Iterate())) {
    CHECK(!new_class.IsNull());
    CHECK(!old_class.IsNull());
    CHECK(!old_class->IsErroneous());
    if (old_class->GetStatus() > new_class->GetStatus()) {
      // Some verification/initialization step happened during interval between
      // creating the new class and now. Just copy the new status.
      new_class->SetStatusLocked(old_class->GetStatus());
    }
    CopyAndClearFields(true, new_class, new_class, old_class, old_class);
  }

  // Copy and clear the fields of the old-instances.
  for (auto [new_instance, old_instance] :
       art::ZipLeft(new_instances->Iterate(), old_instances->Iterate())) {
    CopyAndClearFields(/*is_static=*/false,
                       new_instance,
                       new_instance->GetClass(),
                       old_instance,
                       old_instance->GetClass());
  }
  // Mark old class and methods obsolete. Copy over any native implementation as well.
  for (auto [old_class, new_class] : art::ZipLeft(old_classes->Iterate(), new_classes->Iterate())) {
    old_class->SetObsoleteObject();
    // Mark methods obsolete and copy native implementation. We need to wait
    // until later to actually clear the jit data. We copy the native
    // implementation here since we don't want to race with any threads doing
    // RegisterNatives.
    for (art::ArtMethod& m : old_class->GetMethods(art::kRuntimePointerSize)) {
      if (m.IsNative()) {
        art::ArtMethod* new_method =
            new_class->FindClassMethod(m.GetNameView(), m.GetSignature(), art::kRuntimePointerSize);
        DCHECK(new_class->GetMethodsSlice(art::kRuntimePointerSize).Contains(new_method))
            << "Could not find method " << m.PrettyMethod() << " declared in new class!";
        DCHECK(new_method->IsNative());
        new_method->SetEntryPointFromJni(m.GetEntryPointFromJni());
      }
      m.SetIsObsolete();
      cl->SetEntryPointsForObsoleteMethod(&m);
      if (m.IsInvokable()) {
        m.SetDontCompile();
      }
    }
  }
  // Update live pointers in ART code.
  auto could_change_resolution_of = [&](auto* field_or_method,
                                        const auto& info) REQUIRES(art::Locks::mutator_lock_) {
    constexpr bool is_method = std::is_same_v<art::ArtMethod*, decltype(field_or_method)>;
    static_assert(is_method || std::is_same_v<art::ArtField*, decltype(field_or_method)>,
                  "Input is not field or method!");
    // Only dex-cache is used for resolution
    if (LIKELY(info.GetType() != art::ReflectionSourceType::kSourceDexCacheResolvedField &&
               info.GetType() != art::ReflectionSourceType::kSourceDexCacheResolvedMethod)) {
      return false;
    }
    if constexpr (is_method) {
      // Only direct methods are used without further indirection through a vtable/IFTable.
      // Constructors cannot be shadowed.
      if (LIKELY(!field_or_method->IsDirect() || field_or_method->IsConstructor())) {
        return false;
      }
    } else {
      // Only non-private fields can be shadowed in a manner that's visible.
      if (LIKELY(field_or_method->IsPrivate())) {
        return false;
      }
    }
    // We can only shadow things from our superclasses
    auto orig_classes_iter = old_classes->Iterate();
    auto replacement_classes_iter = new_classes->Iterate();
    art::ObjPtr<art::mirror::Class> f_or_m_class = field_or_method->GetDeclaringClass();
    if (LIKELY(!f_or_m_class->IsAssignableFrom(holder.GetMirrorClass()) &&
               std::find(orig_classes_iter.begin(), orig_classes_iter.end(), f_or_m_class) ==
                   orig_classes_iter.end())) {
      return false;
    }
    if constexpr (is_method) {
      return std::any_of(
          replacement_classes_iter.begin(),
          replacement_classes_iter.end(),
          [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
            auto direct_methods = cand->GetDirectMethods(art::kRuntimePointerSize);
            return std::find_if(direct_methods.begin(),
                                direct_methods.end(),
                                [&](art::ArtMethod& m) REQUIRES(art::Locks::mutator_lock_) {
                                  return UNLIKELY(m.HasSameNameAndSignature(field_or_method));
                                }) != direct_methods.end();
          });
    } else {
      auto pred = [&](art::ArtField& f) REQUIRES(art::Locks::mutator_lock_) {
        return std::string_view(f.GetName()) == std::string_view(field_or_method->GetName()) &&
               std::string_view(f.GetTypeDescriptor()) ==
                   std::string_view(field_or_method->GetTypeDescriptor());
      };
      if (field_or_method->IsStatic()) {
        return std::any_of(
            replacement_classes_iter.begin(),
            replacement_classes_iter.end(),
            [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
              auto sfields = cand->GetSFields();
              return std::find_if(sfields.begin(), sfields.end(), pred) != sfields.end();
            });
      } else {
        return std::any_of(
            replacement_classes_iter.begin(),
            replacement_classes_iter.end(),
            [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
              auto ifields = cand->GetIFields();
              return std::find_if(ifields.begin(), ifields.end(), pred) != ifields.end();
            });
      }
    }
  };
  // TODO Performing 2 stack-walks back to back isn't the greatest. We might want to try to combine
  // it with the one ReplaceReferences does. Doing so would be rather complicated though.
  driver_->runtime_->VisitReflectiveTargets(
      [&](art::ArtField* f, const auto& info) REQUIRES(art::Locks::mutator_lock_) {
        DCHECK(f != nullptr) << info;
        auto it = field_map.find(f);
        if (UNLIKELY(could_change_resolution_of(f, info))) {
          // Dex-cache Resolution might change. Just clear the resolved value.
          VLOG(plugin) << "Clearing resolution " << info << " for (field) " << f->PrettyField();
          return static_cast<art::ArtField*>(nullptr);
        } else if (it != field_map.end()) {
          VLOG(plugin) << "Updating " << info << " object for (field) "
                       << it->second->PrettyField();
          return it->second;
        }
        return f;
      },
      [&](art::ArtMethod* m, const auto& info) REQUIRES(art::Locks::mutator_lock_) {
        DCHECK(m != nullptr) << info;
        auto it = method_map.find(m);
        if (UNLIKELY(could_change_resolution_of(m, info))) {
          // Dex-cache Resolution might change. Just clear the resolved value.
          VLOG(plugin) << "Clearing resolution " << info << " for (method) " << m->PrettyMethod();
          return static_cast<art::ArtMethod*>(nullptr);
        } else if (it != method_map.end()) {
          VLOG(plugin) << "Updating " << info << " object for (method) "
                      << it->second->PrettyMethod();
          return it->second;
        }
        return m;
      });

  // Force every frame of every thread to deoptimize (any frame might have eg offsets compiled in).
  driver_->runtime_->GetInstrumentation()->DeoptimizeAllThreadFrames();

  std::unordered_map<art::ObjPtr<art::mirror::Object>,
                     art::ObjPtr<art::mirror::Object>,
                     art::HashObjPtr> map;
  for (auto [new_class, old_class] : art::ZipLeft(new_classes->Iterate(), old_classes->Iterate())) {
    map.emplace(old_class, new_class);
  }
  for (auto [new_instance, old_instance] :
       art::ZipLeft(new_instances->Iterate(), old_instances->Iterate())) {
    map.emplace(old_instance, new_instance);
    // Bare-bones check that the mapping is correct.
    CHECK(new_instance->GetClass() == map[old_instance->GetClass()]->AsClass())
        << new_instance->GetClass()->PrettyClass() << " vs "
        << map[old_instance->GetClass()]->AsClass()->PrettyClass();
  }

  // Actually perform the general replacement. This doesn't affect ArtMethod/ArtFields. It does
  // affect the declaring_class field of all the obsolete objects, which is unfortunate and needs to
  // be undone. This replaces the mirror::Class in 'holder' as well. It's magic!
  HeapExtensions::ReplaceReferences(driver_->self_, map);

  // Undo the replacement of old_class with new_class for the methods / fields on the old_class.
  // It is hard to ensure that we don't replace the declaring class of the old class field / methods
  // isn't impacted by ReplaceReferences. It is just simpler to undo the replacement here.
  std::for_each(
      old_classes_vec.cbegin(),
      old_classes_vec.cend(),
      [](art::ObjPtr<art::mirror::Class> orig) REQUIRES_SHARED(art::Locks::mutator_lock_) {
        orig->VisitMethods(
            [&](art::ArtMethod* method) REQUIRES_SHARED(art::Locks::mutator_lock_) {
              if (method->IsCopied()) {
                // Copied methods have interfaces as their declaring class.
                return;
              }
              method->SetDeclaringClass(orig);
            },
            art::kRuntimePointerSize);
        orig->VisitFields([&](art::ArtField* field) REQUIRES_SHARED(art::Locks::mutator_lock_) {
          field->SetDeclaringClass(orig);
        });
      });

  // Save the old class so that the JIT gc doesn't get confused by it being collected before the
  // jit code. This is also needed to keep the dex-caches of any obsolete methods live.
  for (auto [new_class, old_class] :
       art::ZipLeft(new_classes->Iterate(), art::MakeIterationRange(old_classes_vec))) {
    new_class->GetExtData()->SetObsoleteClass(old_class);
  }

  art::jit::Jit* jit = driver_->runtime_->GetJit();
  if (jit != nullptr) {
    // Clear jit.
    // TODO We might want to have some way to tell the JIT not to wait the kJitSamplesBatchSize
    // invokes to start compiling things again.
    jit->GetCodeCache()->InvalidateAllCompiledCode();
  }

  // Clear thread caches
  {
    // TODO We might be able to avoid doing this but given the rather unstructured nature of the
    // interpreter cache it's probably not worth the effort.
    art::MutexLock mu(driver_->self_, *art::Locks::thread_list_lock_);
    driver_->runtime_->GetThreadList()->ForEach(
        [](art::Thread* t) { t->GetInterpreterCache()->Clear(t); });
  }

  if (art::kIsDebugBuild) {
    // Just make sure we didn't screw up any of the now obsolete methods or fields. We need their
    // declaring-class to still be the obolete class
    std::for_each(
        old_classes_vec.cbegin(),
        old_classes_vec.cend(),
        [](art::ObjPtr<art::mirror::Class> orig) REQUIRES_SHARED(art::Locks::mutator_lock_) {
          orig->VisitMethods(
              [&](art::ArtMethod* method) REQUIRES_SHARED(art::Locks::mutator_lock_) {
                if (method->IsCopied()) {
                  // Copied methods have interfaces as their declaring class.
                  return;
                }
                DCHECK_EQ(method->GetDeclaringClass(), orig)
                    << method->GetDeclaringClass()->PrettyClass() << " vs " << orig->PrettyClass();
              },
              art::kRuntimePointerSize);
          orig->VisitFields([&](art::ArtField* field) REQUIRES_SHARED(art::Locks::mutator_lock_) {
            DCHECK_EQ(field->GetDeclaringClass(), orig)
                << field->GetDeclaringClass()->PrettyClass() << " vs " << orig->PrettyClass();
          });
        });
  }
}

// Redefines the class in place
void Redefiner::ClassRedefinition::UpdateClassInPlace(const RedefinitionDataIter& holder) {
  art::ObjPtr<art::mirror::Class> mclass(holder.GetMirrorClass());
  // TODO Rewrite so we don't do a stack walk for each and every class.
  FindAndAllocateObsoleteMethods(mclass);
  art::ObjPtr<art::mirror::DexCache> new_dex_cache(holder.GetNewDexCache());
  art::ObjPtr<art::mirror::Object> original_dex_file(holder.GetOriginalDexFile());
  DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
  const art::dex::ClassDef& class_def = dex_file_->GetClassDef(0);
  UpdateMethods(mclass, class_def);
  UpdateFields(mclass);

  art::ObjPtr<art::mirror::ClassExt> ext(mclass->GetExtData());
  CHECK(!ext.IsNull());
  ext->SetOriginalDexFile(original_dex_file);

  // If this is the first time the class is being redefined, store
  // the native DexFile pointer and initial ClassDef index in ClassExt.
  // This preserves the pointer for hiddenapi access checks which need
  // to read access flags from the initial DexFile.
  if (ext->GetPreRedefineDexFile() == nullptr) {
    ext->SetPreRedefineDexFile(&mclass->GetDexFile());
    ext->SetPreRedefineClassDefIndex(mclass->GetDexClassDefIndex());
  }

  // Update the class fields.
  // Need to update class last since the ArtMethod gets its DexFile from the class (which is needed
  // to call GetReturnTypeDescriptor and GetParameterTypeList above).
  mclass->SetDexCache(new_dex_cache.Ptr());
  mclass->SetDexClassDefIndex(dex_file_->GetIndexForClassDef(class_def));
  mclass->SetDexTypeIndex(dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(class_sig_.c_str())));

  // Notify the jit that all the methods in this class were redefined. Need to do this last since
  // the jit relies on the dex_file_ being correct (for native methods at least) to find the method
  // meta-data.
  art::jit::Jit* jit = driver_->runtime_->GetJit();
  if (jit != nullptr) {
    art::PointerSize image_pointer_size =
        driver_->runtime_->GetClassLinker()->GetImagePointerSize();
    auto code_cache = jit->GetCodeCache();
    // Non-invokable methods don't have any JIT data associated with them so we don't need to tell
    // the jit about them.
    for (art::ArtMethod& method : mclass->GetDeclaredMethods(image_pointer_size)) {
      if (method.IsInvokable()) {
        code_cache->NotifyMethodRedefined(&method);
      }
    }
  }
}

// Performs final updates to class for redefinition.
void Redefiner::ClassRedefinition::UpdateClass(const RedefinitionDataIter& holder) {
  CHECK(holder.IsInitialized());
  if (holder.IsInitialStructural()) {
    UpdateClassStructurally(holder);
  } else if (!holder.IsActuallyStructural()) {
    UpdateClassInPlace(holder);
  }
}

// Restores the old obsolete methods maps if it turns out they weren't needed (ie there were no new
// obsolete methods).
void Redefiner::ClassRedefinition::RestoreObsoleteMethodMapsIfUnneeded(
    const RedefinitionDataIter* cur_data) {
  if (cur_data->IsActuallyStructural()) {
    // We didn't touch these in this case.
    return;
  }
  art::ObjPtr<art::mirror::Class> klass = GetMirrorClass();
  art::ObjPtr<art::mirror::ClassExt> ext = klass->GetExtData();
  art::ObjPtr<art::mirror::PointerArray> methods = ext->GetObsoleteMethods();
  art::ObjPtr<art::mirror::PointerArray> old_methods = cur_data->GetOldObsoleteMethods();
  int32_t old_length = old_methods == nullptr ? 0 : old_methods->GetLength();
  int32_t expected_length =
      old_length + klass->NumDirectMethods() + klass->NumDeclaredVirtualMethods();
  // Check to make sure we are only undoing this one.
  if (methods.IsNull()) {
    // No new obsolete methods! We can get rid of the maps.
    ext->SetObsoleteArrays(cur_data->GetOldObsoleteMethods(), cur_data->GetOldDexCaches());
  } else if (expected_length == methods->GetLength()) {
    for (int32_t i = 0; i < expected_length; i++) {
      art::ArtMethod* expected = nullptr;
      if (i < old_length) {
        expected = old_methods->GetElementPtrSize<art::ArtMethod*>(i, art::kRuntimePointerSize);
      }
      if (methods->GetElementPtrSize<art::ArtMethod*>(i, art::kRuntimePointerSize) != expected) {
        // We actually have some new obsolete methods. Just abort since we cannot safely shrink the
        // obsolete methods array.
        return;
      }
    }
    // No new obsolete methods! We can get rid of the maps.
    ext->SetObsoleteArrays(cur_data->GetOldObsoleteMethods(), cur_data->GetOldDexCaches());
  }
}

// This function does all (java) allocations we need to do for the Class being redefined.
// TODO Change this name maybe?
bool Redefiner::ClassRedefinition::EnsureClassAllocationsFinished(
    /*out*/RedefinitionDataIter* cur_data) {
  art::StackHandleScope<2> hs(driver_->self_);
  art::Handle<art::mirror::Class> klass(hs.NewHandle(
      driver_->self_->DecodeJObject(klass_)->AsClass()));
  if (klass == nullptr) {
    RecordFailure(ERR(INVALID_CLASS), "Unable to decode class argument!");
    return false;
  }
  // Allocate the classExt
  art::Handle<art::mirror::ClassExt> ext =
      hs.NewHandle(art::mirror::Class::EnsureExtDataPresent(klass, driver_->self_));
  if (ext == nullptr) {
    // No memory. Clear exception (it's not useful) and return error.
    driver_->self_->AssertPendingOOMException();
    driver_->self_->ClearException();
    RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate ClassExt");
    return false;
  }
  if (!cur_data->IsActuallyStructural()) {
    CHECK(!IsStructuralRedefinition());
    // First save the old values of the 2 arrays that make up the obsolete methods maps. Then
    // allocate the 2 arrays that make up the obsolete methods map. Since the contents of the arrays
    // are only modified when all threads (other than the modifying one) are suspended we don't need
    // to worry about missing the unsynchronized writes to the array. We do synchronize when setting
    // it however, since that can happen at any time.
    cur_data->SetOldObsoleteMethods(ext->GetObsoleteMethods());
    cur_data->SetOldDexCaches(ext->GetObsoleteDexCaches());
    // FIXME: The `ClassExt::ExtendObsoleteArrays()` is non-atomic and does not ensure proper
    // memory visibility, so it can race with `ArtMethod::GetObsoleteDexCache()`.
    // We should allocate the new arrays here but record it in the redefinition data and set the
    // new arrays in `ClassExt` later with all other threads suspended.
    if (!art::mirror::ClassExt::ExtendObsoleteArrays(
            ext, driver_->self_, klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size())) {
      // OOM. Clear exception and return error.
      driver_->self_->AssertPendingOOMException();
      driver_->self_->ClearException();
      RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate/extend obsolete methods map");
      return false;
    }
  }
  return true;
}

}  // namespace openjdkjvmti
