Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_COMPILER_UTILS_ATOMIC_DEX_REF_MAP_INL_H_
     18 #define ART_COMPILER_UTILS_ATOMIC_DEX_REF_MAP_INL_H_
     19 
     20 #include "atomic_dex_ref_map.h"
     21 
     22 #include <type_traits>
     23 
     24 #include "dex/class_reference.h"
     25 #include "dex/dex_file-inl.h"
     26 #include "dex/method_reference.h"
     27 #include "dex/type_reference.h"
     28 
     29 namespace art {
     30 
     31 template <typename DexFileReferenceType, typename Value>
     32 inline size_t AtomicDexRefMap<DexFileReferenceType, Value>::NumberOfDexIndices(
     33     const DexFile* dex_file) {
     34   // TODO: Use specialization for this? Not sure if worth it.
     35   static_assert(std::is_same<DexFileReferenceType, MethodReference>::value ||
     36                 std::is_same<DexFileReferenceType, ClassReference>::value ||
     37                 std::is_same<DexFileReferenceType, TypeReference>::value,
     38                 "invalid index type");
     39   if (std::is_same<DexFileReferenceType, MethodReference>::value) {
     40     return dex_file->NumMethodIds();
     41   }
     42   if (std::is_same<DexFileReferenceType, ClassReference>::value) {
     43     return dex_file->NumClassDefs();
     44   }
     45   if (std::is_same<DexFileReferenceType, TypeReference>::value) {
     46     return dex_file->NumTypeIds();
     47   }
     48   UNREACHABLE();
     49 }
     50 
     51 template <typename DexFileReferenceType, typename Value>
     52 inline typename AtomicDexRefMap<DexFileReferenceType, Value>::InsertResult
     53     AtomicDexRefMap<DexFileReferenceType, Value>::Insert(const DexFileReferenceType& ref,
     54                                                          const Value& expected,
     55                                                          const Value& desired) {
     56   ElementArray* const array = GetArray(ref.dex_file);
     57   if (array == nullptr) {
     58     return kInsertResultInvalidDexFile;
     59   }
     60   DCHECK_LT(ref.index, array->size());
     61   return (*array)[ref.index].CompareAndSetStrongSequentiallyConsistent(expected, desired)
     62       ? kInsertResultSuccess
     63       : kInsertResultCASFailure;
     64 }
     65 
     66 template <typename DexFileReferenceType, typename Value>
     67 inline bool AtomicDexRefMap<DexFileReferenceType, Value>::Get(const DexFileReferenceType& ref,
     68                                                               Value* out) const {
     69   const ElementArray* const array = GetArray(ref.dex_file);
     70   if (array == nullptr) {
     71     return false;
     72   }
     73   *out = (*array)[ref.index].LoadRelaxed();
     74   return true;
     75 }
     76 
     77 template <typename DexFileReferenceType, typename Value>
     78 inline bool AtomicDexRefMap<DexFileReferenceType, Value>::Remove(const DexFileReferenceType& ref,
     79                                                                  Value* out) {
     80   ElementArray* const array = GetArray(ref.dex_file);
     81   if (array == nullptr) {
     82     return false;
     83   }
     84   *out = (*array)[ref.index].ExchangeSequentiallyConsistent(nullptr);
     85   return true;
     86 }
     87 
     88 template <typename DexFileReferenceType, typename Value>
     89 inline void AtomicDexRefMap<DexFileReferenceType, Value>::AddDexFile(const DexFile* dex_file) {
     90   arrays_.Put(dex_file, std::move(ElementArray(NumberOfDexIndices(dex_file))));
     91 }
     92 
     93 template <typename DexFileReferenceType, typename Value>
     94 inline void AtomicDexRefMap<DexFileReferenceType, Value>::AddDexFiles(
     95     const std::vector<const DexFile*>& dex_files) {
     96   for (const DexFile* dex_file : dex_files) {
     97     if (!HaveDexFile(dex_file)) {
     98       AddDexFile(dex_file);
     99     }
    100   }
    101 }
    102 
    103 template <typename DexFileReferenceType, typename Value>
    104 inline typename AtomicDexRefMap<DexFileReferenceType, Value>::ElementArray*
    105     AtomicDexRefMap<DexFileReferenceType, Value>::GetArray(const DexFile* dex_file) {
    106   auto it = arrays_.find(dex_file);
    107   return (it != arrays_.end()) ? &it->second : nullptr;
    108 }
    109 
    110 template <typename DexFileReferenceType, typename Value>
    111 inline const typename AtomicDexRefMap<DexFileReferenceType, Value>::ElementArray*
    112     AtomicDexRefMap<DexFileReferenceType, Value>::GetArray(const DexFile* dex_file) const {
    113   auto it = arrays_.find(dex_file);
    114   return (it != arrays_.end()) ? &it->second : nullptr;
    115 }
    116 
    117 template <typename DexFileReferenceType, typename Value> template <typename Visitor>
    118 inline void AtomicDexRefMap<DexFileReferenceType, Value>::Visit(const Visitor& visitor) {
    119   for (auto& pair : arrays_) {
    120     const DexFile* dex_file = pair.first;
    121     const ElementArray& elements = pair.second;
    122     for (size_t i = 0; i < elements.size(); ++i) {
    123       visitor(DexFileReference(dex_file, i), elements[i].LoadRelaxed());
    124     }
    125   }
    126 }
    127 
    128 template <typename DexFileReferenceType, typename Value>
    129 inline void AtomicDexRefMap<DexFileReferenceType, Value>::ClearEntries() {
    130   for (auto& it : arrays_) {
    131     for (auto& element : it.second) {
    132       element.StoreRelaxed(nullptr);
    133     }
    134   }
    135 }
    136 
    137 }  // namespace art
    138 
    139 #endif  // ART_COMPILER_UTILS_ATOMIC_DEX_REF_MAP_INL_H_
    140