/*
 * Copyright (C) 2016 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_COMPILER_UTILS_ATOMIC_DEX_REF_MAP_INL_H_
#define ART_COMPILER_UTILS_ATOMIC_DEX_REF_MAP_INL_H_

#include "atomic_dex_ref_map.h"

#include <type_traits>

#include "base/macros.h"
#include "dex/class_reference.h"
#include "dex/dex_file-inl.h"
#include "dex/method_reference.h"
#include "dex/type_reference.h"

namespace art HIDDEN {

template <typename DexFileReferenceType, typename Value>
inline size_t AtomicDexRefMap<DexFileReferenceType, Value>::NumberOfDexIndices(
    const DexFile* dex_file) {
  // TODO: Use specialization for this? Not sure if worth it.
  static_assert(std::is_same<DexFileReferenceType, MethodReference>::value ||
                std::is_same<DexFileReferenceType, ClassReference>::value ||
                std::is_same<DexFileReferenceType, TypeReference>::value,
                "invalid index type");
  if (std::is_same<DexFileReferenceType, MethodReference>::value) {
    return dex_file->NumMethodIds();
  }
  if (std::is_same<DexFileReferenceType, ClassReference>::value) {
    return dex_file->NumClassDefs();
  }
  if (std::is_same<DexFileReferenceType, TypeReference>::value) {
    return dex_file->NumTypeIds();
  }
  UNREACHABLE();
}

template <typename DexFileReferenceType, typename Value>
inline typename AtomicDexRefMap<DexFileReferenceType, Value>::InsertResult
    AtomicDexRefMap<DexFileReferenceType, Value>::Insert(const DexFileReferenceType& ref,
                                                         const Value& expected,
                                                         const Value& desired) {
  ElementArray* const array = GetArray(ref.dex_file);
  if (array == nullptr) {
    return kInsertResultInvalidDexFile;
  }
  DCHECK_LT(ref.index, array->size());
  return (*array)[ref.index].CompareAndSetStrongSequentiallyConsistent(expected, desired)
      ? kInsertResultSuccess
      : kInsertResultCASFailure;
}

template <typename DexFileReferenceType, typename Value>
inline bool AtomicDexRefMap<DexFileReferenceType, Value>::Get(const DexFileReferenceType& ref,
                                                              Value* out) const {
  const ElementArray* const array = GetArray(ref.dex_file);
  if (array == nullptr) {
    return false;
  }
  *out = (*array)[ref.index].load(std::memory_order_relaxed);
  return true;
}

template <typename DexFileReferenceType, typename Value>
inline bool AtomicDexRefMap<DexFileReferenceType, Value>::Remove(const DexFileReferenceType& ref,
                                                                 Value* out) {
  ElementArray* const array = GetArray(ref.dex_file);
  if (array == nullptr) {
    return false;
  }
  *out = (*array)[ref.index].exchange(nullptr, std::memory_order_seq_cst);
  return true;
}

template <typename DexFileReferenceType, typename Value>
inline void AtomicDexRefMap<DexFileReferenceType, Value>::AddDexFile(const DexFile* dex_file) {
  arrays_.Put(dex_file, std::move(ElementArray(NumberOfDexIndices(dex_file))));
}

template <typename DexFileReferenceType, typename Value>
inline void AtomicDexRefMap<DexFileReferenceType, Value>::AddDexFiles(
    const std::vector<const DexFile*>& dex_files) {
  for (const DexFile* dex_file : dex_files) {
    if (!HaveDexFile(dex_file)) {
      AddDexFile(dex_file);
    }
  }
}

template <typename DexFileReferenceType, typename Value>
inline typename AtomicDexRefMap<DexFileReferenceType, Value>::ElementArray*
    AtomicDexRefMap<DexFileReferenceType, Value>::GetArray(const DexFile* dex_file) {
  auto it = arrays_.find(dex_file);
  return (it != arrays_.end()) ? &it->second : nullptr;
}

template <typename DexFileReferenceType, typename Value>
inline const typename AtomicDexRefMap<DexFileReferenceType, Value>::ElementArray*
    AtomicDexRefMap<DexFileReferenceType, Value>::GetArray(const DexFile* dex_file) const {
  auto it = arrays_.find(dex_file);
  return (it != arrays_.end()) ? &it->second : nullptr;
}

template <typename DexFileReferenceType, typename Value> template <typename Visitor>
inline void AtomicDexRefMap<DexFileReferenceType, Value>::Visit(const Visitor& visitor) {
  for (auto& pair : arrays_) {
    const DexFile* dex_file = pair.first;
    const ElementArray& elements = pair.second;
    for (size_t i = 0; i < elements.size(); ++i) {
      visitor(DexFileReference(dex_file, i), elements[i].load(std::memory_order_relaxed));
    }
  }
}

template <typename DexFileReferenceType, typename Value>
inline void AtomicDexRefMap<DexFileReferenceType, Value>::ClearEntries() {
  for (auto& it : arrays_) {
    for (auto& element : it.second) {
      element.store(nullptr, std::memory_order_relaxed);
    }
  }
}

template <typename DexFileReferenceType, typename Value>
inline std::vector<const DexFile*> AtomicDexRefMap<DexFileReferenceType, Value>::GetDexFiles()
    const {
  std::vector<const DexFile*> result;
  result.reserve(arrays_.size());
  for (auto& it : arrays_) {
    result.push_back(it.first);
  }
  return result;
}

}  // namespace art

#endif  // ART_COMPILER_UTILS_ATOMIC_DEX_REF_MAP_INL_H_
