1 /*
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  */
16 
17 #ifndef ART_RUNTIME_MIRROR_DEX_CACHE_H_
18 #define ART_RUNTIME_MIRROR_DEX_CACHE_H_
19 
20 #include "array.h"
21 #include "base/bit_utils.h"
22 #include "base/mutex.h"
23 #include "dex/dex_file_types.h"
24 #include "object.h"
25 #include "object_array.h"
26 
27 namespace art {
28 
29 class ArtField;
30 class ArtMethod;
31 struct DexCacheOffsets;
32 class DexFile;
33 class ImageWriter;
34 union JValue;
35 class LinearAlloc;
36 class Thread;
37 
38 namespace mirror {
39 
40 class CallSite;
41 class Class;
42 class MethodType;
43 class String;
44 
45 template <typename T> struct PACKED(8) DexCachePair {
46   GcRoot<T> object;
47   uint32_t index;
48   // The array is initially [ {0,0}, {0,0}, {0,0} ... ]
49   // We maintain the invariant that once a dex cache entry is populated,
50   // the pointer is always non-0
51   // Any given entry would thus be:
52   // {non-0, non-0} OR {0,0}
53   //
54   // It's generally sufficiently enough then to check if the
55   // lookup index matches the stored index (for a >0 lookup index)
56   // because if it's true the pointer is also non-null.
57   //
58   // For the 0th entry which is a special case, the value is either
59   // {0,0} (initial state) or {non-0, 0} which indicates
60   // that a valid object is stored at that index for a dex section id of 0.
61   //
62   // As an optimization, we want to avoid branching on the object pointer since
63   // it's always non-null if the id branch succeeds (except for the 0th id).
64   // Set the initial state for the 0th entry to be {0,1} which is guaranteed to fail
65   // the lookup id == stored id branch.
DexCachePairDexCachePair66   DexCachePair(ObjPtr<T> object, uint32_t index)
67       : object(object),
68         index(index) {}
DexCachePairDexCachePair69   DexCachePair() : index(0) {}
70   DexCachePair(const DexCachePair<T>&) = default;
71   DexCachePair& operator=(const DexCachePair<T>&) = default;
72 
InitializeDexCachePair73   static void Initialize(std::atomic<DexCachePair<T>>* dex_cache) {
74     DexCachePair<T> first_elem;
75     first_elem.object = GcRoot<T>(nullptr);
76     first_elem.index = InvalidIndexForSlot(0);
77     dex_cache[0].store(first_elem, std::memory_order_relaxed);
78   }
79 
InvalidIndexForSlotDexCachePair80   static uint32_t InvalidIndexForSlot(uint32_t slot) {
81     // Since the cache size is a power of two, 0 will always map to slot 0.
82     // Use 1 for slot 0 and 0 for all other slots.
83     return (slot == 0) ? 1u : 0u;
84   }
85 
GetObjectForIndexDexCachePair86   T* GetObjectForIndex(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_) {
87     if (idx != index) {
88       return nullptr;
89     }
90     DCHECK(!object.IsNull());
91     return object.Read();
92   }
93 };
94 
95 template <typename T> struct PACKED(2 * __SIZEOF_POINTER__) NativeDexCachePair {
96   T* object;
97   size_t index;
98   // This is similar to DexCachePair except that we're storing a native pointer
99   // instead of a GC root. See DexCachePair for the details.
NativeDexCachePairNativeDexCachePair100   NativeDexCachePair(T* object, uint32_t index)
101       : object(object),
102         index(index) {}
NativeDexCachePairNativeDexCachePair103   NativeDexCachePair() : object(nullptr), index(0u) { }
104   NativeDexCachePair(const NativeDexCachePair<T>&) = default;
105   NativeDexCachePair& operator=(const NativeDexCachePair<T>&) = default;
106 
107   static void Initialize(std::atomic<NativeDexCachePair<T>>* dex_cache, PointerSize pointer_size);
108 
InvalidIndexForSlotNativeDexCachePair109   static uint32_t InvalidIndexForSlot(uint32_t slot) {
110     // Since the cache size is a power of two, 0 will always map to slot 0.
111     // Use 1 for slot 0 and 0 for all other slots.
112     return (slot == 0) ? 1u : 0u;
113   }
114 
GetObjectForIndexNativeDexCachePair115   T* GetObjectForIndex(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_) {
116     if (idx != index) {
117       return nullptr;
118     }
119     DCHECK(object != nullptr);
120     return object;
121   }
122 };
123 
124 using TypeDexCachePair = DexCachePair<Class>;
125 using TypeDexCacheType = std::atomic<TypeDexCachePair>;
126 
127 using StringDexCachePair = DexCachePair<String>;
128 using StringDexCacheType = std::atomic<StringDexCachePair>;
129 
130 using FieldDexCachePair = NativeDexCachePair<ArtField>;
131 using FieldDexCacheType = std::atomic<FieldDexCachePair>;
132 
133 using MethodDexCachePair = NativeDexCachePair<ArtMethod>;
134 using MethodDexCacheType = std::atomic<MethodDexCachePair>;
135 
136 using MethodTypeDexCachePair = DexCachePair<MethodType>;
137 using MethodTypeDexCacheType = std::atomic<MethodTypeDexCachePair>;
138 
139 // C++ mirror of java.lang.DexCache.
140 class MANAGED DexCache FINAL : public Object {
141  public:
142   // Size of java.lang.DexCache.class.
143   static uint32_t ClassSize(PointerSize pointer_size);
144 
145   // Size of type dex cache. Needs to be a power of 2 for entrypoint assumptions to hold.
146   static constexpr size_t kDexCacheTypeCacheSize = 1024;
147   static_assert(IsPowerOfTwo(kDexCacheTypeCacheSize),
148                 "Type dex cache size is not a power of 2.");
149 
150   // Size of string dex cache. Needs to be a power of 2 for entrypoint assumptions to hold.
151   static constexpr size_t kDexCacheStringCacheSize = 1024;
152   static_assert(IsPowerOfTwo(kDexCacheStringCacheSize),
153                 "String dex cache size is not a power of 2.");
154 
155   // Size of field dex cache. Needs to be a power of 2 for entrypoint assumptions to hold.
156   static constexpr size_t kDexCacheFieldCacheSize = 1024;
157   static_assert(IsPowerOfTwo(kDexCacheFieldCacheSize),
158                 "Field dex cache size is not a power of 2.");
159 
160   // Size of method dex cache. Needs to be a power of 2 for entrypoint assumptions to hold.
161   static constexpr size_t kDexCacheMethodCacheSize = 1024;
162   static_assert(IsPowerOfTwo(kDexCacheMethodCacheSize),
163                 "Method dex cache size is not a power of 2.");
164 
165   // Size of method type dex cache. Needs to be a power of 2 for entrypoint assumptions
166   // to hold.
167   static constexpr size_t kDexCacheMethodTypeCacheSize = 1024;
168   static_assert(IsPowerOfTwo(kDexCacheMethodTypeCacheSize),
169                 "MethodType dex cache size is not a power of 2.");
170 
StaticTypeSize()171   static constexpr size_t StaticTypeSize() {
172     return kDexCacheTypeCacheSize;
173   }
174 
StaticStringSize()175   static constexpr size_t StaticStringSize() {
176     return kDexCacheStringCacheSize;
177   }
178 
StaticArtFieldSize()179   static constexpr size_t StaticArtFieldSize() {
180     return kDexCacheFieldCacheSize;
181   }
182 
StaticMethodSize()183   static constexpr size_t StaticMethodSize() {
184     return kDexCacheMethodCacheSize;
185   }
186 
StaticMethodTypeSize()187   static constexpr size_t StaticMethodTypeSize() {
188     return kDexCacheMethodTypeCacheSize;
189   }
190 
191   // Size of an instance of java.lang.DexCache not including referenced values.
InstanceSize()192   static constexpr uint32_t InstanceSize() {
193     return sizeof(DexCache);
194   }
195 
196   static void InitializeDexCache(Thread* self,
197                                  ObjPtr<mirror::DexCache> dex_cache,
198                                  ObjPtr<mirror::String> location,
199                                  const DexFile* dex_file,
200                                  LinearAlloc* linear_alloc,
201                                  PointerSize image_pointer_size)
202       REQUIRES_SHARED(Locks::mutator_lock_)
203       REQUIRES(Locks::dex_lock_);
204 
205   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
206   void FixupStrings(StringDexCacheType* dest, const Visitor& visitor)
207       REQUIRES_SHARED(Locks::mutator_lock_);
208 
209   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
210   void FixupResolvedTypes(TypeDexCacheType* dest, const Visitor& visitor)
211       REQUIRES_SHARED(Locks::mutator_lock_);
212 
213   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
214   void FixupResolvedMethodTypes(MethodTypeDexCacheType* dest, const Visitor& visitor)
215       REQUIRES_SHARED(Locks::mutator_lock_);
216 
217   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
218   void FixupResolvedCallSites(GcRoot<mirror::CallSite>* dest, const Visitor& visitor)
219       REQUIRES_SHARED(Locks::mutator_lock_);
220 
GetLocation()221   String* GetLocation() REQUIRES_SHARED(Locks::mutator_lock_) {
222     return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_));
223   }
224 
StringsOffset()225   static MemberOffset StringsOffset() {
226     return OFFSET_OF_OBJECT_MEMBER(DexCache, strings_);
227   }
228 
ResolvedTypesOffset()229   static MemberOffset ResolvedTypesOffset() {
230     return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_);
231   }
232 
ResolvedFieldsOffset()233   static MemberOffset ResolvedFieldsOffset() {
234     return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_fields_);
235   }
236 
ResolvedMethodsOffset()237   static MemberOffset ResolvedMethodsOffset() {
238     return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_methods_);
239   }
240 
ResolvedMethodTypesOffset()241   static MemberOffset ResolvedMethodTypesOffset() {
242     return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_method_types_);
243   }
244 
ResolvedCallSitesOffset()245   static MemberOffset ResolvedCallSitesOffset() {
246     return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_call_sites_);
247   }
248 
NumStringsOffset()249   static MemberOffset NumStringsOffset() {
250     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_strings_);
251   }
252 
NumResolvedTypesOffset()253   static MemberOffset NumResolvedTypesOffset() {
254     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_types_);
255   }
256 
NumResolvedFieldsOffset()257   static MemberOffset NumResolvedFieldsOffset() {
258     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_fields_);
259   }
260 
NumResolvedMethodsOffset()261   static MemberOffset NumResolvedMethodsOffset() {
262     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_methods_);
263   }
264 
NumResolvedMethodTypesOffset()265   static MemberOffset NumResolvedMethodTypesOffset() {
266     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_method_types_);
267   }
268 
NumResolvedCallSitesOffset()269   static MemberOffset NumResolvedCallSitesOffset() {
270     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_call_sites_);
271   }
272 
273   String* GetResolvedString(dex::StringIndex string_idx) ALWAYS_INLINE
274       REQUIRES_SHARED(Locks::mutator_lock_);
275 
276   void SetResolvedString(dex::StringIndex string_idx, ObjPtr<mirror::String> resolved) ALWAYS_INLINE
277       REQUIRES_SHARED(Locks::mutator_lock_);
278 
279   // Clear a string for a string_idx, used to undo string intern transactions to make sure
280   // the string isn't kept live.
281   void ClearString(dex::StringIndex string_idx) REQUIRES_SHARED(Locks::mutator_lock_);
282 
283   Class* GetResolvedType(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
284 
285   void SetResolvedType(dex::TypeIndex type_idx, ObjPtr<Class> resolved)
286       REQUIRES_SHARED(Locks::mutator_lock_);
287 
288   void ClearResolvedType(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
289 
290   ALWAYS_INLINE ArtMethod* GetResolvedMethod(uint32_t method_idx, PointerSize ptr_size)
291       REQUIRES_SHARED(Locks::mutator_lock_);
292 
293   ALWAYS_INLINE void SetResolvedMethod(uint32_t method_idx,
294                                        ArtMethod* resolved,
295                                        PointerSize ptr_size)
296       REQUIRES_SHARED(Locks::mutator_lock_);
297   ALWAYS_INLINE void ClearResolvedMethod(uint32_t method_idx, PointerSize ptr_size)
298       REQUIRES_SHARED(Locks::mutator_lock_);
299 
300   // Pointer sized variant, used for patching.
301   ALWAYS_INLINE ArtField* GetResolvedField(uint32_t idx, PointerSize ptr_size)
302       REQUIRES_SHARED(Locks::mutator_lock_);
303 
304   // Pointer sized variant, used for patching.
305   ALWAYS_INLINE void SetResolvedField(uint32_t idx, ArtField* field, PointerSize ptr_size)
306       REQUIRES_SHARED(Locks::mutator_lock_);
307   ALWAYS_INLINE void ClearResolvedField(uint32_t idx, PointerSize ptr_size)
308       REQUIRES_SHARED(Locks::mutator_lock_);
309 
310   MethodType* GetResolvedMethodType(uint32_t proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
311 
312   void SetResolvedMethodType(uint32_t proto_idx, MethodType* resolved)
313       REQUIRES_SHARED(Locks::mutator_lock_);
314 
315   CallSite* GetResolvedCallSite(uint32_t call_site_idx) REQUIRES_SHARED(Locks::mutator_lock_);
316 
317   // Attempts to bind |call_site_idx| to the call site |resolved|. The
318   // caller must use the return value in place of |resolved|. This is
319   // because multiple threads can invoke the bootstrap method each
320   // producing a call site, but the method handle invocation on the
321   // call site must be on a common agreed value.
322   CallSite* SetResolvedCallSite(uint32_t call_site_idx, CallSite* resolved) WARN_UNUSED
323       REQUIRES_SHARED(Locks::mutator_lock_);
324 
GetStrings()325   StringDexCacheType* GetStrings() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
326     return GetFieldPtr64<StringDexCacheType*>(StringsOffset());
327   }
328 
SetStrings(StringDexCacheType * strings)329   void SetStrings(StringDexCacheType* strings) ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
330     SetFieldPtr<false>(StringsOffset(), strings);
331   }
332 
GetResolvedTypes()333   TypeDexCacheType* GetResolvedTypes() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
334     return GetFieldPtr<TypeDexCacheType*>(ResolvedTypesOffset());
335   }
336 
SetResolvedTypes(TypeDexCacheType * resolved_types)337   void SetResolvedTypes(TypeDexCacheType* resolved_types)
338       ALWAYS_INLINE
339       REQUIRES_SHARED(Locks::mutator_lock_) {
340     SetFieldPtr<false>(ResolvedTypesOffset(), resolved_types);
341   }
342 
GetResolvedMethods()343   MethodDexCacheType* GetResolvedMethods() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
344     return GetFieldPtr<MethodDexCacheType*>(ResolvedMethodsOffset());
345   }
346 
SetResolvedMethods(MethodDexCacheType * resolved_methods)347   void SetResolvedMethods(MethodDexCacheType* resolved_methods)
348       ALWAYS_INLINE
349       REQUIRES_SHARED(Locks::mutator_lock_) {
350     SetFieldPtr<false>(ResolvedMethodsOffset(), resolved_methods);
351   }
352 
GetResolvedFields()353   FieldDexCacheType* GetResolvedFields() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
354     return GetFieldPtr<FieldDexCacheType*>(ResolvedFieldsOffset());
355   }
356 
SetResolvedFields(FieldDexCacheType * resolved_fields)357   void SetResolvedFields(FieldDexCacheType* resolved_fields)
358       ALWAYS_INLINE
359       REQUIRES_SHARED(Locks::mutator_lock_) {
360     SetFieldPtr<false>(ResolvedFieldsOffset(), resolved_fields);
361   }
362 
GetResolvedMethodTypes()363   MethodTypeDexCacheType* GetResolvedMethodTypes()
364       ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
365     return GetFieldPtr64<MethodTypeDexCacheType*>(ResolvedMethodTypesOffset());
366   }
367 
SetResolvedMethodTypes(MethodTypeDexCacheType * resolved_method_types)368   void SetResolvedMethodTypes(MethodTypeDexCacheType* resolved_method_types)
369       ALWAYS_INLINE
370       REQUIRES_SHARED(Locks::mutator_lock_) {
371     SetFieldPtr<false>(ResolvedMethodTypesOffset(), resolved_method_types);
372   }
373 
GetResolvedCallSites()374   GcRoot<CallSite>* GetResolvedCallSites()
375       ALWAYS_INLINE
376       REQUIRES_SHARED(Locks::mutator_lock_) {
377     return GetFieldPtr<GcRoot<CallSite>*>(ResolvedCallSitesOffset());
378   }
379 
SetResolvedCallSites(GcRoot<CallSite> * resolved_call_sites)380   void SetResolvedCallSites(GcRoot<CallSite>* resolved_call_sites)
381       ALWAYS_INLINE
382       REQUIRES_SHARED(Locks::mutator_lock_) {
383     SetFieldPtr<false>(ResolvedCallSitesOffset(), resolved_call_sites);
384   }
385 
NumStrings()386   size_t NumStrings() REQUIRES_SHARED(Locks::mutator_lock_) {
387     return GetField32(NumStringsOffset());
388   }
389 
NumResolvedTypes()390   size_t NumResolvedTypes() REQUIRES_SHARED(Locks::mutator_lock_) {
391     return GetField32(NumResolvedTypesOffset());
392   }
393 
NumResolvedMethods()394   size_t NumResolvedMethods() REQUIRES_SHARED(Locks::mutator_lock_) {
395     return GetField32(NumResolvedMethodsOffset());
396   }
397 
NumResolvedFields()398   size_t NumResolvedFields() REQUIRES_SHARED(Locks::mutator_lock_) {
399     return GetField32(NumResolvedFieldsOffset());
400   }
401 
NumResolvedMethodTypes()402   size_t NumResolvedMethodTypes() REQUIRES_SHARED(Locks::mutator_lock_) {
403     return GetField32(NumResolvedMethodTypesOffset());
404   }
405 
NumResolvedCallSites()406   size_t NumResolvedCallSites() REQUIRES_SHARED(Locks::mutator_lock_) {
407     return GetField32(NumResolvedCallSitesOffset());
408   }
409 
GetDexFile()410   const DexFile* GetDexFile() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
411     return GetFieldPtr<const DexFile*>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_));
412   }
413 
SetDexFile(const DexFile * dex_file)414   void SetDexFile(const DexFile* dex_file) REQUIRES_SHARED(Locks::mutator_lock_) {
415     SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file);
416   }
417 
418   void SetLocation(ObjPtr<String> location) REQUIRES_SHARED(Locks::mutator_lock_);
419 
420   template <typename T>
421   static NativeDexCachePair<T> GetNativePairPtrSize(std::atomic<NativeDexCachePair<T>>* pair_array,
422                                                     size_t idx,
423                                                     PointerSize ptr_size);
424 
425   template <typename T>
426   static void SetNativePairPtrSize(std::atomic<NativeDexCachePair<T>>* pair_array,
427                                    size_t idx,
428                                    NativeDexCachePair<T> pair,
429                                    PointerSize ptr_size);
430 
431   uint32_t StringSlotIndex(dex::StringIndex string_idx) REQUIRES_SHARED(Locks::mutator_lock_);
432   uint32_t TypeSlotIndex(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
433   uint32_t FieldSlotIndex(uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_);
434   uint32_t MethodSlotIndex(uint32_t method_idx) REQUIRES_SHARED(Locks::mutator_lock_);
435   uint32_t MethodTypeSlotIndex(uint32_t proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
436 
437  private:
438   void Init(const DexFile* dex_file,
439             ObjPtr<String> location,
440             StringDexCacheType* strings,
441             uint32_t num_strings,
442             TypeDexCacheType* resolved_types,
443             uint32_t num_resolved_types,
444             MethodDexCacheType* resolved_methods,
445             uint32_t num_resolved_methods,
446             FieldDexCacheType* resolved_fields,
447             uint32_t num_resolved_fields,
448             MethodTypeDexCacheType* resolved_method_types,
449             uint32_t num_resolved_method_types,
450             GcRoot<CallSite>* resolved_call_sites,
451             uint32_t num_resolved_call_sites)
452       REQUIRES_SHARED(Locks::mutator_lock_);
453 
454   // std::pair<> is not trivially copyable and as such it is unsuitable for atomic operations,
455   // so we use a custom pair class for loading and storing the NativeDexCachePair<>.
456   template <typename IntType>
457   struct PACKED(2 * sizeof(IntType)) ConversionPair {
ConversionPairConversionPair458     ConversionPair(IntType f, IntType s) : first(f), second(s) { }
459     ConversionPair(const ConversionPair&) = default;
460     ConversionPair& operator=(const ConversionPair&) = default;
461     IntType first;
462     IntType second;
463   };
464   using ConversionPair32 = ConversionPair<uint32_t>;
465   using ConversionPair64 = ConversionPair<uint64_t>;
466 
467   // Visit instance fields of the dex cache as well as its associated arrays.
468   template <bool kVisitNativeRoots,
469             VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
470             ReadBarrierOption kReadBarrierOption = kWithReadBarrier,
471             typename Visitor>
472   void VisitReferences(ObjPtr<Class> klass, const Visitor& visitor)
473       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_);
474 
475   // Due to lack of 16-byte atomics support, we use hand-crafted routines.
476 #if defined(__aarch64__) || defined(__mips__)
477   // 16-byte atomics are supported on aarch64, mips and mips64.
AtomicLoadRelaxed16B(std::atomic<ConversionPair64> * target)478   ALWAYS_INLINE static ConversionPair64 AtomicLoadRelaxed16B(
479       std::atomic<ConversionPair64>* target) {
480     return target->load(std::memory_order_relaxed);
481   }
482 
AtomicStoreRelease16B(std::atomic<ConversionPair64> * target,ConversionPair64 value)483   ALWAYS_INLINE static void AtomicStoreRelease16B(
484       std::atomic<ConversionPair64>* target, ConversionPair64 value) {
485     target->store(value, std::memory_order_release);
486   }
487 #elif defined(__x86_64__)
AtomicLoadRelaxed16B(std::atomic<ConversionPair64> * target)488   ALWAYS_INLINE static ConversionPair64 AtomicLoadRelaxed16B(
489       std::atomic<ConversionPair64>* target) {
490     uint64_t first, second;
491     __asm__ __volatile__(
492         "lock cmpxchg16b (%2)"
493         : "=&a"(first), "=&d"(second)
494         : "r"(target), "a"(0), "d"(0), "b"(0), "c"(0)
495         : "cc");
496     return ConversionPair64(first, second);
497   }
498 
AtomicStoreRelease16B(std::atomic<ConversionPair64> * target,ConversionPair64 value)499   ALWAYS_INLINE static void AtomicStoreRelease16B(
500       std::atomic<ConversionPair64>* target, ConversionPair64 value) {
501     uint64_t first, second;
502     __asm__ __volatile__ (
503         "movq (%2), %%rax\n\t"
504         "movq 8(%2), %%rdx\n\t"
505         "1:\n\t"
506         "lock cmpxchg16b (%2)\n\t"
507         "jnz 1b"
508         : "=&a"(first), "=&d"(second)
509         : "r"(target), "b"(value.first), "c"(value.second)
510         : "cc");
511   }
512 #else
513   static ConversionPair64 AtomicLoadRelaxed16B(std::atomic<ConversionPair64>* target);
514   static void AtomicStoreRelease16B(std::atomic<ConversionPair64>* target, ConversionPair64 value);
515 #endif
516 
517   HeapReference<String> location_;
518   // Number of elements in the call_sites_ array. Note that this appears here
519   // because of our packing logic for 32 bit fields.
520   uint32_t num_resolved_call_sites_;
521 
522   uint64_t dex_file_;               // const DexFile*
523   uint64_t resolved_call_sites_;    // GcRoot<CallSite>* array with num_resolved_call_sites_
524                                     // elements.
525   uint64_t resolved_fields_;        // std::atomic<FieldDexCachePair>*, array with
526                                     // num_resolved_fields_ elements.
527   uint64_t resolved_method_types_;  // std::atomic<MethodTypeDexCachePair>* array with
528                                     // num_resolved_method_types_ elements.
529   uint64_t resolved_methods_;       // ArtMethod*, array with num_resolved_methods_ elements.
530   uint64_t resolved_types_;         // TypeDexCacheType*, array with num_resolved_types_ elements.
531   uint64_t strings_;                // std::atomic<StringDexCachePair>*, array with num_strings_
532                                     // elements.
533 
534   uint32_t num_resolved_fields_;        // Number of elements in the resolved_fields_ array.
535   uint32_t num_resolved_method_types_;  // Number of elements in the resolved_method_types_ array.
536   uint32_t num_resolved_methods_;       // Number of elements in the resolved_methods_ array.
537   uint32_t num_resolved_types_;         // Number of elements in the resolved_types_ array.
538   uint32_t num_strings_;                // Number of elements in the strings_ array.
539 
540   friend struct art::DexCacheOffsets;  // for verifying offset information
541   friend class Object;  // For VisitReferences
542   DISALLOW_IMPLICIT_CONSTRUCTORS(DexCache);
543 };
544 
545 }  // namespace mirror
546 }  // namespace art
547 
548 #endif  // ART_RUNTIME_MIRROR_DEX_CACHE_H_
549