/*
 * Copyright (C) 2013 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_DEX_CACHE_INL_H_
#define ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_

#include "dex_cache.h"

#include <android-base/logging.h>

#include "art_field.h"
#include "art_method.h"
#include "base/atomic_pair.h"
#include "base/casts.h"
#include "base/pointer_size.h"
#include "class_linker.h"
#include "dex/dex_file.h"
#include "gc_root-inl.h"
#include "linear_alloc-inl.h"
#include "mirror/call_site.h"
#include "mirror/class.h"
#include "mirror/method_type.h"
#include "obj_ptr.h"
#include "object-inl.h"
#include "runtime.h"
#include "write_barrier-inl.h"

#include <atomic>

namespace art HIDDEN {
namespace mirror {

template<typename DexCachePair>
static void InitializeArray(std::atomic<DexCachePair>* array) {
  DexCachePair::Initialize(array);
}

template<typename T>
static void InitializeArray(T*) {
  // Nothing to do.
}

template<typename T>
T* DexCache::AllocArray(MemberOffset obj_offset, size_t num, LinearAllocKind kind, bool startup) {
  Thread* self = Thread::Current();
  mirror::DexCache* dex_cache = this;
  if (gUseReadBarrier && self->GetIsGcMarking()) {
    // Several code paths use DexCache without read-barrier for performance.
    // We have to check the "to-space" object here to avoid allocating twice.
    dex_cache = reinterpret_cast<DexCache*>(ReadBarrier::Mark(this));
  }
  // DON'T USE 'this' from now on.
  Runtime* runtime = Runtime::Current();
  // Note: in the 1002-notify-startup test, the startup linear alloc can become null
  // concurrently, even if the runtime is marked at startup. Therefore we should only
  // fetch it once here.
  LinearAlloc* startup_linear_alloc = runtime->GetStartupLinearAlloc();
  LinearAlloc* alloc = (startup && startup_linear_alloc != nullptr)
      ? startup_linear_alloc
      : runtime->GetClassLinker()->GetOrCreateAllocatorForClassLoader(GetClassLoader());
  MutexLock mu(self, *Locks::dex_cache_lock_);  // Avoid allocation by multiple threads.
  T* array = dex_cache->GetFieldPtr64<T*>(obj_offset);
  if (array != nullptr) {
    DCHECK(alloc->Contains(array));
    return array;  // Other thread just allocated the array.
  }
  array = reinterpret_cast<T*>(alloc->AllocAlign16(self, RoundUp(num * sizeof(T), 16), kind));
  InitializeArray(array);  // Ensure other threads see the array initialized.
  dex_cache->SetField64Volatile<false, false>(obj_offset, reinterpret_cast64<uint64_t>(array));
  return array;
}

template <typename T>
inline DexCachePair<T>::DexCachePair(ObjPtr<T> object, uint32_t index)
    : object(object), index(index) {}

template <typename T>
inline T* DexCachePair<T>::GetObjectForIndex(uint32_t idx) {
  if (idx != index) {
    return nullptr;
  }
  DCHECK(!object.IsNull());
  return object.Read();
}

template <typename T>
inline void DexCachePair<T>::Initialize(std::atomic<DexCachePair<T>>* dex_cache) {
  DexCachePair<T> first_elem;
  first_elem.object = GcRoot<T>(nullptr);
  first_elem.index = InvalidIndexForSlot(0);
  dex_cache[0].store(first_elem, std::memory_order_relaxed);
}

template <typename T>
inline void NativeDexCachePair<T>::Initialize(std::atomic<NativeDexCachePair<T>>* dex_cache) {
  NativeDexCachePair<T> first_elem;
  first_elem.object = nullptr;
  first_elem.index = InvalidIndexForSlot(0);

  auto* array = reinterpret_cast<AtomicPair<uintptr_t>*>(dex_cache);
  AtomicPair<uintptr_t> v(first_elem.index, reinterpret_cast<size_t>(first_elem.object));
  AtomicPairStoreRelease(&array[0], v);
}

template <typename T>
inline void GcRootArray<T>::Set(uint32_t index, T* value) {
  GcRoot<T> root(value);
  entries_[index].store(root, std::memory_order_relaxed);
}

template <typename T>
inline T* GcRootArray<T>::Get(uint32_t index) {
  return entries_[index].load(std::memory_order_relaxed).Read();
}

inline uint32_t DexCache::ClassSize(PointerSize pointer_size) {
  const uint32_t vtable_entries = Object::kVTableLength;
  return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, 0, pointer_size);
}

inline String* DexCache::GetResolvedString(dex::StringIndex string_idx) {
  return GetStringsEntry(string_idx.index_);
}

inline void DexCache::SetResolvedString(dex::StringIndex string_idx, ObjPtr<String> resolved) {
  DCHECK(resolved != nullptr);
  SetStringsEntry(string_idx.index_, resolved.Ptr());
  Runtime* const runtime = Runtime::Current();
  if (UNLIKELY(runtime->IsActiveTransaction())) {
    DCHECK(runtime->IsAotCompiler());
    runtime->GetClassLinker()->RecordResolveString(this, string_idx);
  }
  // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
  WriteBarrier::ForEveryFieldWrite(this);
}

inline void DexCache::ClearString(dex::StringIndex string_idx) {
  DCHECK(Runtime::Current()->IsAotCompiler());
  auto* array = GetStringsArray();
  if (array != nullptr) {
    array->Set(string_idx.index_, nullptr);
  }
  auto* strings = GetStrings();
  if (UNLIKELY(strings == nullptr)) {
    return;
  }
  strings->Clear(string_idx.index_);
}

inline Class* DexCache::GetResolvedType(dex::TypeIndex type_idx) {
  return GetResolvedTypesEntry(type_idx.index_);
}

inline void DexCache::ClearResolvedType(dex::TypeIndex type_idx) {
  DCHECK(Runtime::Current()->IsAotCompiler());
  auto* array = GetResolvedTypesArray();
  if (array != nullptr) {
    array->Set(type_idx.index_, nullptr);
  }
  auto* resolved_types = GetResolvedTypes();
  if (UNLIKELY(resolved_types == nullptr)) {
    return;
  }
  resolved_types->Clear(type_idx.index_);
}

inline MethodType* DexCache::GetResolvedMethodType(dex::ProtoIndex proto_idx) {
  return GetResolvedMethodTypesEntry(proto_idx.index_);
}

inline void DexCache::SetResolvedMethodType(dex::ProtoIndex proto_idx, MethodType* resolved) {
  DCHECK(resolved != nullptr);
  SetResolvedMethodTypesEntry(proto_idx.index_, resolved);

  Runtime* const runtime = Runtime::Current();
  if (UNLIKELY(runtime->IsActiveTransaction())) {
    DCHECK(runtime->IsAotCompiler());
    runtime->GetClassLinker()->RecordResolveMethodType(this, proto_idx);
  }
  // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
  WriteBarrier::ForEveryFieldWrite(this);
}

inline void DexCache::ClearMethodType(dex::ProtoIndex proto_idx) {
  DCHECK(Runtime::Current()->IsAotCompiler());
  auto* array = GetResolvedMethodTypesArray();
  if (array != nullptr) {
    array->Set(proto_idx.index_, nullptr);
  }
  auto* methods = GetResolvedMethodTypes();
  if (methods == nullptr) {
    return;
  }
  methods->Clear(proto_idx.index_);
}

inline CallSite* DexCache::GetResolvedCallSite(uint32_t call_site_idx) {
  DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
  DCHECK_LT(call_site_idx, GetDexFile()->NumCallSiteIds());
  GcRootArray<CallSite>* call_sites = GetResolvedCallSites();
  if (UNLIKELY(call_sites == nullptr)) {
    return nullptr;
  }
  Atomic<GcRoot<mirror::CallSite>>* target = call_sites->GetGcRoot(call_site_idx);
  return target->load(std::memory_order_seq_cst).Read();
}

inline ObjPtr<CallSite> DexCache::SetResolvedCallSite(uint32_t call_site_idx,
                                                      ObjPtr<CallSite> call_site) {
  DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
  DCHECK_LT(call_site_idx, GetDexFile()->NumCallSiteIds());

  GcRoot<mirror::CallSite> null_call_site(nullptr);
  GcRoot<mirror::CallSite> candidate(call_site);
  GcRootArray<CallSite>* call_sites = GetResolvedCallSites();
  if (UNLIKELY(call_sites == nullptr)) {
    call_sites = AllocateResolvedCallSites();
  }
  Atomic<GcRoot<mirror::CallSite>>* target = call_sites->GetGcRoot(call_site_idx);

  // The first assignment for a given call site wins.
  if (target->CompareAndSetStrongSequentiallyConsistent(null_call_site, candidate)) {
    // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
    WriteBarrier::ForEveryFieldWrite(this);
    return call_site;
  } else {
    return target->load(std::memory_order_relaxed).Read();
  }
}

inline ArtField* DexCache::GetResolvedField(uint32_t field_idx) {
  return GetResolvedFieldsEntry(field_idx);
}

inline void DexCache::SetResolvedField(uint32_t field_idx, ArtField* field) {
  SetResolvedFieldsEntry(field_idx, field);
}

inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx) {
  return GetResolvedMethodsEntry(method_idx);
}

inline void DexCache::SetResolvedMethod(uint32_t method_idx, ArtMethod* method) {
  SetResolvedMethodsEntry(method_idx, method);
}

template <ReadBarrierOption kReadBarrierOption,
          typename Visitor,
          typename T>
inline void VisitDexCachePairs(T* array,
                               size_t num_pairs,
                               const Visitor& visitor)
    REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
  // Check both the data pointer and count since the array might be initialized
  // concurrently on other thread, and we might observe just one of the values.
  for (size_t i = 0; array != nullptr && i < num_pairs; ++i) {
    auto source = array->GetPair(i);
    // NOTE: We need the "template" keyword here to avoid a compilation
    // failure. GcRoot<T> is a template argument-dependent type and we need to
    // tell the compiler to treat "Read" as a template rather than a field or
    // function. Otherwise, on encountering the "<" token, the compiler would
    // treat "Read" as a field.
    auto const before = source.object.template Read<kReadBarrierOption>();
    visitor.VisitRootIfNonNull(source.object.AddressWithoutBarrier());
    if (source.object.template Read<kReadBarrierOption>() != before) {
      array->SetPair(i, source);
    }
  }
}

template <typename Visitor>
void DexCache::VisitDexCachePairRoots(Visitor& visitor,
                                      DexCachePair<Object>* pairs_begin,
                                      DexCachePair<Object>* pairs_end) {
  for (; pairs_begin < pairs_end; pairs_begin++) {
    visitor.VisitRootIfNonNull(pairs_begin->object.AddressWithoutBarrier());
  }
}

template <bool kVisitNativeRoots,
          VerifyObjectFlags kVerifyFlags,
          ReadBarrierOption kReadBarrierOption,
          typename Visitor>
inline void DexCache::VisitReferences(ObjPtr<Class> klass, const Visitor& visitor) {
  // Visit instance fields first.
  VisitInstanceFieldsReferences<kVerifyFlags>(klass, visitor);
  // Visit arrays after.
  if (kVisitNativeRoots) {
    VisitNativeRoots<kVerifyFlags, kReadBarrierOption>(visitor);
  }
}

template <VerifyObjectFlags kVerifyFlags,
          ReadBarrierOption kReadBarrierOption,
          typename Visitor>
inline void DexCache::VisitNativeRoots(const Visitor& visitor) {
  VisitDexCachePairs<kReadBarrierOption, Visitor>(
      GetStrings<kVerifyFlags>(), NumStrings<kVerifyFlags>(), visitor);

  VisitDexCachePairs<kReadBarrierOption, Visitor>(
      GetResolvedTypes<kVerifyFlags>(), NumResolvedTypes<kVerifyFlags>(), visitor);

  VisitDexCachePairs<kReadBarrierOption, Visitor>(
      GetResolvedMethodTypes<kVerifyFlags>(), NumResolvedMethodTypes<kVerifyFlags>(), visitor);

  GcRootArray<mirror::CallSite>* resolved_call_sites = GetResolvedCallSites<kVerifyFlags>();
  size_t num_call_sites = NumResolvedCallSites<kVerifyFlags>();
  for (size_t i = 0; resolved_call_sites != nullptr && i != num_call_sites; ++i) {
    visitor.VisitRootIfNonNull(resolved_call_sites->GetGcRootAddress(i)->AddressWithoutBarrier());
  }

  // Dex cache arrays can be reset and cleared during app startup. Assert we do not get
  // suspended to ensure the arrays are not deallocated.
  ScopedAssertNoThreadSuspension soants("dex caches");
  GcRootArray<mirror::Class>* resolved_types = GetResolvedTypesArray<kVerifyFlags>();
  size_t num_resolved_types = NumResolvedTypesArray<kVerifyFlags>();
  for (size_t i = 0; resolved_types != nullptr && i != num_resolved_types; ++i) {
    visitor.VisitRootIfNonNull(resolved_types->GetGcRootAddress(i)->AddressWithoutBarrier());
  }

  GcRootArray<mirror::String>* resolved_strings = GetStringsArray<kVerifyFlags>();
  size_t num_resolved_strings = NumStringsArray<kVerifyFlags>();
  for (size_t i = 0; resolved_strings != nullptr && i != num_resolved_strings; ++i) {
    visitor.VisitRootIfNonNull(resolved_strings->GetGcRootAddress(i)->AddressWithoutBarrier());
  }

  GcRootArray<mirror::MethodType>* resolved_method_types =
      GetResolvedMethodTypesArray<kVerifyFlags>();
  size_t num_resolved_method_types = NumResolvedMethodTypesArray<kVerifyFlags>();
  for (size_t i = 0; resolved_method_types != nullptr && i != num_resolved_method_types; ++i) {
    visitor.VisitRootIfNonNull(resolved_method_types->GetGcRootAddress(i)->AddressWithoutBarrier());
  }
}

template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ObjPtr<String> DexCache::GetLocation() {
  return GetFieldObject<String, kVerifyFlags, kReadBarrierOption>(
      OFFSET_OF_OBJECT_MEMBER(DexCache, location_));
}

}  // namespace mirror
}  // namespace art

#endif  // ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_
