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