/*
 * Copyright (C) 2017 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.
 */

#ifndef ART_RUNTIME_MIRROR_CLASS_EXT_INL_H_
#define ART_RUNTIME_MIRROR_CLASS_EXT_INL_H_

#include "class_ext.h"

#include "array-inl.h"
#include "art_method-inl.h"
#include "base/enums.h"
#include "base/globals.h"
#include "class_linker.h"
#include "handle_scope.h"
#include "jni/jni_internal.h"
#include "jni_id_type.h"
#include "mirror/array.h"
#include "mirror/object.h"
#include "object-inl.h"
#include "verify_object.h"

namespace art HIDDEN {
namespace mirror {

template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool ClassExt::EnsureJniIdsArrayPresent(MemberOffset off, size_t count) {
  ObjPtr<Object> existing(
      GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(off));
  if (!existing.IsNull()) {
    return true;
  }
  Thread* self = Thread::Current();
  StackHandleScope<2> hs(self);
  Handle<ClassExt> h_this(hs.NewHandle(this));
  MutableHandle<Object> new_arr(hs.NewHandle<Object>(nullptr));
  if (UNLIKELY(Runtime::Current()->GetJniIdType() == JniIdType::kSwapablePointer)) {
    new_arr.Assign(Runtime::Current()->GetJniIdManager()->GetPointerMarker());
  } else {
    new_arr.Assign(Runtime::Current()->GetClassLinker()->AllocPointerArray(self, count));
  }
  if (new_arr.IsNull()) {
    // Fail.
    self->AssertPendingOOMException();
    return false;
  }
  bool set;
  // Set the ext_data_ field using CAS semantics.
  if (Runtime::Current()->IsActiveTransaction()) {
    set = h_this->CasFieldObject<true>(
        off, nullptr, new_arr.Get(), CASMode::kStrong, std::memory_order_seq_cst);
  } else {
    set = h_this->CasFieldObject<false>(
        off, nullptr, new_arr.Get(), CASMode::kStrong, std::memory_order_seq_cst);
  }
  if (kIsDebugBuild) {
    ObjPtr<Object> ret(
        set ? new_arr.Get()
            : h_this->GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>(off));
    CHECK(!ret.IsNull());
  }
  return true;
}

template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool ClassExt::EnsureJMethodIDsArrayPresent(size_t count) {
  return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>(
      MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, jmethod_ids_)), count);
}
template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool ClassExt::EnsureStaticJFieldIDsArrayPresent(size_t count) {
  return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>(
      MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, static_jfield_ids_)), count);
}
template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool ClassExt::EnsureInstanceJFieldIDsArrayPresent(size_t count) {
  return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>(
      MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, instance_jfield_ids_)), count);
}

template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ObjPtr<Object> ClassExt::GetInstanceJFieldIDs() {
  return GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(
      OFFSET_OF_OBJECT_MEMBER(ClassExt, instance_jfield_ids_));
}
template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool ClassExt::HasInstanceFieldPointerIdMarker() {
  ObjPtr<Object> arr(GetInstanceJFieldIDs<kVerifyFlags, kReadBarrierOption>());
  return !arr.IsNull() && !arr->IsArrayInstance();
}
template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ObjPtr<PointerArray> ClassExt::GetInstanceJFieldIDsPointerArray() {
  DCHECK(!HasInstanceFieldPointerIdMarker());
  return down_cast<PointerArray*>(GetInstanceJFieldIDs<kVerifyFlags, kReadBarrierOption>().Ptr());
}

template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ObjPtr<Object> ClassExt::GetStaticJFieldIDs() {
  return GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(
      OFFSET_OF_OBJECT_MEMBER(ClassExt, static_jfield_ids_));
}
template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ObjPtr<PointerArray> ClassExt::GetStaticJFieldIDsPointerArray() {
  DCHECK(!HasStaticFieldPointerIdMarker());
  return down_cast<PointerArray*>(GetStaticJFieldIDs<kVerifyFlags, kReadBarrierOption>().Ptr());
}
template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool ClassExt::HasStaticFieldPointerIdMarker() {
  ObjPtr<Object> arr(GetStaticJFieldIDs<kVerifyFlags, kReadBarrierOption>());
  return !arr.IsNull() && !arr->IsArrayInstance();
}

template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ObjPtr<Class> ClassExt::GetObsoleteClass() {
  return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(
      OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_class_));
}

template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ObjPtr<Object> ClassExt::GetJMethodIDs() {
  return GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(
      OFFSET_OF_OBJECT_MEMBER(ClassExt, jmethod_ids_));
}
template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ObjPtr<PointerArray> ClassExt::GetJMethodIDsPointerArray() {
  DCHECK(!HasMethodPointerIdMarker());
  return down_cast<PointerArray*>(GetJMethodIDs<kVerifyFlags, kReadBarrierOption>().Ptr());
}
template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool ClassExt::HasMethodPointerIdMarker() {
  ObjPtr<Object> arr(GetJMethodIDs<kVerifyFlags, kReadBarrierOption>());
  return !arr.IsNull() && !arr->IsArrayInstance();
}

inline ObjPtr<Throwable> ClassExt::GetErroneousStateError() {
  return GetFieldObject<Throwable>(OFFSET_OF_OBJECT_MEMBER(ClassExt, erroneous_state_error_));
}

template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ObjPtr<ObjectArray<DexCache>> ClassExt::GetObsoleteDexCaches() {
  return GetFieldObject<ObjectArray<DexCache>, kVerifyFlags, kReadBarrierOption>(
      OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_dex_caches_));
}

template<VerifyObjectFlags kVerifyFlags,
         ReadBarrierOption kReadBarrierOption>
inline ObjPtr<PointerArray> ClassExt::GetObsoleteMethods() {
  return GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>(
      OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_methods_));
}

inline ObjPtr<Object> ClassExt::GetOriginalDexFile() {
  return GetFieldObject<Object>(OFFSET_OF_OBJECT_MEMBER(ClassExt, original_dex_file_));
}

template<ReadBarrierOption kReadBarrierOption, bool kVisitProxyMethod, class Visitor>
void ClassExt::VisitNativeRoots(Visitor& visitor, PointerSize pointer_size) {
  VisitMethods<kReadBarrierOption>([&](ArtMethod* method) {
    method->VisitRoots<kReadBarrierOption, kVisitProxyMethod>(visitor, pointer_size);
  }, pointer_size);
}

template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
void ClassExt::VisitDexCaches(DexCacheVisitor& visitor) {
  ObjPtr<ObjectArray<DexCache>> arr(GetObsoleteDexCaches<kVerifyFlags, kReadBarrierOption>());
  if (!arr.IsNull()) {
    int32_t len = arr->GetLength();
    for (int32_t i = 0; i < len; i++) {
      ObjPtr<mirror::DexCache> dex_cache = arr->Get<kVerifyFlags, kReadBarrierOption>(i);
      visitor.Visit(dex_cache);
    }
  }
}

template<ReadBarrierOption kReadBarrierOption, class Visitor>
void ClassExt::VisitMethods(Visitor visitor, PointerSize pointer_size) {
  ObjPtr<PointerArray> arr(GetObsoleteMethods<kDefaultVerifyFlags, kReadBarrierOption>());
  if (!arr.IsNull()) {
    int32_t len = arr->GetLength();
    for (int32_t i = 0; i < len; i++) {
      ArtMethod* method = arr->GetElementPtrSize<ArtMethod*>(i, pointer_size);
      if (method != nullptr) {
        visitor(method);
      }
    }
  }
}

template<ReadBarrierOption kReadBarrierOption, class Visitor>
void ClassExt::VisitJMethodIDs(Visitor v) {
  ObjPtr<Object> arr(GetJMethodIDs<kDefaultVerifyFlags, kReadBarrierOption>());
  if (!arr.IsNull() && arr->IsArrayInstance()) {
    ObjPtr<PointerArray> marr(down_cast<PointerArray*>(arr.Ptr()));
    int32_t len = marr->GetLength();
    for (int32_t i = 0; i < len; i++) {
      jmethodID id = marr->GetElementPtrSize<jmethodID>(i, kRuntimePointerSize);
      if (id != nullptr) {
        v(id, i);
      }
    }
  }
}
template<ReadBarrierOption kReadBarrierOption, class Visitor>
void ClassExt::VisitJFieldIDs(Visitor v) {
  ObjPtr<Object> sarr_obj(GetStaticJFieldIDs<kDefaultVerifyFlags, kReadBarrierOption>());
  if (!sarr_obj.IsNull() && sarr_obj->IsArrayInstance()) {
    ObjPtr<PointerArray> sarr(down_cast<PointerArray*>(sarr_obj->AsArray().Ptr()));
    int32_t len = sarr->GetLength();
    for (int32_t i = 0; i < len; i++) {
      jfieldID id = sarr->GetElementPtrSize<jfieldID>(i, kRuntimePointerSize);
      if (id != nullptr) {
        v(id, i, true);
      }
    }
  }
  ObjPtr<PointerArray> iarr_obj(GetInstanceJFieldIDs<kDefaultVerifyFlags, kReadBarrierOption>());
  if (!iarr_obj.IsNull() && iarr_obj->IsArrayInstance()) {
    ObjPtr<PointerArray> iarr(down_cast<PointerArray*>(iarr_obj->AsArray().Ptr()));
    int32_t len = iarr->GetLength();
    for (int32_t i = 0; i < len; i++) {
      jfieldID id = iarr->GetElementPtrSize<jfieldID>(i, kRuntimePointerSize);
      if (id != nullptr) {
        v(id, i, false);
      }
    }
  }
}

}  // namespace mirror
}  // namespace art

#endif  // ART_RUNTIME_MIRROR_CLASS_EXT_INL_H_
