Home | History | Annotate | Download | only in mirror
      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/locks.h"
     23 #include "dex/dex_file_types.h"
     24 #include "gc_root.h"  // Note: must not use -inl here to avoid circular dependency.
     25 #include "object.h"
     26 #include "object_array.h"
     27 
     28 namespace art {
     29 
     30 namespace linker {
     31 class ImageWriter;
     32 }  // namespace linker
     33 
     34 class ArtField;
     35 class ArtMethod;
     36 struct DexCacheOffsets;
     37 class DexFile;
     38 union JValue;
     39 class LinearAlloc;
     40 class Thread;
     41 
     42 namespace mirror {
     43 
     44 class CallSite;
     45 class Class;
     46 class MethodType;
     47 class String;
     48 
     49 template <typename T> struct PACKED(8) DexCachePair {
     50   GcRoot<T> object;
     51   uint32_t index;
     52   // 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
     59   // lookup index matches the stored index (for a >0 lookup index)
     60   // 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
     64   // that a valid object is stored at that index for a dex section id of 0.
     65   //
     66   // 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).
     68   // Set the initial state for the 0th entry to be {0,1} which is guaranteed to fail
     69   // the lookup id == stored id branch.
     70   DexCachePair(ObjPtr<T> object, uint32_t index);
     71   DexCachePair() : index(0) {}
     72   DexCachePair(const DexCachePair<T>&) = default;
     73   DexCachePair& operator=(const DexCachePair<T>&) = default;
     74 
     75   static void Initialize(std::atomic<DexCachePair<T>>* dex_cache);
     76 
     77   static uint32_t InvalidIndexForSlot(uint32_t slot) {
     78     // 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   }
     82 
     83   T* GetObjectForIndex(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_);
     84 };
     85 
     86 template <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 
    115 using TypeDexCachePair = DexCachePair<Class>;
    116 using TypeDexCacheType = std::atomic<TypeDexCachePair>;
    117 
    118 using StringDexCachePair = DexCachePair<String>;
    119 using StringDexCacheType = std::atomic<StringDexCachePair>;
    120 
    121 using FieldDexCachePair = NativeDexCachePair<ArtField>;
    122 using FieldDexCacheType = std::atomic<FieldDexCachePair>;
    123 
    124 using MethodDexCachePair = NativeDexCachePair<ArtMethod>;
    125 using MethodDexCacheType = std::atomic<MethodDexCachePair>;
    126 
    127 using MethodTypeDexCachePair = DexCachePair<MethodType>;
    128 using MethodTypeDexCacheType = std::atomic<MethodTypeDexCachePair>;
    129 
    130 // C++ mirror of java.lang.DexCache.
    131 class MANAGED DexCache final : public Object {
    132  public:
    133   // Size of java.lang.DexCache.class.
    134   static uint32_t ClassSize(PointerSize pointer_size);
    135 
    136   // 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 
    141   // 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 
    146   // Size of field dex cache. Needs to be a power of 2 for entrypoint assumptions to hold.
    147   static constexpr size_t kDexCacheFieldCacheSize = 1024;
    148   static_assert(IsPowerOfTwo(kDexCacheFieldCacheSize),
    149                 "Field dex cache size is not a power of 2.");
    150 
    151   // Size of method dex cache. Needs to be a power of 2 for entrypoint assumptions to hold.
    152   static constexpr size_t kDexCacheMethodCacheSize = 1024;
    153   static_assert(IsPowerOfTwo(kDexCacheMethodCacheSize),
    154                 "Method dex cache size is not a power of 2.");
    155 
    156   // 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 
    162   static constexpr size_t StaticTypeSize() {
    163     return kDexCacheTypeCacheSize;
    164   }
    165 
    166   static constexpr size_t StaticStringSize() {
    167     return kDexCacheStringCacheSize;
    168   }
    169 
    170   static constexpr size_t StaticArtFieldSize() {
    171     return kDexCacheFieldCacheSize;
    172   }
    173 
    174   static constexpr size_t StaticMethodSize() {
    175     return kDexCacheMethodCacheSize;
    176   }
    177 
    178   static constexpr size_t StaticMethodTypeSize() {
    179     return kDexCacheMethodTypeCacheSize;
    180   }
    181 
    182   // Size of an instance of java.lang.DexCache not including referenced values.
    183   static constexpr uint32_t InstanceSize() {
    184     return sizeof(DexCache);
    185   }
    186 
    187   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_);
    195 
    196   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
    197   void FixupStrings(StringDexCacheType* dest, const Visitor& visitor)
    198       REQUIRES_SHARED(Locks::mutator_lock_);
    199 
    200   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
    201   void FixupResolvedTypes(TypeDexCacheType* dest, const Visitor& visitor)
    202       REQUIRES_SHARED(Locks::mutator_lock_);
    203 
    204   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
    205   void FixupResolvedMethodTypes(MethodTypeDexCacheType* dest, const Visitor& visitor)
    206       REQUIRES_SHARED(Locks::mutator_lock_);
    207 
    208   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
    209   void FixupResolvedCallSites(GcRoot<mirror::CallSite>* dest, const Visitor& visitor)
    210       REQUIRES_SHARED(Locks::mutator_lock_);
    211 
    212   ObjPtr<String> GetLocation() REQUIRES_SHARED(Locks::mutator_lock_);
    213 
    214   static constexpr MemberOffset StringsOffset() {
    215     return OFFSET_OF_OBJECT_MEMBER(DexCache, strings_);
    216   }
    217 
    218   static constexpr MemberOffset PreResolvedStringsOffset() {
    219     return OFFSET_OF_OBJECT_MEMBER(DexCache, preresolved_strings_);
    220   }
    221 
    222   static constexpr MemberOffset ResolvedTypesOffset() {
    223     return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_);
    224   }
    225 
    226   static constexpr MemberOffset ResolvedFieldsOffset() {
    227     return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_fields_);
    228   }
    229 
    230   static constexpr MemberOffset ResolvedMethodsOffset() {
    231     return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_methods_);
    232   }
    233 
    234   static constexpr MemberOffset ResolvedMethodTypesOffset() {
    235     return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_method_types_);
    236   }
    237 
    238   static constexpr MemberOffset ResolvedCallSitesOffset() {
    239     return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_call_sites_);
    240   }
    241 
    242   static constexpr MemberOffset NumStringsOffset() {
    243     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_strings_);
    244   }
    245 
    246   static constexpr MemberOffset NumPreResolvedStringsOffset() {
    247     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_preresolved_strings_);
    248   }
    249 
    250   static constexpr MemberOffset NumResolvedTypesOffset() {
    251     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_types_);
    252   }
    253 
    254   static constexpr MemberOffset NumResolvedFieldsOffset() {
    255     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_fields_);
    256   }
    257 
    258   static constexpr MemberOffset NumResolvedMethodsOffset() {
    259     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_methods_);
    260   }
    261 
    262   static constexpr MemberOffset NumResolvedMethodTypesOffset() {
    263     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_method_types_);
    264   }
    265 
    266   static constexpr MemberOffset NumResolvedCallSitesOffset() {
    267     return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_call_sites_);
    268   }
    269 
    270   static constexpr size_t PreResolvedStringsAlignment() {
    271     return alignof(GcRoot<mirror::String>);
    272   }
    273 
    274   String* GetResolvedString(dex::StringIndex string_idx) ALWAYS_INLINE
    275       REQUIRES_SHARED(Locks::mutator_lock_);
    276 
    277   void SetResolvedString(dex::StringIndex string_idx, ObjPtr<mirror::String> resolved) ALWAYS_INLINE
    278       REQUIRES_SHARED(Locks::mutator_lock_);
    279 
    280   void SetPreResolvedString(dex::StringIndex string_idx,
    281                             ObjPtr<mirror::String> resolved)
    282       ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_);
    283 
    284   // Clear the preresolved string cache to prevent further usage.
    285   void ClearPreResolvedStrings()
    286       ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_);
    287 
    288   // Clear a string for a string_idx, used to undo string intern transactions to make sure
    289   // the string isn't kept live.
    290   void ClearString(dex::StringIndex string_idx) REQUIRES_SHARED(Locks::mutator_lock_);
    291 
    292   Class* GetResolvedType(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
    293 
    294   void SetResolvedType(dex::TypeIndex type_idx, ObjPtr<Class> resolved)
    295       REQUIRES_SHARED(Locks::mutator_lock_);
    296 
    297   void ClearResolvedType(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
    298 
    299   ALWAYS_INLINE ArtMethod* GetResolvedMethod(uint32_t method_idx, PointerSize ptr_size)
    300       REQUIRES_SHARED(Locks::mutator_lock_);
    301 
    302   ALWAYS_INLINE void SetResolvedMethod(uint32_t method_idx,
    303                                        ArtMethod* resolved,
    304                                        PointerSize ptr_size)
    305       REQUIRES_SHARED(Locks::mutator_lock_);
    306   ALWAYS_INLINE void ClearResolvedMethod(uint32_t method_idx, PointerSize ptr_size)
    307       REQUIRES_SHARED(Locks::mutator_lock_);
    308 
    309   // Pointer sized variant, used for patching.
    310   ALWAYS_INLINE ArtField* GetResolvedField(uint32_t idx, PointerSize ptr_size)
    311       REQUIRES_SHARED(Locks::mutator_lock_);
    312 
    313   // Pointer sized variant, used for patching.
    314   ALWAYS_INLINE void SetResolvedField(uint32_t idx, ArtField* field, PointerSize ptr_size)
    315       REQUIRES_SHARED(Locks::mutator_lock_);
    316   ALWAYS_INLINE void ClearResolvedField(uint32_t idx, PointerSize ptr_size)
    317       REQUIRES_SHARED(Locks::mutator_lock_);
    318 
    319   MethodType* GetResolvedMethodType(dex::ProtoIndex proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
    320 
    321   void SetResolvedMethodType(dex::ProtoIndex proto_idx, MethodType* resolved)
    322       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.
    331   ObjPtr<CallSite> SetResolvedCallSite(uint32_t call_site_idx, ObjPtr<CallSite> resolved)
    332       REQUIRES_SHARED(Locks::mutator_lock_) WARN_UNUSED;
    333 
    334   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    335   StringDexCacheType* GetStrings() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
    336     return GetFieldPtr64<StringDexCacheType*, kVerifyFlags>(StringsOffset());
    337   }
    338 
    339   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 
    345   void SetStrings(StringDexCacheType* strings) ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
    346     SetFieldPtr<false>(StringsOffset(), strings);
    347   }
    348 
    349   void SetPreResolvedStrings(GcRoot<mirror::String>* strings)
    350       ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
    351     SetFieldPtr<false>(PreResolvedStringsOffset(), strings);
    352   }
    353 
    354   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    355   TypeDexCacheType* GetResolvedTypes() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
    356     return GetFieldPtr<TypeDexCacheType*, kVerifyFlags>(ResolvedTypesOffset());
    357   }
    358 
    359   void SetResolvedTypes(TypeDexCacheType* resolved_types)
    360       ALWAYS_INLINE
    361       REQUIRES_SHARED(Locks::mutator_lock_) {
    362     SetFieldPtr<false>(ResolvedTypesOffset(), resolved_types);
    363   }
    364 
    365   MethodDexCacheType* GetResolvedMethods() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
    366     return GetFieldPtr<MethodDexCacheType*>(ResolvedMethodsOffset());
    367   }
    368 
    369   void SetResolvedMethods(MethodDexCacheType* resolved_methods)
    370       ALWAYS_INLINE
    371       REQUIRES_SHARED(Locks::mutator_lock_) {
    372     SetFieldPtr<false>(ResolvedMethodsOffset(), resolved_methods);
    373   }
    374 
    375   FieldDexCacheType* GetResolvedFields() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
    376     return GetFieldPtr<FieldDexCacheType*>(ResolvedFieldsOffset());
    377   }
    378 
    379   void SetResolvedFields(FieldDexCacheType* resolved_fields)
    380       ALWAYS_INLINE
    381       REQUIRES_SHARED(Locks::mutator_lock_) {
    382     SetFieldPtr<false>(ResolvedFieldsOffset(), resolved_fields);
    383   }
    384 
    385   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    386   MethodTypeDexCacheType* GetResolvedMethodTypes()
    387       ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
    388     return GetFieldPtr64<MethodTypeDexCacheType*, kVerifyFlags>(ResolvedMethodTypesOffset());
    389   }
    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 
    397   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    398   GcRoot<CallSite>* GetResolvedCallSites()
    399       ALWAYS_INLINE
    400       REQUIRES_SHARED(Locks::mutator_lock_) {
    401     return GetFieldPtr<GcRoot<CallSite>*, kVerifyFlags>(ResolvedCallSitesOffset());
    402   }
    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 
    410   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    411   size_t NumStrings() REQUIRES_SHARED(Locks::mutator_lock_) {
    412     return GetField32<kVerifyFlags>(NumStringsOffset());
    413   }
    414 
    415   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    416   size_t NumPreResolvedStrings() REQUIRES_SHARED(Locks::mutator_lock_) {
    417     return GetField32<kVerifyFlags>(NumPreResolvedStringsOffset());
    418   }
    419 
    420   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    421   size_t NumResolvedTypes() REQUIRES_SHARED(Locks::mutator_lock_) {
    422     return GetField32<kVerifyFlags>(NumResolvedTypesOffset());
    423   }
    424 
    425   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    426   size_t NumResolvedMethods() REQUIRES_SHARED(Locks::mutator_lock_) {
    427     return GetField32<kVerifyFlags>(NumResolvedMethodsOffset());
    428   }
    429 
    430   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    431   size_t NumResolvedFields() REQUIRES_SHARED(Locks::mutator_lock_) {
    432     return GetField32<kVerifyFlags>(NumResolvedFieldsOffset());
    433   }
    434 
    435   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    436   size_t NumResolvedMethodTypes() REQUIRES_SHARED(Locks::mutator_lock_) {
    437     return GetField32<kVerifyFlags>(NumResolvedMethodTypesOffset());
    438   }
    439 
    440   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
    441   size_t NumResolvedCallSites() REQUIRES_SHARED(Locks::mutator_lock_) {
    442     return GetField32<kVerifyFlags>(NumResolvedCallSitesOffset());
    443   }
    444 
    445   const DexFile* GetDexFile() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
    446     return GetFieldPtr<const DexFile*>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_));
    447   }
    448 
    449   void SetDexFile(const DexFile* dex_file) REQUIRES_SHARED(Locks::mutator_lock_) {
    450     SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file);
    451   }
    452 
    453   void SetLocation(ObjPtr<String> location) REQUIRES_SHARED(Locks::mutator_lock_);
    454 
    455   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 
    466   static size_t PreResolvedStringsSize(size_t num_strings) {
    467     return sizeof(GcRoot<mirror::String>) * num_strings;
    468   }
    469 
    470   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_);
    473   uint32_t MethodSlotIndex(uint32_t method_idx) REQUIRES_SHARED(Locks::mutator_lock_);
    474   uint32_t MethodTypeSlotIndex(dex::ProtoIndex proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
    475 
    476   // Returns true if we succeeded in adding the pre-resolved string array.
    477   bool AddPreResolvedStringsArray() REQUIRES_SHARED(Locks::mutator_lock_);
    478 
    479  private:
    480   void Init(const DexFile* dex_file,
    481             ObjPtr<String> location,
    482             StringDexCacheType* strings,
    483             uint32_t num_strings,
    484             TypeDexCacheType* resolved_types,
    485             uint32_t num_resolved_types,
    486             MethodDexCacheType* resolved_methods,
    487             uint32_t num_resolved_methods,
    488             FieldDexCacheType* resolved_fields,
    489             uint32_t num_resolved_fields,
    490             MethodTypeDexCacheType* resolved_method_types,
    491             uint32_t num_resolved_method_types,
    492             GcRoot<CallSite>* resolved_call_sites,
    493             uint32_t num_resolved_call_sites)
    494       REQUIRES_SHARED(Locks::mutator_lock_);
    495 
    496   // 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 
    509   // Visit instance fields of the dex cache as well as its associated arrays.
    510   template <bool kVisitNativeRoots,
    511             VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
    512             ReadBarrierOption kReadBarrierOption = kWithReadBarrier,
    513             typename Visitor>
    514   void VisitReferences(ObjPtr<Class> klass, const Visitor& visitor)
    515       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_);
    516 
    517   // Due to lack of 16-byte atomics support, we use hand-crafted routines.
    518 #if defined(__aarch64__) || defined(__mips__)
    519   // 16-byte atomics are supported on aarch64, mips and mips64.
    520   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 
    559   HeapReference<String> location_;
    560   // 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_;
    563 
    564   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.
    577 
    578   uint32_t num_resolved_call_sites_;    // Number of elements in the call_sites_ array.
    579   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.
    584 
    585   friend struct art::DexCacheOffsets;  // for verifying offset information
    586   friend class linker::ImageWriter;
    587   friend class Object;  // For VisitReferences
    588   DISALLOW_IMPLICIT_CONSTRUCTORS(DexCache);
    589 };
    590 
    591 }  // namespace mirror
    592 }  // namespace art
    593 
    594 #endif  // ART_RUNTIME_MIRROR_DEX_CACHE_H_
    595