blob: b41443e5fb75b3a3aa33fd860cfbdcb5192d2b71 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 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 */
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070016
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_MIRROR_DEX_CACHE_H_
18#define ART_RUNTIME_MIRROR_DEX_CACHE_H_
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070019
Mathieu Chartiere401d142015-04-22 13:56:20 -070020#include "array.h"
Vladimir Marko8d6768d2017-03-14 10:13:21 +000021#include "base/bit_utils.h"
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080022#include "base/locks.h"
David Sehr9e734c72018-01-04 17:56:19 -080023#include "dex/dex_file_types.h"
Andreas Gampe88dbad32018-06-26 19:54:12 -070024#include "gc_root.h" // Note: must not use -inl here to avoid circular dependency.
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070025#include "object.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080026#include "object_array.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070027
28namespace art {
29
Vladimir Markoca8de0a2018-07-04 11:56:08 +010030namespace linker {
31class ImageWriter;
32} // namespace linker
33
Vladimir Marko8d6768d2017-03-14 10:13:21 +000034class ArtField;
Alex Lightdba61482016-12-21 08:20:29 -080035class ArtMethod;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080036struct DexCacheOffsets;
37class DexFile;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080038union JValue;
Andreas Gampecc1b5352016-12-01 16:58:38 -080039class LinearAlloc;
40class Thread;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080041
42namespace mirror {
43
Orion Hodsonc069a302017-01-18 09:23:12 +000044class CallSite;
Vladimir Marko8d6768d2017-03-14 10:13:21 +000045class Class;
Narayan Kamath25352fc2016-08-03 12:46:58 +010046class MethodType;
Mingyao Yang98d1cc82014-05-15 17:02:16 -070047class String;
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070048
Narayan Kamathc38a6f82016-09-29 17:07:20 +010049template <typename T> struct PACKED(8) DexCachePair {
50 GcRoot<T> object;
51 uint32_t index;
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -070052 // The array is initially [ {0,0}, {0,0}, {0,0} ... ]
53 // We maintain the invariant that once a dex cache entry is populated,
54 // the pointer is always non-0
55 // Any given entry would thus be:
56 // {non-0, non-0} OR {0,0}
57 //
58 // It's generally sufficiently enough then to check if the
Narayan Kamathc38a6f82016-09-29 17:07:20 +010059 // lookup index matches the stored index (for a >0 lookup index)
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -070060 // because if it's true the pointer is also non-null.
61 //
62 // For the 0th entry which is a special case, the value is either
63 // {0,0} (initial state) or {non-0, 0} which indicates
Narayan Kamathc38a6f82016-09-29 17:07:20 +010064 // that a valid object is stored at that index for a dex section id of 0.
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -070065 //
Narayan Kamathc38a6f82016-09-29 17:07:20 +010066 // As an optimization, we want to avoid branching on the object pointer since
67 // it's always non-null if the id branch succeeds (except for the 0th id).
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -070068 // Set the initial state for the 0th entry to be {0,1} which is guaranteed to fail
Narayan Kamathc38a6f82016-09-29 17:07:20 +010069 // the lookup id == stored id branch.
Andreas Gampe88dbad32018-06-26 19:54:12 -070070 DexCachePair(ObjPtr<T> object, uint32_t index);
Andreas Gamped9911ee2017-03-27 13:27:24 -070071 DexCachePair() : index(0) {}
Narayan Kamathc38a6f82016-09-29 17:07:20 +010072 DexCachePair(const DexCachePair<T>&) = default;
73 DexCachePair& operator=(const DexCachePair<T>&) = default;
Mathieu Chartierbb816d62016-09-07 10:17:46 -070074
Andreas Gampe88dbad32018-06-26 19:54:12 -070075 static void Initialize(std::atomic<DexCachePair<T>>* dex_cache);
Mathieu Chartierbb816d62016-09-07 10:17:46 -070076
Narayan Kamathc38a6f82016-09-29 17:07:20 +010077 static uint32_t InvalidIndexForSlot(uint32_t slot) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -070078 // Since the cache size is a power of two, 0 will always map to slot 0.
79 // Use 1 for slot 0 and 0 for all other slots.
80 return (slot == 0) ? 1u : 0u;
81 }
Vladimir Marko8d6768d2017-03-14 10:13:21 +000082
Andreas Gampe88dbad32018-06-26 19:54:12 -070083 T* GetObjectForIndex(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_);
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -070084};
Narayan Kamathc38a6f82016-09-29 17:07:20 +010085
Vladimir Markof44d36c2017-03-14 14:18:46 +000086template <typename T> struct PACKED(2 * __SIZEOF_POINTER__) NativeDexCachePair {
87 T* object;
88 size_t index;
89 // This is similar to DexCachePair except that we're storing a native pointer
90 // instead of a GC root. See DexCachePair for the details.
91 NativeDexCachePair(T* object, uint32_t index)
92 : object(object),
93 index(index) {}
94 NativeDexCachePair() : object(nullptr), index(0u) { }
95 NativeDexCachePair(const NativeDexCachePair<T>&) = default;
96 NativeDexCachePair& operator=(const NativeDexCachePair<T>&) = default;
97
98 static void Initialize(std::atomic<NativeDexCachePair<T>>* dex_cache, PointerSize pointer_size);
99
100 static uint32_t InvalidIndexForSlot(uint32_t slot) {
101 // Since the cache size is a power of two, 0 will always map to slot 0.
102 // Use 1 for slot 0 and 0 for all other slots.
103 return (slot == 0) ? 1u : 0u;
104 }
105
106 T* GetObjectForIndex(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_) {
107 if (idx != index) {
108 return nullptr;
109 }
110 DCHECK(object != nullptr);
111 return object;
112 }
113};
114
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000115using TypeDexCachePair = DexCachePair<Class>;
116using TypeDexCacheType = std::atomic<TypeDexCachePair>;
117
118using StringDexCachePair = DexCachePair<String>;
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -0700119using StringDexCacheType = std::atomic<StringDexCachePair>;
120
Vladimir Markof44d36c2017-03-14 14:18:46 +0000121using FieldDexCachePair = NativeDexCachePair<ArtField>;
122using FieldDexCacheType = std::atomic<FieldDexCachePair>;
123
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100124using MethodDexCachePair = NativeDexCachePair<ArtMethod>;
125using MethodDexCacheType = std::atomic<MethodDexCachePair>;
126
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000127using MethodTypeDexCachePair = DexCachePair<MethodType>;
Narayan Kamath25352fc2016-08-03 12:46:58 +0100128using MethodTypeDexCacheType = std::atomic<MethodTypeDexCachePair>;
129
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700130// C++ mirror of java.lang.DexCache.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100131class MANAGED DexCache final : public Object {
Brian Carlstrom83db7722011-08-26 17:32:56 -0700132 public:
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700133 // Size of java.lang.DexCache.class.
Andreas Gampe542451c2016-07-26 09:02:02 -0700134 static uint32_t ClassSize(PointerSize pointer_size);
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700135
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000136 // Size of type dex cache. Needs to be a power of 2 for entrypoint assumptions to hold.
137 static constexpr size_t kDexCacheTypeCacheSize = 1024;
138 static_assert(IsPowerOfTwo(kDexCacheTypeCacheSize),
139 "Type dex cache size is not a power of 2.");
140
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -0700141 // Size of string dex cache. Needs to be a power of 2 for entrypoint assumptions to hold.
142 static constexpr size_t kDexCacheStringCacheSize = 1024;
143 static_assert(IsPowerOfTwo(kDexCacheStringCacheSize),
144 "String dex cache size is not a power of 2.");
145
Vladimir Markof44d36c2017-03-14 14:18:46 +0000146 // Size of field dex cache. Needs to be a power of 2 for entrypoint assumptions to hold.
Vladimir Marko990fc442018-08-29 13:58:23 +0000147 static constexpr size_t kDexCacheFieldCacheSize = 1024;
Vladimir Markof44d36c2017-03-14 14:18:46 +0000148 static_assert(IsPowerOfTwo(kDexCacheFieldCacheSize),
149 "Field dex cache size is not a power of 2.");
150
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100151 // Size of method dex cache. Needs to be a power of 2 for entrypoint assumptions to hold.
Vladimir Marko990fc442018-08-29 13:58:23 +0000152 static constexpr size_t kDexCacheMethodCacheSize = 1024;
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100153 static_assert(IsPowerOfTwo(kDexCacheMethodCacheSize),
154 "Method dex cache size is not a power of 2.");
155
Narayan Kamath25352fc2016-08-03 12:46:58 +0100156 // Size of method type dex cache. Needs to be a power of 2 for entrypoint assumptions
157 // to hold.
158 static constexpr size_t kDexCacheMethodTypeCacheSize = 1024;
159 static_assert(IsPowerOfTwo(kDexCacheMethodTypeCacheSize),
160 "MethodType dex cache size is not a power of 2.");
161
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000162 static constexpr size_t StaticTypeSize() {
163 return kDexCacheTypeCacheSize;
164 }
165
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -0700166 static constexpr size_t StaticStringSize() {
167 return kDexCacheStringCacheSize;
168 }
169
Vladimir Markof44d36c2017-03-14 14:18:46 +0000170 static constexpr size_t StaticArtFieldSize() {
171 return kDexCacheFieldCacheSize;
172 }
173
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100174 static constexpr size_t StaticMethodSize() {
175 return kDexCacheMethodCacheSize;
176 }
177
Narayan Kamath25352fc2016-08-03 12:46:58 +0100178 static constexpr size_t StaticMethodTypeSize() {
179 return kDexCacheMethodTypeCacheSize;
180 }
181
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700182 // Size of an instance of java.lang.DexCache not including referenced values.
183 static constexpr uint32_t InstanceSize() {
184 return sizeof(DexCache);
185 }
186
Andreas Gampecc1b5352016-12-01 16:58:38 -0800187 static void InitializeDexCache(Thread* self,
188 ObjPtr<mirror::DexCache> dex_cache,
189 ObjPtr<mirror::String> location,
190 const DexFile* dex_file,
191 LinearAlloc* linear_alloc,
192 PointerSize image_pointer_size)
193 REQUIRES_SHARED(Locks::mutator_lock_)
194 REQUIRES(Locks::dex_lock_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700195
Mathieu Chartier60bc39c2016-01-27 18:37:48 -0800196 template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -0700197 void FixupStrings(StringDexCacheType* dest, const Visitor& visitor)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700198 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800199
Mathieu Chartier60bc39c2016-01-27 18:37:48 -0800200 template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000201 void FixupResolvedTypes(TypeDexCacheType* dest, const Visitor& visitor)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700202 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800203
Narayan Kamath7fe56582016-10-14 18:49:12 +0100204 template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
205 void FixupResolvedMethodTypes(MethodTypeDexCacheType* dest, const Visitor& visitor)
206 REQUIRES_SHARED(Locks::mutator_lock_);
207
Orion Hodsonc069a302017-01-18 09:23:12 +0000208 template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
209 void FixupResolvedCallSites(GcRoot<mirror::CallSite>* dest, const Visitor& visitor)
210 REQUIRES_SHARED(Locks::mutator_lock_);
211
Vladimir Marko58412b12019-04-01 13:26:34 +0100212 ObjPtr<String> GetLocation() REQUIRES_SHARED(Locks::mutator_lock_);
Brian Carlstroma663ea52011-08-19 23:33:41 -0700213
David Srbecky56de89a2018-10-01 15:32:20 +0100214 static constexpr MemberOffset StringsOffset() {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700215 return OFFSET_OF_OBJECT_MEMBER(DexCache, strings_);
buzbeec5ef0462011-08-25 18:44:49 -0700216 }
217
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700218 static constexpr MemberOffset PreResolvedStringsOffset() {
219 return OFFSET_OF_OBJECT_MEMBER(DexCache, preresolved_strings_);
220 }
221
David Srbecky56de89a2018-10-01 15:32:20 +0100222 static constexpr MemberOffset ResolvedTypesOffset() {
Vladimir Marko05792b92015-08-03 11:56:49 +0100223 return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_);
224 }
225
David Srbecky56de89a2018-10-01 15:32:20 +0100226 static constexpr MemberOffset ResolvedFieldsOffset() {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700227 return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_fields_);
buzbeec5ef0462011-08-25 18:44:49 -0700228 }
229
David Srbecky56de89a2018-10-01 15:32:20 +0100230 static constexpr MemberOffset ResolvedMethodsOffset() {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700231 return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_methods_);
buzbeec5ef0462011-08-25 18:44:49 -0700232 }
233
David Srbecky56de89a2018-10-01 15:32:20 +0100234 static constexpr MemberOffset ResolvedMethodTypesOffset() {
Narayan Kamath25352fc2016-08-03 12:46:58 +0100235 return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_method_types_);
236 }
237
David Srbecky56de89a2018-10-01 15:32:20 +0100238 static constexpr MemberOffset ResolvedCallSitesOffset() {
Orion Hodsonc069a302017-01-18 09:23:12 +0000239 return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_call_sites_);
240 }
241
David Srbecky56de89a2018-10-01 15:32:20 +0100242 static constexpr MemberOffset NumStringsOffset() {
Vladimir Marko05792b92015-08-03 11:56:49 +0100243 return OFFSET_OF_OBJECT_MEMBER(DexCache, num_strings_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700244 }
245
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700246 static constexpr MemberOffset NumPreResolvedStringsOffset() {
247 return OFFSET_OF_OBJECT_MEMBER(DexCache, num_preresolved_strings_);
248 }
249
David Srbecky56de89a2018-10-01 15:32:20 +0100250 static constexpr MemberOffset NumResolvedTypesOffset() {
Vladimir Marko05792b92015-08-03 11:56:49 +0100251 return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_types_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700252 }
253
David Srbecky56de89a2018-10-01 15:32:20 +0100254 static constexpr MemberOffset NumResolvedFieldsOffset() {
Vladimir Marko05792b92015-08-03 11:56:49 +0100255 return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_fields_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700256 }
257
David Srbecky56de89a2018-10-01 15:32:20 +0100258 static constexpr MemberOffset NumResolvedMethodsOffset() {
Vladimir Marko05792b92015-08-03 11:56:49 +0100259 return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_methods_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700260 }
261
David Srbecky56de89a2018-10-01 15:32:20 +0100262 static constexpr MemberOffset NumResolvedMethodTypesOffset() {
Narayan Kamath25352fc2016-08-03 12:46:58 +0100263 return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_method_types_);
264 }
265
David Srbecky56de89a2018-10-01 15:32:20 +0100266 static constexpr MemberOffset NumResolvedCallSitesOffset() {
Orion Hodsonc069a302017-01-18 09:23:12 +0000267 return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_call_sites_);
268 }
269
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700270 static constexpr size_t PreResolvedStringsAlignment() {
271 return alignof(GcRoot<mirror::String>);
272 }
273
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000274 String* GetResolvedString(dex::StringIndex string_idx) ALWAYS_INLINE
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700275 REQUIRES_SHARED(Locks::mutator_lock_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700276
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800277 void SetResolvedString(dex::StringIndex string_idx, ObjPtr<mirror::String> resolved) ALWAYS_INLINE
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700278 REQUIRES_SHARED(Locks::mutator_lock_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700279
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700280 void SetPreResolvedString(dex::StringIndex string_idx,
281 ObjPtr<mirror::String> resolved)
282 ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_);
283
Mathieu Chartier6e7a72c2019-03-07 21:40:10 -0800284 // Clear the preresolved string cache to prevent further usage.
Mathieu Chartiera88abfa2019-02-04 11:08:29 -0800285 void ClearPreResolvedStrings()
286 ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_);
287
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700288 // Clear a string for a string_idx, used to undo string intern transactions to make sure
289 // the string isn't kept live.
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800290 void ClearString(dex::StringIndex string_idx) REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700291
Andreas Gampea5b09a62016-11-17 15:21:22 -0800292 Class* GetResolvedType(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Marko05792b92015-08-03 11:56:49 +0100293
Andreas Gampea5b09a62016-11-17 15:21:22 -0800294 void SetResolvedType(dex::TypeIndex type_idx, ObjPtr<Class> resolved)
Mathieu Chartier31e88222016-10-14 18:43:19 -0700295 REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Marko05792b92015-08-03 11:56:49 +0100296
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000297 void ClearResolvedType(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
298
Andreas Gampe542451c2016-07-26 09:02:02 -0700299 ALWAYS_INLINE ArtMethod* GetResolvedMethod(uint32_t method_idx, PointerSize ptr_size)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700300 REQUIRES_SHARED(Locks::mutator_lock_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700301
Andreas Gampe542451c2016-07-26 09:02:02 -0700302 ALWAYS_INLINE void SetResolvedMethod(uint32_t method_idx,
303 ArtMethod* resolved,
304 PointerSize ptr_size)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700305 REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100306 ALWAYS_INLINE void ClearResolvedMethod(uint32_t method_idx, PointerSize ptr_size)
307 REQUIRES_SHARED(Locks::mutator_lock_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700308
Mathieu Chartierc7853442015-03-27 14:35:38 -0700309 // Pointer sized variant, used for patching.
Andreas Gampe542451c2016-07-26 09:02:02 -0700310 ALWAYS_INLINE ArtField* GetResolvedField(uint32_t idx, PointerSize ptr_size)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700311 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700312
313 // Pointer sized variant, used for patching.
Andreas Gampe542451c2016-07-26 09:02:02 -0700314 ALWAYS_INLINE void SetResolvedField(uint32_t idx, ArtField* field, PointerSize ptr_size)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700315 REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Markof44d36c2017-03-14 14:18:46 +0000316 ALWAYS_INLINE void ClearResolvedField(uint32_t idx, PointerSize ptr_size)
317 REQUIRES_SHARED(Locks::mutator_lock_);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700318
Orion Hodson06d10a72018-05-14 08:53:38 +0100319 MethodType* GetResolvedMethodType(dex::ProtoIndex proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
Narayan Kamath25352fc2016-08-03 12:46:58 +0100320
Orion Hodson06d10a72018-05-14 08:53:38 +0100321 void SetResolvedMethodType(dex::ProtoIndex proto_idx, MethodType* resolved)
Orion Hodsonc069a302017-01-18 09:23:12 +0000322 REQUIRES_SHARED(Locks::mutator_lock_);
323
324 CallSite* GetResolvedCallSite(uint32_t call_site_idx) REQUIRES_SHARED(Locks::mutator_lock_);
325
326 // Attempts to bind |call_site_idx| to the call site |resolved|. The
327 // caller must use the return value in place of |resolved|. This is
328 // because multiple threads can invoke the bootstrap method each
329 // producing a call site, but the method handle invocation on the
330 // call site must be on a common agreed value.
Orion Hodson4c8e12e2018-05-18 08:33:20 +0100331 ObjPtr<CallSite> SetResolvedCallSite(uint32_t call_site_idx, ObjPtr<CallSite> resolved)
332 REQUIRES_SHARED(Locks::mutator_lock_) WARN_UNUSED;
Narayan Kamath25352fc2016-08-03 12:46:58 +0100333
Vladimir Marko98db89c2018-09-07 11:45:46 +0100334 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700335 StringDexCacheType* GetStrings() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko98db89c2018-09-07 11:45:46 +0100336 return GetFieldPtr64<StringDexCacheType*, kVerifyFlags>(StringsOffset());
Brian Carlstrom1caa2c22011-08-28 13:02:33 -0700337 }
Brian Carlstrom83db7722011-08-26 17:32:56 -0700338
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700339 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
340 GcRoot<mirror::String>* GetPreResolvedStrings() ALWAYS_INLINE
341 REQUIRES_SHARED(Locks::mutator_lock_) {
342 return GetFieldPtr64<GcRoot<mirror::String>*, kVerifyFlags>(PreResolvedStringsOffset());
343 }
344
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700345 void SetStrings(StringDexCacheType* strings) ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800346 SetFieldPtr<false>(StringsOffset(), strings);
347 }
348
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700349 void SetPreResolvedStrings(GcRoot<mirror::String>* strings)
350 ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
351 SetFieldPtr<false>(PreResolvedStringsOffset(), strings);
352 }
353
Vladimir Marko98db89c2018-09-07 11:45:46 +0100354 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000355 TypeDexCacheType* GetResolvedTypes() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko98db89c2018-09-07 11:45:46 +0100356 return GetFieldPtr<TypeDexCacheType*, kVerifyFlags>(ResolvedTypesOffset());
Mathieu Chartier66f19252012-09-18 08:57:04 -0700357 }
358
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000359 void SetResolvedTypes(TypeDexCacheType* resolved_types)
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800360 ALWAYS_INLINE
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700361 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800362 SetFieldPtr<false>(ResolvedTypesOffset(), resolved_types);
363 }
364
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100365 MethodDexCacheType* GetResolvedMethods() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
366 return GetFieldPtr<MethodDexCacheType*>(ResolvedMethodsOffset());
Mathieu Chartier66f19252012-09-18 08:57:04 -0700367 }
368
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100369 void SetResolvedMethods(MethodDexCacheType* resolved_methods)
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800370 ALWAYS_INLINE
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700371 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800372 SetFieldPtr<false>(ResolvedMethodsOffset(), resolved_methods);
373 }
374
Vladimir Markof44d36c2017-03-14 14:18:46 +0000375 FieldDexCacheType* GetResolvedFields() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
376 return GetFieldPtr<FieldDexCacheType*>(ResolvedFieldsOffset());
Vladimir Marko05792b92015-08-03 11:56:49 +0100377 }
378
Vladimir Markof44d36c2017-03-14 14:18:46 +0000379 void SetResolvedFields(FieldDexCacheType* resolved_fields)
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800380 ALWAYS_INLINE
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700381 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800382 SetFieldPtr<false>(ResolvedFieldsOffset(), resolved_fields);
383 }
384
Vladimir Marko98db89c2018-09-07 11:45:46 +0100385 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Narayan Kamath25352fc2016-08-03 12:46:58 +0100386 MethodTypeDexCacheType* GetResolvedMethodTypes()
387 ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko98db89c2018-09-07 11:45:46 +0100388 return GetFieldPtr64<MethodTypeDexCacheType*, kVerifyFlags>(ResolvedMethodTypesOffset());
Narayan Kamath25352fc2016-08-03 12:46:58 +0100389 }
390
391 void SetResolvedMethodTypes(MethodTypeDexCacheType* resolved_method_types)
392 ALWAYS_INLINE
393 REQUIRES_SHARED(Locks::mutator_lock_) {
394 SetFieldPtr<false>(ResolvedMethodTypesOffset(), resolved_method_types);
395 }
396
Vladimir Marko98db89c2018-09-07 11:45:46 +0100397 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Orion Hodsonc069a302017-01-18 09:23:12 +0000398 GcRoot<CallSite>* GetResolvedCallSites()
399 ALWAYS_INLINE
400 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko98db89c2018-09-07 11:45:46 +0100401 return GetFieldPtr<GcRoot<CallSite>*, kVerifyFlags>(ResolvedCallSitesOffset());
Orion Hodsonc069a302017-01-18 09:23:12 +0000402 }
403
404 void SetResolvedCallSites(GcRoot<CallSite>* resolved_call_sites)
405 ALWAYS_INLINE
406 REQUIRES_SHARED(Locks::mutator_lock_) {
407 SetFieldPtr<false>(ResolvedCallSitesOffset(), resolved_call_sites);
408 }
409
Vladimir Marko98db89c2018-09-07 11:45:46 +0100410 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700411 size_t NumStrings() REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko98db89c2018-09-07 11:45:46 +0100412 return GetField32<kVerifyFlags>(NumStringsOffset());
Vladimir Marko05792b92015-08-03 11:56:49 +0100413 }
414
Vladimir Marko98db89c2018-09-07 11:45:46 +0100415 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700416 size_t NumPreResolvedStrings() REQUIRES_SHARED(Locks::mutator_lock_) {
417 return GetField32<kVerifyFlags>(NumPreResolvedStringsOffset());
418 }
419
420 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700421 size_t NumResolvedTypes() REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko98db89c2018-09-07 11:45:46 +0100422 return GetField32<kVerifyFlags>(NumResolvedTypesOffset());
Vladimir Marko05792b92015-08-03 11:56:49 +0100423 }
424
Vladimir Marko924ad502018-09-19 09:48:04 +0100425 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700426 size_t NumResolvedMethods() REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko924ad502018-09-19 09:48:04 +0100427 return GetField32<kVerifyFlags>(NumResolvedMethodsOffset());
Vladimir Marko05792b92015-08-03 11:56:49 +0100428 }
429
Vladimir Marko924ad502018-09-19 09:48:04 +0100430 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700431 size_t NumResolvedFields() REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko924ad502018-09-19 09:48:04 +0100432 return GetField32<kVerifyFlags>(NumResolvedFieldsOffset());
Mathieu Chartier66f19252012-09-18 08:57:04 -0700433 }
434
Vladimir Marko98db89c2018-09-07 11:45:46 +0100435 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Narayan Kamath25352fc2016-08-03 12:46:58 +0100436 size_t NumResolvedMethodTypes() REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko98db89c2018-09-07 11:45:46 +0100437 return GetField32<kVerifyFlags>(NumResolvedMethodTypesOffset());
Narayan Kamath25352fc2016-08-03 12:46:58 +0100438 }
439
Vladimir Marko98db89c2018-09-07 11:45:46 +0100440 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Orion Hodsonc069a302017-01-18 09:23:12 +0000441 size_t NumResolvedCallSites() REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko98db89c2018-09-07 11:45:46 +0100442 return GetField32<kVerifyFlags>(NumResolvedCallSitesOffset());
Orion Hodsonc069a302017-01-18 09:23:12 +0000443 }
444
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700445 const DexFile* GetDexFile() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700446 return GetFieldPtr<const DexFile*>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_));
Mathieu Chartier66f19252012-09-18 08:57:04 -0700447 }
448
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700449 void SetDexFile(const DexFile* dex_file) REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier76172162016-01-26 14:54:06 -0800450 SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file);
Brian Carlstrom4b620ff2011-09-11 01:11:01 -0700451 }
Brian Carlstromc4fa2c02011-08-21 03:00:12 -0700452
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000453 void SetLocation(ObjPtr<String> location) REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier76172162016-01-26 14:54:06 -0800454
Vladimir Markof44d36c2017-03-14 14:18:46 +0000455 template <typename T>
456 static NativeDexCachePair<T> GetNativePairPtrSize(std::atomic<NativeDexCachePair<T>>* pair_array,
457 size_t idx,
458 PointerSize ptr_size);
459
460 template <typename T>
461 static void SetNativePairPtrSize(std::atomic<NativeDexCachePair<T>>* pair_array,
462 size_t idx,
463 NativeDexCachePair<T> pair,
464 PointerSize ptr_size);
465
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700466 static size_t PreResolvedStringsSize(size_t num_strings) {
467 return sizeof(GcRoot<mirror::String>) * num_strings;
468 }
469
Vladimir Markof25cc732017-03-16 16:18:15 +0000470 uint32_t StringSlotIndex(dex::StringIndex string_idx) REQUIRES_SHARED(Locks::mutator_lock_);
471 uint32_t TypeSlotIndex(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
472 uint32_t FieldSlotIndex(uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100473 uint32_t MethodSlotIndex(uint32_t method_idx) REQUIRES_SHARED(Locks::mutator_lock_);
Orion Hodson06d10a72018-05-14 08:53:38 +0100474 uint32_t MethodTypeSlotIndex(dex::ProtoIndex proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Markof25cc732017-03-16 16:18:15 +0000475
Mathieu Chartier3ffb5b12019-06-06 14:23:03 -0700476 // Returns true if we succeeded in adding the pre-resolved string array.
477 bool AddPreResolvedStringsArray() REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700478
Brian Carlstromc4fa2c02011-08-21 03:00:12 -0700479 private:
Andreas Gampecc1b5352016-12-01 16:58:38 -0800480 void Init(const DexFile* dex_file,
481 ObjPtr<String> location,
482 StringDexCacheType* strings,
483 uint32_t num_strings,
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000484 TypeDexCacheType* resolved_types,
Andreas Gampecc1b5352016-12-01 16:58:38 -0800485 uint32_t num_resolved_types,
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100486 MethodDexCacheType* resolved_methods,
Andreas Gampecc1b5352016-12-01 16:58:38 -0800487 uint32_t num_resolved_methods,
Vladimir Markof44d36c2017-03-14 14:18:46 +0000488 FieldDexCacheType* resolved_fields,
Andreas Gampecc1b5352016-12-01 16:58:38 -0800489 uint32_t num_resolved_fields,
Orion Hodsonc069a302017-01-18 09:23:12 +0000490 MethodTypeDexCacheType* resolved_method_types,
491 uint32_t num_resolved_method_types,
492 GcRoot<CallSite>* resolved_call_sites,
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100493 uint32_t num_resolved_call_sites)
Andreas Gampecc1b5352016-12-01 16:58:38 -0800494 REQUIRES_SHARED(Locks::mutator_lock_);
495
Vladimir Markof44d36c2017-03-14 14:18:46 +0000496 // std::pair<> is not trivially copyable and as such it is unsuitable for atomic operations,
497 // so we use a custom pair class for loading and storing the NativeDexCachePair<>.
498 template <typename IntType>
499 struct PACKED(2 * sizeof(IntType)) ConversionPair {
500 ConversionPair(IntType f, IntType s) : first(f), second(s) { }
501 ConversionPair(const ConversionPair&) = default;
502 ConversionPair& operator=(const ConversionPair&) = default;
503 IntType first;
504 IntType second;
505 };
506 using ConversionPair32 = ConversionPair<uint32_t>;
507 using ConversionPair64 = ConversionPair<uint64_t>;
508
Vladimir Marko05792b92015-08-03 11:56:49 +0100509 // Visit instance fields of the dex cache as well as its associated arrays.
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800510 template <bool kVisitNativeRoots,
511 VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
512 ReadBarrierOption kReadBarrierOption = kWithReadBarrier,
513 typename Visitor>
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000514 void VisitReferences(ObjPtr<Class> klass, const Visitor& visitor)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700515 REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_);
Vladimir Marko05792b92015-08-03 11:56:49 +0100516
Vladimir Markof44d36c2017-03-14 14:18:46 +0000517 // Due to lack of 16-byte atomics support, we use hand-crafted routines.
Alexey Frunze279cfba2017-07-22 00:24:43 -0700518#if defined(__aarch64__) || defined(__mips__)
519 // 16-byte atomics are supported on aarch64, mips and mips64.
Vladimir Markof44d36c2017-03-14 14:18:46 +0000520 ALWAYS_INLINE static ConversionPair64 AtomicLoadRelaxed16B(
521 std::atomic<ConversionPair64>* target) {
522 return target->load(std::memory_order_relaxed);
523 }
524
525 ALWAYS_INLINE static void AtomicStoreRelease16B(
526 std::atomic<ConversionPair64>* target, ConversionPair64 value) {
527 target->store(value, std::memory_order_release);
528 }
529#elif defined(__x86_64__)
530 ALWAYS_INLINE static ConversionPair64 AtomicLoadRelaxed16B(
531 std::atomic<ConversionPair64>* target) {
532 uint64_t first, second;
533 __asm__ __volatile__(
534 "lock cmpxchg16b (%2)"
535 : "=&a"(first), "=&d"(second)
536 : "r"(target), "a"(0), "d"(0), "b"(0), "c"(0)
537 : "cc");
538 return ConversionPair64(first, second);
539 }
540
541 ALWAYS_INLINE static void AtomicStoreRelease16B(
542 std::atomic<ConversionPair64>* target, ConversionPair64 value) {
543 uint64_t first, second;
544 __asm__ __volatile__ (
545 "movq (%2), %%rax\n\t"
546 "movq 8(%2), %%rdx\n\t"
547 "1:\n\t"
548 "lock cmpxchg16b (%2)\n\t"
549 "jnz 1b"
550 : "=&a"(first), "=&d"(second)
551 : "r"(target), "b"(value.first), "c"(value.second)
552 : "cc");
553 }
554#else
555 static ConversionPair64 AtomicLoadRelaxed16B(std::atomic<ConversionPair64>* target);
556 static void AtomicStoreRelease16B(std::atomic<ConversionPair64>* target, ConversionPair64 value);
557#endif
558
Ian Rogersef7d42f2014-01-06 12:55:46 -0800559 HeapReference<String> location_;
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700560 // Number of elements in the preresolved_strings_ array. Note that this appears here because of
561 // our packing logic for 32 bit fields.
562 uint32_t num_preresolved_strings_;
Narayan Kamath6b2dc312017-03-14 13:26:12 +0000563
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700564 uint64_t dex_file_; // const DexFile*
565 uint64_t preresolved_strings_; // GcRoot<mirror::String*> array with num_preresolved_strings
566 // elements.
567 uint64_t resolved_call_sites_; // GcRoot<CallSite>* array with num_resolved_call_sites_
568 // elements.
569 uint64_t resolved_fields_; // std::atomic<FieldDexCachePair>*, array with
570 // num_resolved_fields_ elements.
571 uint64_t resolved_method_types_; // std::atomic<MethodTypeDexCachePair>* array with
572 // num_resolved_method_types_ elements.
573 uint64_t resolved_methods_; // ArtMethod*, array with num_resolved_methods_ elements.
574 uint64_t resolved_types_; // TypeDexCacheType*, array with num_resolved_types_ elements.
575 uint64_t strings_; // std::atomic<StringDexCachePair>*, array with num_strings_
576 // elements.
Narayan Kamath25352fc2016-08-03 12:46:58 +0100577
Mathieu Chartier1ca718e2018-10-23 12:55:34 -0700578 uint32_t num_resolved_call_sites_; // Number of elements in the call_sites_ array.
Narayan Kamath25352fc2016-08-03 12:46:58 +0100579 uint32_t num_resolved_fields_; // Number of elements in the resolved_fields_ array.
580 uint32_t num_resolved_method_types_; // Number of elements in the resolved_method_types_ array.
581 uint32_t num_resolved_methods_; // Number of elements in the resolved_methods_ array.
582 uint32_t num_resolved_types_; // Number of elements in the resolved_types_ array.
583 uint32_t num_strings_; // Number of elements in the strings_ array.
Brian Carlstrom83db7722011-08-26 17:32:56 -0700584
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700585 friend struct art::DexCacheOffsets; // for verifying offset information
Vladimir Markoca8de0a2018-07-04 11:56:08 +0100586 friend class linker::ImageWriter;
Vladimir Marko05792b92015-08-03 11:56:49 +0100587 friend class Object; // For VisitReferences
Brian Carlstromc4fa2c02011-08-21 03:00:12 -0700588 DISALLOW_IMPLICIT_CONSTRUCTORS(DexCache);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700589};
590
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800591} // namespace mirror
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700592} // namespace art
593
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700594#endif // ART_RUNTIME_MIRROR_DEX_CACHE_H_