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 "base/macros.h"
25 #include "dex/class_reference.h"
26 #include "dex/dex_file-inl.h"
27 #include "dex/method_reference.h"
28 #include "dex/type_reference.h"
29
30 namespace art HIDDEN {
31
32 template <typename DexFileReferenceType, typename Value>
NumberOfDexIndices(const DexFile * dex_file)33 inline size_t AtomicDexRefMap<DexFileReferenceType, Value>::NumberOfDexIndices(
34 const DexFile* dex_file) {
35 // TODO: Use specialization for this? Not sure if worth it.
36 static_assert(std::is_same<DexFileReferenceType, MethodReference>::value ||
37 std::is_same<DexFileReferenceType, ClassReference>::value ||
38 std::is_same<DexFileReferenceType, TypeReference>::value,
39 "invalid index type");
40 if (std::is_same<DexFileReferenceType, MethodReference>::value) {
41 return dex_file->NumMethodIds();
42 }
43 if (std::is_same<DexFileReferenceType, ClassReference>::value) {
44 return dex_file->NumClassDefs();
45 }
46 if (std::is_same<DexFileReferenceType, TypeReference>::value) {
47 return dex_file->NumTypeIds();
48 }
49 UNREACHABLE();
50 }
51
52 template <typename DexFileReferenceType, typename Value>
53 inline typename AtomicDexRefMap<DexFileReferenceType, Value>::InsertResult
Insert(const DexFileReferenceType & ref,const Value & expected,const Value & desired)54 AtomicDexRefMap<DexFileReferenceType, Value>::Insert(const DexFileReferenceType& ref,
55 const Value& expected,
56 const Value& desired) {
57 ElementArray* const array = GetArray(ref.dex_file);
58 if (array == nullptr) {
59 return kInsertResultInvalidDexFile;
60 }
61 DCHECK_LT(ref.index, array->size());
62 return (*array)[ref.index].CompareAndSetStrongSequentiallyConsistent(expected, desired)
63 ? kInsertResultSuccess
64 : kInsertResultCASFailure;
65 }
66
67 template <typename DexFileReferenceType, typename Value>
Get(const DexFileReferenceType & ref,Value * out)68 inline bool AtomicDexRefMap<DexFileReferenceType, Value>::Get(const DexFileReferenceType& ref,
69 Value* out) const {
70 const ElementArray* const array = GetArray(ref.dex_file);
71 if (array == nullptr) {
72 return false;
73 }
74 *out = (*array)[ref.index].load(std::memory_order_relaxed);
75 return true;
76 }
77
78 template <typename DexFileReferenceType, typename Value>
Remove(const DexFileReferenceType & ref,Value * out)79 inline bool AtomicDexRefMap<DexFileReferenceType, Value>::Remove(const DexFileReferenceType& ref,
80 Value* out) {
81 ElementArray* const array = GetArray(ref.dex_file);
82 if (array == nullptr) {
83 return false;
84 }
85 *out = (*array)[ref.index].exchange(nullptr, std::memory_order_seq_cst);
86 return true;
87 }
88
89 template <typename DexFileReferenceType, typename Value>
AddDexFile(const DexFile * dex_file)90 inline void AtomicDexRefMap<DexFileReferenceType, Value>::AddDexFile(const DexFile* dex_file) {
91 arrays_.Put(dex_file, std::move(ElementArray(NumberOfDexIndices(dex_file))));
92 }
93
94 template <typename DexFileReferenceType, typename Value>
AddDexFiles(const std::vector<const DexFile * > & dex_files)95 inline void AtomicDexRefMap<DexFileReferenceType, Value>::AddDexFiles(
96 const std::vector<const DexFile*>& dex_files) {
97 for (const DexFile* dex_file : dex_files) {
98 if (!HaveDexFile(dex_file)) {
99 AddDexFile(dex_file);
100 }
101 }
102 }
103
104 template <typename DexFileReferenceType, typename Value>
105 inline typename AtomicDexRefMap<DexFileReferenceType, Value>::ElementArray*
GetArray(const DexFile * dex_file)106 AtomicDexRefMap<DexFileReferenceType, Value>::GetArray(const DexFile* dex_file) {
107 auto it = arrays_.find(dex_file);
108 return (it != arrays_.end()) ? &it->second : nullptr;
109 }
110
111 template <typename DexFileReferenceType, typename Value>
112 inline const typename AtomicDexRefMap<DexFileReferenceType, Value>::ElementArray*
GetArray(const DexFile * dex_file)113 AtomicDexRefMap<DexFileReferenceType, Value>::GetArray(const DexFile* dex_file) const {
114 auto it = arrays_.find(dex_file);
115 return (it != arrays_.end()) ? &it->second : nullptr;
116 }
117
118 template <typename DexFileReferenceType, typename Value> template <typename Visitor>
Visit(const Visitor & visitor)119 inline void AtomicDexRefMap<DexFileReferenceType, Value>::Visit(const Visitor& visitor) {
120 for (auto& pair : arrays_) {
121 const DexFile* dex_file = pair.first;
122 const ElementArray& elements = pair.second;
123 for (size_t i = 0; i < elements.size(); ++i) {
124 visitor(DexFileReference(dex_file, i), elements[i].load(std::memory_order_relaxed));
125 }
126 }
127 }
128
129 template <typename DexFileReferenceType, typename Value>
ClearEntries()130 inline void AtomicDexRefMap<DexFileReferenceType, Value>::ClearEntries() {
131 for (auto& it : arrays_) {
132 for (auto& element : it.second) {
133 element.store(nullptr, std::memory_order_relaxed);
134 }
135 }
136 }
137
138 template <typename DexFileReferenceType, typename Value>
GetDexFiles()139 inline std::vector<const DexFile*> AtomicDexRefMap<DexFileReferenceType, Value>::GetDexFiles()
140 const {
141 std::vector<const DexFile*> result;
142 result.reserve(arrays_.size());
143 for (auto& it : arrays_) {
144 result.push_back(it.first);
145 }
146 return result;
147 }
148
149 } // namespace art
150
151 #endif // ART_COMPILER_UTILS_ATOMIC_DEX_REF_MAP_INL_H_
152