/*
 * 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"
#include "well_known_classes.h"

namespace art {
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_
