/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "jni_id_manager.h"

#include <algorithm>
#include <cstdint>
#include <type_traits>

#include "android-base/macros.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/enums.h"
#include "base/globals.h"
#include "base/locks.h"
#include "base/mutex.h"
#include "class_root-inl.h"
#include "gc/allocation_listener.h"
#include "gc/heap.h"
#include "jni/jni_internal.h"
#include "jni_id_type.h"
#include "mirror/array-inl.h"
#include "mirror/array.h"
#include "mirror/class-alloc-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class.h"
#include "mirror/class_ext-inl.h"
#include "mirror/object-inl.h"
#include "obj_ptr-inl.h"
#include "reflective_handle_scope-inl.h"
#include "reflective_handle_scope.h"
#include "reflective_value_visitor.h"
#include "thread-inl.h"
#include "thread.h"

namespace art {
namespace jni {

constexpr bool kTraceIds = false;

// TODO This whole thing could be done lock & wait free (since we never remove anything from the
// ids list). It's not clear this would be worthwile though.

namespace {

static constexpr size_t IdToIndex(uintptr_t id) {
  return id >> 1;
}

static constexpr uintptr_t IndexToId(size_t index) {
  return (index << 1) + 1;
}

static bool CanUseIdArrays(ArtMethod* t) {
  // We cannot use ID arrays from the ClassExt object for obsolete and default conflict methods. The
  // ID arrays hold an ID corresponding to the methods in the methods_list. Obsolete methods aren't
  // in the method list. For default conflicting methods it is difficult to find the class that
  // contains the copied method, so we omit using ID arrays. For Default conflicting methods we
  // cannot use the canonical method because canonicalizing would return a method from one of the
  // interface classes. If we use that method ID and invoke it via the CallNonVirtual JNI interface,
  // it wouldn't throw the expected ICCE.
  return !(t->IsObsolete() || t->IsDefaultConflicting());
}

template <typename ArtType>
ObjPtr<mirror::PointerArray> GetIds(ObjPtr<mirror::Class> k, ArtType* t)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ObjPtr<mirror::Object> ret;
  if constexpr (std::is_same_v<ArtType, ArtField>) {
    ret = t->IsStatic() ? k->GetStaticFieldIds() : k->GetInstanceFieldIds();
  } else {
    ret = CanUseIdArrays(t) ? k->GetMethodIds() : nullptr;
  }
  DCHECK(ret.IsNull() || ret->IsArrayInstance()) << "Should have bailed out early!";
  if (kIsDebugBuild && !ret.IsNull()) {
    if (kRuntimePointerSize == PointerSize::k32) {
      CHECK(ret->IsIntArray());
    } else {
      CHECK(ret->IsLongArray());
    }
  }
  return down_cast<mirror::PointerArray*>(ret.Ptr());
}

template <typename ArtType>
bool ShouldReturnPointer(ObjPtr<mirror::Class> klass, ArtType* t)
    REQUIRES_SHARED(Locks::mutator_lock_);

template <>
bool ShouldReturnPointer(ObjPtr<mirror::Class> klass, ArtMethod* t ATTRIBUTE_UNUSED) {
  ObjPtr<mirror::ClassExt> ext(klass->GetExtData());
  if (ext.IsNull()) {
    return true;
  }
  ObjPtr<mirror::Object> arr = ext->GetJMethodIDs();
  return arr.IsNull() || !arr->IsArrayInstance();
}

template<>
bool ShouldReturnPointer(ObjPtr<mirror::Class> klass, ArtField* t) {
  ObjPtr<mirror::ClassExt> ext(klass->GetExtData());
  if (ext.IsNull()) {
    return true;
  }
  ObjPtr<mirror::Object> arr = t->IsStatic() ? ext->GetStaticJFieldIDs()
                                             : ext->GetInstanceJFieldIDs();
  return arr.IsNull() || !arr->IsArrayInstance();
}


// Forces the appropriate id array to be present if possible. Returns true if allocation was
// attempted but failed.
template <typename ArtType>
bool EnsureIdsArray(Thread* self, ObjPtr<mirror::Class> k, ArtType* t)
    REQUIRES_SHARED(Locks::mutator_lock_);

template <>
bool EnsureIdsArray(Thread* self, ObjPtr<mirror::Class> k, ArtField* field) {
  ScopedExceptionStorage ses(self);
  StackHandleScope<1> hs(self);
  Handle<mirror::Class> h_k(hs.NewHandle(k));
  if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
    return false;
  } else {
    // NB This modifies the class to allocate the ClassExt and the ids array.
    field->IsStatic() ? mirror::Class::EnsureStaticFieldIds(h_k)
                      : mirror::Class::EnsureInstanceFieldIds(h_k);
  }
  if (self->IsExceptionPending()) {
    self->AssertPendingOOMException();
    ses.SuppressOldException("Failed to allocate maps for jmethodIDs. ");
    return true;
  }
  return false;
}

template <>
bool EnsureIdsArray(Thread* self, ObjPtr<mirror::Class> k, ArtMethod* method) {
  if (!CanUseIdArrays(method)) {
    if (kTraceIds) {
      LOG(INFO) << "jmethodID for Obsolete / Default conflicting method " << method->PrettyMethod()
                << " requested!";
    }
    // No ids array for obsolete methods. Just do a linear scan.
    return false;
  }
  StackHandleScope<1> hs(self);
  Handle<mirror::Class> h_k(hs.NewHandle(k));
  if (Locks::mutator_lock_->IsExclusiveHeld(self) || !Locks::mutator_lock_->IsSharedHeld(self)) {
    return false;
  } else {
    // NB This modifies the class to allocate the ClassExt and the ids array.
    mirror::Class::EnsureMethodIds(h_k);
  }
  if (self->IsExceptionPending()) {
    self->AssertPendingOOMException();
    return true;
  }
  return false;
}

template <typename ArtType>
size_t GetIdOffset(ObjPtr<mirror::Class> k, ArtType* t, PointerSize pointer_size)
    REQUIRES_SHARED(Locks::mutator_lock_);
template <>
size_t GetIdOffset(ObjPtr<mirror::Class> k, ArtField* f, PointerSize ptr_size ATTRIBUTE_UNUSED) {
  return f->IsStatic() ? k->GetStaticFieldIdOffset(f) : k->GetInstanceFieldIdOffset(f);
}
template <>
size_t GetIdOffset(ObjPtr<mirror::Class> k, ArtMethod* method, PointerSize pointer_size) {
  return CanUseIdArrays(method) ? k->GetMethodIdOffset(method, pointer_size) : -1;
}

// Calls the relevant PrettyMethod/PrettyField on the input.
template <typename ArtType>
std::string PrettyGeneric(ArtType t) REQUIRES_SHARED(Locks::mutator_lock_);
template <>
std::string PrettyGeneric(ArtMethod* f) {
  return f->PrettyMethod();
}
template <>
std::string PrettyGeneric(ReflectiveHandle<ArtMethod> f) {
  return f->PrettyMethod();
}
template <>
std::string PrettyGeneric(ArtField* f) {
  return f->PrettyField();
}
template <>
std::string PrettyGeneric(ReflectiveHandle<ArtField> f) {
  return f->PrettyField();
}

// Checks if the field or method can use the ID array from class extension.
template <typename ArtType>
bool CanUseIdArrays(ReflectiveHandle<ArtType> t) REQUIRES_SHARED(Locks::mutator_lock_);
template <>
bool CanUseIdArrays(ReflectiveHandle<ArtField> t ATTRIBUTE_UNUSED) {
  return true;
}
template <>
bool CanUseIdArrays(ReflectiveHandle<ArtMethod> t) {
  return CanUseIdArrays(t.Get());
}

// Get the canonical (non-copied) version of the field or method. Only relevant for methods.
template <typename ArtType>
ArtType* Canonicalize(ReflectiveHandle<ArtType> t) REQUIRES_SHARED(Locks::mutator_lock_);
template <>
ArtField* Canonicalize(ReflectiveHandle<ArtField> t) {
  return t.Get();
}
template <>
ArtMethod* Canonicalize(ReflectiveHandle<ArtMethod> t) {
  if (UNLIKELY(t->IsCopied())) {
    return t->GetCanonicalMethod();
  }
  return t.Get();
}

};  // namespace

// We increment the id by 2 each time to allow us to use the LSB as a flag that the ID is an index
// and not a pointer. This gives us 2**31 unique methods that can be addressed on 32-bit art, which
// should be more than enough.
template <>
uintptr_t JniIdManager::GetNextId<ArtField>(JniIdType type) {
  DCHECK_EQ(type, JniIdType::kIndices);
  uintptr_t res = next_field_id_;
  next_field_id_ += 2;
  CHECK_GT(next_field_id_, res) << "jfieldID Overflow";
  return res;
}

template <>
uintptr_t JniIdManager::GetNextId<ArtMethod>(JniIdType type) {
  DCHECK_EQ(type, JniIdType::kIndices);
  uintptr_t res = next_method_id_;
  next_method_id_ += 2;
  CHECK_GT(next_method_id_, res) << "jmethodID Overflow";
  return res;
}
template <>
std::vector<ArtField*>& JniIdManager::GetGenericMap<ArtField>() {
  return field_id_map_;
}

template <>
std::vector<ArtMethod*>& JniIdManager::GetGenericMap<ArtMethod>() {
  return method_id_map_;
}
template <>
size_t JniIdManager::GetLinearSearchStartId<ArtField>(
    ReflectiveHandle<ArtField> t ATTRIBUTE_UNUSED) {
  return deferred_allocation_field_id_start_;
}

template <>
size_t JniIdManager::GetLinearSearchStartId<ArtMethod>(ReflectiveHandle<ArtMethod> m) {
  if (CanUseIdArrays(m)) {
    // If we are searching because we couldn't allocate because of defer allocate scope, then we
    // should only look from deferred_allocation_method_id_start_. Once we exit the deferred scope
    // all these method ids will be updated to the id arrays in the respective ClassExt objects.
    return deferred_allocation_method_id_start_;
  } else {
    // If we cannot use ID arrays, then the method can be anywhere in the list.
    return 1;
  }
}

// TODO need to fix races in here with visitors
template <typename ArtType>
uintptr_t JniIdManager::EncodeGenericId(ReflectiveHandle<ArtType> t) {
  static_assert(std::is_same_v<ArtType, ArtField> || std::is_same_v<ArtType, ArtMethod>,
                "Expected ArtField or ArtMethod");
  Runtime* runtime = Runtime::Current();
  JniIdType id_type = runtime->GetJniIdType();
  if (id_type == JniIdType::kPointer || t == nullptr) {
    return reinterpret_cast<uintptr_t>(t.Get());
  }
  Thread* self = Thread::Current();
  ScopedExceptionStorage ses(self);
  DCHECK(!t->GetDeclaringClass().IsNull()) << "Null declaring class " << PrettyGeneric(t);
  size_t off = -1;
  bool allocation_failure = false;
  // When we cannot use ID arrays, we just fallback to looking through the list to obtain the ID.
  // These are rare cases so shouldn't be a problem for performance. See CanUseIdArrays for more
  // information.
  if (CanUseIdArrays(t)) {
    off = GetIdOffset(t->GetDeclaringClass(), Canonicalize(t), kRuntimePointerSize);
    // Here is the earliest point we can suspend.
    allocation_failure = EnsureIdsArray(self, t->GetDeclaringClass(), t.Get());
  }
  if (allocation_failure) {
    self->AssertPendingOOMException();
    ses.SuppressOldException("OOM exception while trying to allocate JNI ids.");
    return 0u;
  } else if (ShouldReturnPointer(t->GetDeclaringClass(), t.Get())) {
    // TODO(mythria): Check why we return a pointer here instead of falling back
    // to the slow path of finding the ID by looping through the ID -> method
    // map. This seem incorrect. For example, if we are in ScopedEnableSuspendAllJniIdQueries
    // scope, we don't allocate ID arrays. We would then incorrectly return a
    // pointer here.
    return reinterpret_cast<uintptr_t>(t.Get());
  }
  ObjPtr<mirror::Class> klass = t->GetDeclaringClass();
  ObjPtr<mirror::PointerArray> ids(GetIds(klass, t.Get()));
  uintptr_t cur_id = 0;
  if (!ids.IsNull()) {
    DCHECK_GT(ids->GetLength(), static_cast<int32_t>(off)) << " is " << PrettyGeneric(t);
    DCHECK_LE(0, static_cast<int32_t>(off)) << " is " << PrettyGeneric(t);
    cur_id = ids->GetElementPtrSize<uintptr_t>(off, kRuntimePointerSize);
  }
  if (cur_id != 0) {
    return cur_id;
  }
  WriterMutexLock mu(self, *Locks::jni_id_lock_);
  ScopedAssertNoThreadSuspension sants("EncodeJniId critical section.");
  // Check the ids array for a racing id.
  constexpr std::pair<size_t, size_t> counts {
    std::is_same_v<ArtType, ArtField> ? 1 : 0,
    std::is_same_v<ArtType, ArtField> ? 0 : 1,
  };
  StackReflectiveHandleScope<counts.first, counts.second> hs(self);
  t = hs.NewHandle(Canonicalize(t));
  if (!ids.IsNull()) {
    // It's possible we got suspended and structurally redefined during the EnsureIdsArray. We need
    // to get the information again.
    ids = GetIds(klass, t.Get());
    off = GetIdOffset(klass, Canonicalize(t), kRuntimePointerSize);
    CHECK(!ids.IsNull());
    cur_id = ids->GetElementPtrSize<uintptr_t>(off, kRuntimePointerSize);
    if (cur_id != 0) {
      // We were racing some other thread and lost.
      return cur_id;
    }
  } else {
    // We cannot allocate anything here or don't have an ids array (we might be an obsolete method).
    DCHECK(!CanUseIdArrays(t) || deferred_allocation_refcount_ > 0u)
        << "deferred_allocation_refcount_: " << deferred_allocation_refcount_
        << " t: " << PrettyGeneric(t);
    // Check to see if we raced and lost to another thread.
    const std::vector<ArtType*>& vec = GetGenericMap<ArtType>();
    bool found = false;
    // simple count-while.
    size_t search_start_index = IdToIndex(GetLinearSearchStartId(t));
    size_t index = std::count_if(vec.cbegin() + search_start_index,
                                 vec.cend(),
                                 [&found, &self, t](const ArtType* candidate) {
                                   Locks::mutator_lock_->AssertSharedHeld(self);
                                   found = found || candidate == t.Get();
                                   return !found;
                                 }) +
                   search_start_index;
    if (found) {
      // We were either racing some other thread and lost or this thread was asked to encode the
      // same method multiple times while holding the mutator lock.
      DCHECK_EQ(vec[index], t.Get())
          << "Expected: " << PrettyGeneric(vec[index]) << " got " << PrettyGeneric(t)
          << " at index " << index << " (id: " << IndexToId(index) << ").";
      return IndexToId(index);
    }
  }
  cur_id = GetNextId<ArtType>(id_type);
  DCHECK_EQ(cur_id % 2, 1u);
  size_t cur_index = IdToIndex(cur_id);
  std::vector<ArtType*>& vec = GetGenericMap<ArtType>();
  vec.reserve(cur_index + 1);
  vec.resize(std::max(vec.size(), cur_index + 1), nullptr);
  vec[cur_index] = t.Get();
  if (ids.IsNull()) {
    if (kIsDebugBuild && CanUseIdArrays(t)) {
      CHECK_NE(deferred_allocation_refcount_, 0u)
          << "Failed to allocate ids array despite not being forbidden from doing so!";
      Locks::mutator_lock_->AssertExclusiveHeld(self);
    }
  } else {
    ids->SetElementPtrSize(off, reinterpret_cast<void*>(cur_id), kRuntimePointerSize);
  }
  return cur_id;
}

jfieldID JniIdManager::EncodeFieldId(ArtField* field) {
  StackArtFieldHandleScope<1> rhs(Thread::Current());
  return EncodeFieldId(rhs.NewHandle(field));
}

jfieldID JniIdManager::EncodeFieldId(ReflectiveHandle<ArtField> field) {
  auto* res = reinterpret_cast<jfieldID>(EncodeGenericId(field));
  if (kTraceIds && field != nullptr) {
    LOG(INFO) << "Returning " << res << " for field " << field->PrettyField();
  }
  return res;
}

jmethodID JniIdManager::EncodeMethodId(ArtMethod* method) {
  StackArtMethodHandleScope<1> rhs(Thread::Current());
  return EncodeMethodId(rhs.NewHandle(method));
}

jmethodID JniIdManager::EncodeMethodId(ReflectiveHandle<ArtMethod> method) {
  auto* res = reinterpret_cast<jmethodID>(EncodeGenericId(method));
  if (kTraceIds && method != nullptr) {
    LOG(INFO) << "Returning " << res << " for method " << method->PrettyMethod();
  }
  return res;
}

void JniIdManager::VisitRoots(RootVisitor *visitor) {
  pointer_marker_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
}

void JniIdManager::Init(Thread* self) {
  // When compiling we don't want to have anything to do with any of this, which is fine since JNI
  // ids won't be created during AOT compilation. This also means we don't need to do any
  // complicated stuff with the image-writer.
  if (!Runtime::Current()->IsAotCompiler()) {
    // Allocate the marker
    StackHandleScope<3> hs(self);
    Handle<mirror::Object> marker_obj(
        hs.NewHandle(GetClassRoot<mirror::Object>()->AllocObject(self)));
    CHECK(!marker_obj.IsNull());
    pointer_marker_ = GcRoot<mirror::Object>(marker_obj.Get());
    // Manually mark class-ext as having all pointer-ids to avoid any annoying loops.
    Handle<mirror::Class> class_ext_class(hs.NewHandle(GetClassRoot<mirror::ClassExt>()));
    mirror::Class::EnsureExtDataPresent(class_ext_class, self);
    Handle<mirror::ClassExt> class_ext_ext(hs.NewHandle(class_ext_class->GetExtData()));
    class_ext_ext->SetIdsArraysForClassExtExtData(marker_obj.Get());
  }
}

void JniIdManager::VisitReflectiveTargets(ReflectiveValueVisitor* rvv) {
  art::WriterMutexLock mu(Thread::Current(), *Locks::jni_id_lock_);
  for (auto it = field_id_map_.begin(); it != field_id_map_.end(); ++it) {
    ArtField* old_field = *it;
    uintptr_t id = IndexToId(std::distance(field_id_map_.begin(), it));
    ArtField* new_field =
        rvv->VisitField(old_field, JniIdReflectiveSourceInfo(reinterpret_cast<jfieldID>(id)));
    if (old_field != new_field) {
      *it = new_field;
      ObjPtr<mirror::Class> old_class(old_field->GetDeclaringClass());
      ObjPtr<mirror::Class> new_class(new_field->GetDeclaringClass());
      ObjPtr<mirror::ClassExt> old_ext_data(old_class->GetExtData());
      ObjPtr<mirror::ClassExt> new_ext_data(new_class->GetExtData());
      if (!old_ext_data.IsNull()) {
        CHECK(!old_ext_data->HasInstanceFieldPointerIdMarker() &&
              !old_ext_data->HasStaticFieldPointerIdMarker())
            << old_class->PrettyClass();
        // Clear the old field mapping.
        if (old_field->IsStatic()) {
          size_t old_off = ArraySlice<ArtField>(old_class->GetSFieldsPtr()).OffsetOf(old_field);
          ObjPtr<mirror::PointerArray> old_statics(old_ext_data->GetStaticJFieldIDsPointerArray());
          if (!old_statics.IsNull()) {
            old_statics->SetElementPtrSize(old_off, 0, kRuntimePointerSize);
          }
        } else {
          size_t old_off = ArraySlice<ArtField>(old_class->GetIFieldsPtr()).OffsetOf(old_field);
          ObjPtr<mirror::PointerArray> old_instances(
              old_ext_data->GetInstanceJFieldIDsPointerArray());
          if (!old_instances.IsNull()) {
            old_instances->SetElementPtrSize(old_off, 0, kRuntimePointerSize);
          }
        }
      }
      if (!new_ext_data.IsNull()) {
        CHECK(!new_ext_data->HasInstanceFieldPointerIdMarker() &&
              !new_ext_data->HasStaticFieldPointerIdMarker())
            << new_class->PrettyClass();
        // Set the new field mapping.
        if (new_field->IsStatic()) {
          size_t new_off = ArraySlice<ArtField>(new_class->GetSFieldsPtr()).OffsetOf(new_field);
          ObjPtr<mirror::PointerArray> new_statics(new_ext_data->GetStaticJFieldIDsPointerArray());
          if (!new_statics.IsNull()) {
            new_statics->SetElementPtrSize(new_off, id, kRuntimePointerSize);
          }
        } else {
          size_t new_off = ArraySlice<ArtField>(new_class->GetIFieldsPtr()).OffsetOf(new_field);
          ObjPtr<mirror::PointerArray> new_instances(
              new_ext_data->GetInstanceJFieldIDsPointerArray());
          if (!new_instances.IsNull()) {
            new_instances->SetElementPtrSize(new_off, id, kRuntimePointerSize);
          }
        }
      }
    }
  }
  for (auto it = method_id_map_.begin(); it != method_id_map_.end(); ++it) {
    ArtMethod* old_method = *it;
    uintptr_t id = IndexToId(std::distance(method_id_map_.begin(), it));
    ArtMethod* new_method =
        rvv->VisitMethod(old_method, JniIdReflectiveSourceInfo(reinterpret_cast<jmethodID>(id)));
    if (old_method != new_method) {
      *it = new_method;
      ObjPtr<mirror::Class> old_class(old_method->GetDeclaringClass());
      ObjPtr<mirror::Class> new_class(new_method->GetDeclaringClass());
      ObjPtr<mirror::ClassExt> old_ext_data(old_class->GetExtData());
      ObjPtr<mirror::ClassExt> new_ext_data(new_class->GetExtData());
      if (!old_ext_data.IsNull()) {
        CHECK(!old_ext_data->HasMethodPointerIdMarker()) << old_class->PrettyClass();
        // Clear the old method mapping.
        size_t old_off = ArraySlice<ArtMethod>(old_class->GetMethodsPtr()).OffsetOf(old_method);
        ObjPtr<mirror::PointerArray> old_methods(old_ext_data->GetJMethodIDsPointerArray());
        if (!old_methods.IsNull()) {
          old_methods->SetElementPtrSize(old_off, 0, kRuntimePointerSize);
        }
      }
      if (!new_ext_data.IsNull()) {
        CHECK(!new_ext_data->HasMethodPointerIdMarker()) << new_class->PrettyClass();
        // Set the new method mapping.
        size_t new_off = ArraySlice<ArtMethod>(new_class->GetMethodsPtr()).OffsetOf(new_method);
        ObjPtr<mirror::PointerArray> new_methods(new_ext_data->GetJMethodIDsPointerArray());
        if (!new_methods.IsNull()) {
          new_methods->SetElementPtrSize(new_off, id, kRuntimePointerSize);
        }
      }
    }
  }
}

template <typename ArtType> ArtType* JniIdManager::DecodeGenericId(uintptr_t t) {
  if (Runtime::Current()->GetJniIdType() == JniIdType::kIndices && (t % 2) == 1) {
    ReaderMutexLock mu(Thread::Current(), *Locks::jni_id_lock_);
    size_t index = IdToIndex(t);
    DCHECK_GT(GetGenericMap<ArtType>().size(), index);
    return GetGenericMap<ArtType>().at(index);
  } else {
    DCHECK_EQ((t % 2), 0u) << "id: " << t;
    return reinterpret_cast<ArtType*>(t);
  }
}

ArtMethod* JniIdManager::DecodeMethodId(jmethodID method) {
  return DecodeGenericId<ArtMethod>(reinterpret_cast<uintptr_t>(method));
}

ArtField* JniIdManager::DecodeFieldId(jfieldID field) {
  return DecodeGenericId<ArtField>(reinterpret_cast<uintptr_t>(field));
}

ObjPtr<mirror::Object> JniIdManager::GetPointerMarker() {
  return pointer_marker_.Read();
}

// This whole defer system is an annoying requirement to allow us to generate IDs during heap-walks
// such as those required for instrumentation tooling.
//
// The defer system works with the normal id-assignment routine to ensure that all the class-ext
// data structures are eventually created and filled in. Basically how it works is the id-assignment
// function will check to see if it has a strong mutator-lock. If it does not then it will try to
// allocate the class-ext data structures normally and fail if it is unable to do so. In the case
// where mutator-lock is being held exclusive no attempt to allocate will be made and the thread
// will CHECK that allocations are being deferred (or that the method is obsolete, in which case
// there is no class-ext to store the method->id map in).
//
// Once the thread is done holding the exclusive mutator-lock it will go back and fill-in the
// class-ext data of all the methods that were added. We do this without the exclusive mutator-lock
// on a copy of the maps before we decrement the deferred refcount. This ensures that any other
// threads running at the same time know they need to perform a linear scan of the id-map. Since we
// don't have the mutator-lock anymore other threads can allocate the class-ext data, meaning our
// copy is fine. The only way additional methods could end up on the id-maps after our copy without
// having class-ext data is if another thread picked up the exclusive mutator-lock and added another
// defer, in which case that thread would fix-up the remaining ids. In this way we maintain eventual
// consistency between the class-ext method/field->id maps and the JniIdManager id->method/field
// maps.
//
// TODO It is possible that another thread to gain the mutator-lock and allocate new ids without
// calling StartDefer. This is basically a race that we should try to catch but doing so is
// rather difficult and since this defer system is only used in very rare circumstances unlikely to
// be worth the trouble.
void JniIdManager::StartDefer() {
  Thread* self = Thread::Current();
  WriterMutexLock mu(self, *Locks::jni_id_lock_);
  if (deferred_allocation_refcount_++ == 0) {
    deferred_allocation_field_id_start_ = next_field_id_;
    deferred_allocation_method_id_start_ = next_method_id_;
  }
}

class JniIdDeferStackReflectiveScope : public BaseReflectiveHandleScope {
 public:
  JniIdDeferStackReflectiveScope() REQUIRES_SHARED(art::Locks::mutator_lock_)
      : BaseReflectiveHandleScope(), methods_(), fields_() {
    PushScope(Thread::Current());
  }

  void Initialize(const std::vector<ArtMethod*>& methods, const std::vector<ArtField*>& fields)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Roles::uninterruptible_) {
    methods_ = methods;
    fields_ = fields;
  }

  ~JniIdDeferStackReflectiveScope() REQUIRES_SHARED(Locks::mutator_lock_) {
    PopScope();
  }

  void VisitTargets(ReflectiveValueVisitor* visitor) override
      REQUIRES_SHARED(Locks::mutator_lock_) {
    for (auto it = methods_.begin(); it != methods_.end(); ++it) {
      if (*it == nullptr) {
        continue;
      }
      *it = visitor->VisitMethod(*it, ReflectiveHandleScopeSourceInfo(this));
    }
    for (auto it = fields_.begin(); it != fields_.end(); ++it) {
      if (*it == nullptr) {
        continue;
      }
      *it = visitor->VisitField(*it, ReflectiveHandleScopeSourceInfo(this));
    }
  }

  ArtField** GetFieldPtr(size_t idx) REQUIRES_SHARED(Locks::mutator_lock_) {
    return &fields_[idx];
  }

  ArtMethod** GetMethodPtr(size_t idx) REQUIRES_SHARED(Locks::mutator_lock_) {
    return &methods_[idx];
  }

  size_t NumFields() const {
    return fields_.size();
  }
  size_t NumMethods() const {
    return methods_.size();
  }

 private:
  std::vector<ArtMethod*> methods_;
  std::vector<ArtField*> fields_;
};

void JniIdManager::EndDefer() {
  // Fixup the method->id map.
  Thread* self = Thread::Current();
  auto set_id = [&](auto** t, uintptr_t id) REQUIRES_SHARED(Locks::mutator_lock_) {
    if (t == nullptr) {
      return;
    }
    bool alloc_failure = EnsureIdsArray(self, (*t)->GetDeclaringClass(), *t);
    ObjPtr<mirror::Class> klass((*t)->GetDeclaringClass());
    size_t off = GetIdOffset(klass, (*t), kRuntimePointerSize);
    ObjPtr<mirror::PointerArray> ids = GetIds(klass, (*t));
    CHECK(!alloc_failure) << "Could not allocate jni ids array!";
    if (ids.IsNull()) {
      return;
    }
    if (kIsDebugBuild) {
      uintptr_t old_id = ids->GetElementPtrSize<uintptr_t, kRuntimePointerSize>(off);
      if (old_id != 0) {
        DCHECK_EQ(old_id, id);
      }
    }
    ids->SetElementPtrSize(off, reinterpret_cast<void*>(id), kRuntimePointerSize);
  };
  // To ensure eventual consistency this depends on the fact that the method_id_map_ and
  // field_id_map_ are the ultimate source of truth and no id is ever reused to be valid. It also
  // relies on all threads always getting calling StartDefer if they are going to be allocating jni
  // ids while suspended. If a thread tries to do so while it doesn't have a scope we could miss
  // ids.
  // TODO We should use roles or something to verify that this requirement is not broken.
  //
  // If another thread comes along and adds more methods to the list after
  // copying either (1) the id-maps are already present for the method and everything is fine, (2)
  // the thread is not suspended and so can create the ext-data and id lists or, (3) the thread also
  // suspended everything and incremented the deferred_allocation_refcount_ so it will fix up new
  // ids when it finishes.
  Locks::mutator_lock_->AssertNotExclusiveHeld(self);
  Locks::mutator_lock_->AssertSharedHeld(self);
  JniIdDeferStackReflectiveScope jidsrs;
  uintptr_t method_start_id;
  uintptr_t field_start_id;
  {
    ReaderMutexLock mu(self, *Locks::jni_id_lock_);
    ScopedAssertNoThreadSuspension sants(__FUNCTION__);
    jidsrs.Initialize(method_id_map_, field_id_map_);
    method_start_id = deferred_allocation_method_id_start_;
    field_start_id = deferred_allocation_field_id_start_;
  }

  for (size_t index = kIsDebugBuild ? 0 : IdToIndex(method_start_id); index < jidsrs.NumMethods();
       ++index) {
    set_id(jidsrs.GetMethodPtr(index), IndexToId(index));
  }
  for (size_t index = kIsDebugBuild ? 0 : IdToIndex(field_start_id); index < jidsrs.NumFields();
       ++index) {
    set_id(jidsrs.GetFieldPtr(index), IndexToId(index));
  }
  WriterMutexLock mu(self, *Locks::jni_id_lock_);
  DCHECK_GE(deferred_allocation_refcount_, 1u);
  if (--deferred_allocation_refcount_ == 0) {
    deferred_allocation_field_id_start_ = 0;
    deferred_allocation_method_id_start_ = 0;
  }
}

ScopedEnableSuspendAllJniIdQueries::ScopedEnableSuspendAllJniIdQueries()
    : manager_(Runtime::Current()->GetJniIdManager()) {
  manager_->StartDefer();
}

ScopedEnableSuspendAllJniIdQueries::~ScopedEnableSuspendAllJniIdQueries() {
  manager_->EndDefer();
}

};  // namespace jni
};  // namespace art
