diff options
author | 2022-10-10 12:07:46 +0100 | |
---|---|---|
committer | 2022-10-13 11:36:34 +0000 | |
commit | 5111cb6b246c62a40806940076f9e10761f5f41c (patch) | |
tree | ef27b3465eef3c219e75d13276cecaf9441d6c4e | |
parent | d828fc10982300728d02c97dfac1a0e3684551c8 (diff) |
Refactor and cleanup DexCache.
- Introduce macros to avoid duplicating code for each dex cache kind.
- Remove preResolvedStrings, this was unused.
- Remove dex cache length fields, we can easily infer them.
Test: test.py
Change-Id: I1e0bc8cf078ce8e09c4d756c63be32cb344fcce1
-rw-r--r-- | dex2oat/driver/compiler_driver_test.cc | 6 | ||||
-rw-r--r-- | runtime/class_linker_test.cc | 8 | ||||
-rw-r--r-- | runtime/mirror/dex_cache-inl.h | 219 | ||||
-rw-r--r-- | runtime/mirror/dex_cache.cc | 28 | ||||
-rw-r--r-- | runtime/mirror/dex_cache.h | 424 | ||||
-rw-r--r-- | runtime/mirror/dex_cache_test.cc | 4 | ||||
-rw-r--r-- | test/497-inlining-and-class-loader/clear_dex_cache.cc | 10 | ||||
-rw-r--r-- | test/626-const-class-linking/clear_dex_cache_types.cc | 3 |
8 files changed, 270 insertions, 432 deletions
diff --git a/dex2oat/driver/compiler_driver_test.cc b/dex2oat/driver/compiler_driver_test.cc index 7e3f40ce05..759426a1d3 100644 --- a/dex2oat/driver/compiler_driver_test.cc +++ b/dex2oat/driver/compiler_driver_test.cc @@ -130,19 +130,15 @@ TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) { ASSERT_TRUE(java_lang_dex_file_ != nullptr); const DexFile& dex = *java_lang_dex_file_; ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(soa.Self(), dex); - EXPECT_EQ(dex.NumStringIds(), dex_cache->NumStrings()); for (size_t i = 0; i < dex_cache->NumStrings(); i++) { const ObjPtr<mirror::String> string = dex_cache->GetResolvedString(dex::StringIndex(i)); EXPECT_TRUE(string != nullptr) << "string_idx=" << i; } - EXPECT_EQ(dex.NumTypeIds(), dex_cache->NumResolvedTypes()); for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) { const ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(dex::TypeIndex(i)); EXPECT_TRUE(type != nullptr) << "type_idx=" << i << " " << dex.GetTypeDescriptor(dex.GetTypeId(dex::TypeIndex(i))); } - EXPECT_TRUE(dex_cache->StaticMethodSize() == dex_cache->NumResolvedMethods() - || dex.NumMethodIds() == dex_cache->NumResolvedMethods()); for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) { // FIXME: This is outdated for hash-based method array. ArtMethod* method = dex_cache->GetResolvedMethod(i); @@ -153,8 +149,6 @@ TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) { << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i)) << " " << dex.GetMethodName(dex.GetMethodId(i)); } - EXPECT_TRUE(dex_cache->StaticArtFieldSize() == dex_cache->NumResolvedFields() - || dex.NumFieldIds() == dex_cache->NumResolvedFields()); for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) { // FIXME: This is outdated for hash-based field array. ArtField* field = dex_cache->GetResolvedField(i); diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 666f86eca6..a6cf10c264 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -677,14 +677,6 @@ struct DexCacheOffsets : public CheckOffsets<mirror::DexCache> { addOffset(OFFSETOF_MEMBER(mirror::DexCache, class_loader_), "classLoader"); addOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_file_), "dexFile"); addOffset(OFFSETOF_MEMBER(mirror::DexCache, location_), "location"); - addOffset(OFFSETOF_MEMBER(mirror::DexCache, num_preresolved_strings_), "numPreResolvedStrings"); - addOffset(OFFSETOF_MEMBER(mirror::DexCache, num_resolved_call_sites_), "numResolvedCallSites"); - addOffset(OFFSETOF_MEMBER(mirror::DexCache, num_resolved_fields_), "numResolvedFields"); - addOffset(OFFSETOF_MEMBER(mirror::DexCache, num_resolved_method_types_), "numResolvedMethodTypes"); - addOffset(OFFSETOF_MEMBER(mirror::DexCache, num_resolved_methods_), "numResolvedMethods"); - addOffset(OFFSETOF_MEMBER(mirror::DexCache, num_resolved_types_), "numResolvedTypes"); - addOffset(OFFSETOF_MEMBER(mirror::DexCache, num_strings_), "numStrings"); - addOffset(OFFSETOF_MEMBER(mirror::DexCache, preresolved_strings_), "preResolvedStrings"); addOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_call_sites_), "resolvedCallSites"); addOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_fields_), "resolvedFields"); addOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_method_types_), "resolvedMethodTypes"); diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h index 402bb72945..3cbfb40253 100644 --- a/runtime/mirror/dex_cache-inl.h +++ b/runtime/mirror/dex_cache-inl.h @@ -54,10 +54,7 @@ static void InitializeArray(GcRoot<T>*) { } template<typename T, size_t kMaxCacheSize> -T* DexCache::AllocArray(MemberOffset obj_offset, - MemberOffset num_offset, - size_t num, - LinearAllocKind kind) { +T* DexCache::AllocArray(MemberOffset obj_offset, size_t num, LinearAllocKind kind) { num = std::min<size_t>(num, kMaxCacheSize); if (num == 0) { return nullptr; @@ -79,7 +76,6 @@ T* DexCache::AllocArray(MemberOffset obj_offset, } array = reinterpret_cast<T*>(alloc->AllocAlign16(self, RoundUp(num * sizeof(T), 16), kind)); InitializeArray(array); // Ensure other threads see the array initialized. - dex_cache->SetField32Volatile<false, false>(num_offset, num); dex_cache->SetField64Volatile<false, false>(obj_offset, reinterpret_cast64<uint64_t>(array)); return array; } @@ -89,14 +85,6 @@ inline DexCachePair<T>::DexCachePair(ObjPtr<T> object, uint32_t index) : object(object), index(index) {} template <typename T> -inline void DexCachePair<T>::Initialize(std::atomic<DexCachePair<T>>* dex_cache) { - DexCachePair<T> first_elem; - first_elem.object = GcRoot<T>(nullptr); - first_elem.index = InvalidIndexForSlot(0); - dex_cache[0].store(first_elem, std::memory_order_relaxed); -} - -template <typename T> inline T* DexCachePair<T>::GetObjectForIndex(uint32_t idx) { if (idx != index) { return nullptr; @@ -106,11 +94,22 @@ inline T* DexCachePair<T>::GetObjectForIndex(uint32_t idx) { } template <typename T> +inline void DexCachePair<T>::Initialize(std::atomic<DexCachePair<T>>* dex_cache) { + DexCachePair<T> first_elem; + first_elem.object = GcRoot<T>(nullptr); + first_elem.index = InvalidIndexForSlot(0); + dex_cache[0].store(first_elem, std::memory_order_relaxed); +} + +template <typename T> inline void NativeDexCachePair<T>::Initialize(std::atomic<NativeDexCachePair<T>>* dex_cache) { NativeDexCachePair<T> first_elem; first_elem.object = nullptr; first_elem.index = InvalidIndexForSlot(0); - DexCache::SetNativePair(dex_cache, 0, first_elem); + + auto* array = reinterpret_cast<std::atomic<AtomicPair<uintptr_t>>*>(dex_cache); + AtomicPair<uintptr_t> v(reinterpret_cast<size_t>(first_elem.object), first_elem.index); + AtomicPairStoreRelease(&array[0], v); } inline uint32_t DexCache::ClassSize(PointerSize pointer_size) { @@ -118,34 +117,21 @@ inline uint32_t DexCache::ClassSize(PointerSize pointer_size) { return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size); } -inline uint32_t DexCache::StringSlotIndex(dex::StringIndex string_idx) { - DCHECK_LT(string_idx.index_, GetDexFile()->NumStringIds()); - const uint32_t slot_idx = string_idx.index_ % kDexCacheStringCacheSize; - DCHECK_LT(slot_idx, NumStrings()); - return slot_idx; -} - inline String* DexCache::GetResolvedString(dex::StringIndex string_idx) { - StringDexCacheType* strings = GetStrings(); + auto* strings = GetStrings(); if (UNLIKELY(strings == nullptr)) { return nullptr; } - return strings[StringSlotIndex(string_idx)].load( - std::memory_order_relaxed).GetObjectForIndex(string_idx.index_); + return strings->Get(string_idx.index_); } inline void DexCache::SetResolvedString(dex::StringIndex string_idx, ObjPtr<String> resolved) { DCHECK(resolved != nullptr); - StringDexCacheType* strings = GetStrings(); + auto* strings = GetStrings(); if (UNLIKELY(strings == nullptr)) { - strings = AllocArray<StringDexCacheType, kDexCacheStringCacheSize>( - StringsOffset(), - NumStringsOffset(), - GetDexFile()->NumStringIds(), - LinearAllocKind::kDexCacheArray); + strings = AllocateStrings(); } - strings[StringSlotIndex(string_idx)].store( - StringDexCachePair(resolved, string_idx.index_), std::memory_order_relaxed); + strings->Set(string_idx.index_, resolved.Ptr()); Runtime* const runtime = Runtime::Current(); if (UNLIKELY(runtime->IsActiveTransaction())) { DCHECK(runtime->IsAotCompiler()); @@ -157,102 +143,63 @@ inline void DexCache::SetResolvedString(dex::StringIndex string_idx, ObjPtr<Stri inline void DexCache::ClearString(dex::StringIndex string_idx) { DCHECK(Runtime::Current()->IsAotCompiler()); - uint32_t slot_idx = StringSlotIndex(string_idx); - StringDexCacheType* strings = GetStrings(); + auto* strings = GetStrings(); if (UNLIKELY(strings == nullptr)) { return; } - StringDexCacheType* slot = &strings[slot_idx]; - // This is racy but should only be called from the transactional interpreter. - if (slot->load(std::memory_order_relaxed).index == string_idx.index_) { - StringDexCachePair cleared(nullptr, StringDexCachePair::InvalidIndexForSlot(slot_idx)); - slot->store(cleared, std::memory_order_relaxed); - } -} - -inline uint32_t DexCache::TypeSlotIndex(dex::TypeIndex type_idx) { - DCHECK_LT(type_idx.index_, GetDexFile()->NumTypeIds()); - const uint32_t slot_idx = type_idx.index_ % kDexCacheTypeCacheSize; - DCHECK_LT(slot_idx, NumResolvedTypes()); - return slot_idx; + strings->Clear(string_idx.index_); } inline Class* DexCache::GetResolvedType(dex::TypeIndex type_idx) { // It is theorized that a load acquire is not required since obtaining the resolved class will // always have an address dependency or a lock. - TypeDexCacheType* resolved_types = GetResolvedTypes(); + auto* resolved_types = GetResolvedTypes(); if (UNLIKELY(resolved_types == nullptr)) { return nullptr; } - return resolved_types[TypeSlotIndex(type_idx)].load( - std::memory_order_relaxed).GetObjectForIndex(type_idx.index_); + return resolved_types->Get(type_idx.index_); } inline void DexCache::SetResolvedType(dex::TypeIndex type_idx, ObjPtr<Class> resolved) { DCHECK(resolved != nullptr); DCHECK(resolved->IsResolved()) << resolved->GetStatus(); - TypeDexCacheType* resolved_types = GetResolvedTypes(); + auto* resolved_types = GetResolvedTypes(); if (UNLIKELY(resolved_types == nullptr)) { - resolved_types = AllocArray<TypeDexCacheType, kDexCacheTypeCacheSize>( - ResolvedTypesOffset(), - NumResolvedTypesOffset(), - GetDexFile()->NumTypeIds(), - LinearAllocKind::kDexCacheArray); + resolved_types = AllocateResolvedTypes(); } // TODO default transaction support. // Use a release store for SetResolvedType. This is done to prevent other threads from seeing a // class but not necessarily seeing the loaded members like the static fields array. // See b/32075261. - resolved_types[TypeSlotIndex(type_idx)].store( - TypeDexCachePair(resolved, type_idx.index_), std::memory_order_release); + resolved_types->Set(type_idx.index_, resolved.Ptr()); // TODO: Fine-grained marking, so that we don't need to go through all arrays in full. WriteBarrier::ForEveryFieldWrite(this); } inline void DexCache::ClearResolvedType(dex::TypeIndex type_idx) { DCHECK(Runtime::Current()->IsAotCompiler()); - TypeDexCacheType* resolved_types = GetResolvedTypes(); + auto* resolved_types = GetResolvedTypes(); if (UNLIKELY(resolved_types == nullptr)) { return; } - uint32_t slot_idx = TypeSlotIndex(type_idx); - TypeDexCacheType* slot = &resolved_types[slot_idx]; - // This is racy but should only be called from the single-threaded ImageWriter and tests. - if (slot->load(std::memory_order_relaxed).index == type_idx.index_) { - TypeDexCachePair cleared(nullptr, TypeDexCachePair::InvalidIndexForSlot(slot_idx)); - slot->store(cleared, std::memory_order_relaxed); - } -} - -inline uint32_t DexCache::MethodTypeSlotIndex(dex::ProtoIndex proto_idx) { - DCHECK(Runtime::Current()->IsMethodHandlesEnabled()); - DCHECK_LT(proto_idx.index_, GetDexFile()->NumProtoIds()); - const uint32_t slot_idx = proto_idx.index_ % kDexCacheMethodTypeCacheSize; - DCHECK_LT(slot_idx, NumResolvedMethodTypes()); - return slot_idx; + resolved_types->Clear(type_idx.index_); } inline MethodType* DexCache::GetResolvedMethodType(dex::ProtoIndex proto_idx) { - MethodTypeDexCacheType* methods = GetResolvedMethodTypes(); + auto* methods = GetResolvedMethodTypes(); if (UNLIKELY(methods == nullptr)) { return nullptr; } - return methods[MethodTypeSlotIndex(proto_idx)].load( - std::memory_order_relaxed).GetObjectForIndex(proto_idx.index_); + return methods->Get(proto_idx.index_); } inline void DexCache::SetResolvedMethodType(dex::ProtoIndex proto_idx, MethodType* resolved) { DCHECK(resolved != nullptr); - MethodTypeDexCacheType* methods = GetResolvedMethodTypes(); + auto* methods = GetResolvedMethodTypes(); if (UNLIKELY(methods == nullptr)) { - methods = AllocArray<MethodTypeDexCacheType, kDexCacheMethodTypeCacheSize>( - ResolvedMethodTypesOffset(), - NumResolvedMethodTypesOffset(), - GetDexFile()->NumProtoIds(), - LinearAllocKind::kDexCacheArray); + methods = AllocateResolvedMethodTypes(); } - methods[MethodTypeSlotIndex(proto_idx)].store( - MethodTypeDexCachePair(resolved, proto_idx.index_), std::memory_order_relaxed); + methods->Set(proto_idx.index_, resolved); Runtime* const runtime = Runtime::Current(); if (UNLIKELY(runtime->IsActiveTransaction())) { DCHECK(runtime->IsAotCompiler()); @@ -264,14 +211,11 @@ inline void DexCache::SetResolvedMethodType(dex::ProtoIndex proto_idx, MethodTyp inline void DexCache::ClearMethodType(dex::ProtoIndex proto_idx) { DCHECK(Runtime::Current()->IsAotCompiler()); - uint32_t slot_idx = MethodTypeSlotIndex(proto_idx); - MethodTypeDexCacheType* slot = &GetResolvedMethodTypes()[slot_idx]; - // This is racy but should only be called from the transactional interpreter. - if (slot->load(std::memory_order_relaxed).index == proto_idx.index_) { - MethodTypeDexCachePair cleared(nullptr, - MethodTypeDexCachePair::InvalidIndexForSlot(proto_idx.index_)); - slot->store(cleared, std::memory_order_relaxed); + auto* methods = GetResolvedMethodTypes(); + if (methods == nullptr) { + return; } + methods->Clear(proto_idx.index_); } inline CallSite* DexCache::GetResolvedCallSite(uint32_t call_site_idx) { @@ -296,11 +240,7 @@ inline ObjPtr<CallSite> DexCache::SetResolvedCallSite(uint32_t call_site_idx, GcRoot<mirror::CallSite> candidate(call_site); GcRoot<CallSite>* call_sites = GetResolvedCallSites(); if (UNLIKELY(call_sites == nullptr)) { - call_sites = AllocArray<GcRoot<CallSite>, std::numeric_limits<size_t>::max()>( - ResolvedCallSitesOffset(), - NumResolvedCallSitesOffset(), - GetDexFile()->NumCallSiteIds(), - LinearAllocKind::kGCRootArray); + call_sites = AllocateResolvedCallSites(); } GcRoot<mirror::CallSite>& target = call_sites[call_site_idx]; @@ -316,103 +256,60 @@ inline ObjPtr<CallSite> DexCache::SetResolvedCallSite(uint32_t call_site_idx, } } -inline uint32_t DexCache::FieldSlotIndex(uint32_t field_idx) { - DCHECK_LT(field_idx, GetDexFile()->NumFieldIds()); - const uint32_t slot_idx = field_idx % kDexCacheFieldCacheSize; - DCHECK_LT(slot_idx, NumResolvedFields()); - return slot_idx; -} - inline ArtField* DexCache::GetResolvedField(uint32_t field_idx) { - FieldDexCacheType* fields = GetResolvedFields(); + auto* fields = GetResolvedFields(); if (UNLIKELY(fields == nullptr)) { return nullptr; } - auto pair = GetNativePair(fields, FieldSlotIndex(field_idx)); - return pair.GetObjectForIndex(field_idx); + return fields->Get(field_idx); } inline void DexCache::SetResolvedField(uint32_t field_idx, ArtField* field) { DCHECK(field != nullptr); - FieldDexCachePair pair(field, field_idx); - FieldDexCacheType* fields = GetResolvedFields(); + auto* fields = GetResolvedFields(); if (UNLIKELY(fields == nullptr)) { - fields = AllocArray<FieldDexCacheType, kDexCacheFieldCacheSize>( - ResolvedFieldsOffset(), - NumResolvedFieldsOffset(), - GetDexFile()->NumFieldIds(), - LinearAllocKind::kNoGCRoots); + fields = AllocateResolvedFields(); } - SetNativePair(fields, FieldSlotIndex(field_idx), pair); -} - -inline uint32_t DexCache::MethodSlotIndex(uint32_t method_idx) { - DCHECK_LT(method_idx, GetDexFile()->NumMethodIds()); - const uint32_t slot_idx = method_idx % kDexCacheMethodCacheSize; - DCHECK_LT(slot_idx, NumResolvedMethods()); - return slot_idx; + fields->Set(field_idx, field); } inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx) { - MethodDexCacheType* methods = GetResolvedMethods(); + auto* methods = GetResolvedMethods(); if (UNLIKELY(methods == nullptr)) { return nullptr; } - auto pair = GetNativePair(methods, MethodSlotIndex(method_idx)); - return pair.GetObjectForIndex(method_idx); + return methods->Get(method_idx); } inline void DexCache::SetResolvedMethod(uint32_t method_idx, ArtMethod* method) { DCHECK(method != nullptr); - MethodDexCachePair pair(method, method_idx); - MethodDexCacheType* methods = GetResolvedMethods(); + auto* methods = GetResolvedMethods(); if (UNLIKELY(methods == nullptr)) { - methods = AllocArray<MethodDexCacheType, kDexCacheMethodCacheSize>( - ResolvedMethodsOffset(), - NumResolvedMethodsOffset(), - GetDexFile()->NumMethodIds(), - LinearAllocKind::kNoGCRoots); + methods = AllocateResolvedMethods(); } - SetNativePair(methods, MethodSlotIndex(method_idx), pair); + methods->Set(method_idx, method); } -template <typename T> -NativeDexCachePair<T> DexCache::GetNativePair(std::atomic<NativeDexCachePair<T>>* pair_array, - size_t idx) { - auto* array = reinterpret_cast<std::atomic<AtomicPair<uintptr_t>>*>(pair_array); - AtomicPair<uintptr_t> value = AtomicPairLoadAcquire(&array[idx]); - return NativeDexCachePair<T>(reinterpret_cast<T*>(value.first), value.second); -} - -template <typename T> -void DexCache::SetNativePair(std::atomic<NativeDexCachePair<T>>* pair_array, - size_t idx, - NativeDexCachePair<T> pair) { - auto* array = reinterpret_cast<std::atomic<AtomicPair<uintptr_t>>*>(pair_array); - AtomicPair<uintptr_t> v(reinterpret_cast<size_t>(pair.object), pair.index); - AtomicPairStoreRelease(&array[idx], v); -} - -template <typename T, - ReadBarrierOption kReadBarrierOption, - typename Visitor> -inline void VisitDexCachePairs(std::atomic<DexCachePair<T>>* pairs, +template <ReadBarrierOption kReadBarrierOption, + typename Visitor, + typename T> +inline void VisitDexCachePairs(T* array, size_t num_pairs, const Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) { // Check both the data pointer and count since the array might be initialized // concurrently on other thread, and we might observe just one of the values. - for (size_t i = 0; pairs != nullptr && i < num_pairs; ++i) { - DexCachePair<T> source = pairs[i].load(std::memory_order_relaxed); + for (size_t i = 0; array != nullptr && i < num_pairs; ++i) { + auto source = array->GetPair(i); // NOTE: We need the "template" keyword here to avoid a compilation // failure. GcRoot<T> is a template argument-dependent type and we need to // tell the compiler to treat "Read" as a template rather than a field or // function. Otherwise, on encountering the "<" token, the compiler would // treat "Read" as a field. - T* const before = source.object.template Read<kReadBarrierOption>(); + auto const before = source.object.template Read<kReadBarrierOption>(); visitor.VisitRootIfNonNull(source.object.AddressWithoutBarrier()); if (source.object.template Read<kReadBarrierOption>() != before) { - pairs[i].store(source, std::memory_order_relaxed); + array->SetPair(i, source); } } } @@ -443,13 +340,13 @@ template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> inline void DexCache::VisitNativeRoots(const Visitor& visitor) { - VisitDexCachePairs<String, kReadBarrierOption, Visitor>( + VisitDexCachePairs<kReadBarrierOption, Visitor>( GetStrings<kVerifyFlags>(), NumStrings<kVerifyFlags>(), visitor); - VisitDexCachePairs<Class, kReadBarrierOption, Visitor>( + VisitDexCachePairs<kReadBarrierOption, Visitor>( GetResolvedTypes<kVerifyFlags>(), NumResolvedTypes<kVerifyFlags>(), visitor); - VisitDexCachePairs<MethodType, kReadBarrierOption, Visitor>( + VisitDexCachePairs<kReadBarrierOption, Visitor>( GetResolvedMethodTypes<kVerifyFlags>(), NumResolvedMethodTypes<kVerifyFlags>(), visitor); GcRoot<mirror::CallSite>* resolved_call_sites = GetResolvedCallSites<kVerifyFlags>(); diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc index b7f8ee7a07..1d9fecdd11 100644 --- a/runtime/mirror/dex_cache.cc +++ b/runtime/mirror/dex_cache.cc @@ -52,45 +52,47 @@ void DexCache::Initialize(const DexFile* dex_file, ObjPtr<ClassLoader> class_loa void DexCache::VisitReflectiveTargets(ReflectiveValueVisitor* visitor) { bool wrote = false; - FieldDexCacheType* fields = GetResolvedFields(); + auto* fields = GetResolvedFields(); size_t num_fields = NumResolvedFields(); // Check both the data pointer and count since the array might be initialized // concurrently on other thread, and we might observe just one of the values. for (size_t i = 0; fields != nullptr && i < num_fields; i++) { - auto pair(GetNativePair(fields, i)); - if (pair.index == FieldDexCachePair::InvalidIndexForSlot(i)) { + auto pair(fields->GetNativePair(i)); + if (pair.index == NativeDexCachePair<ArtField>::InvalidIndexForSlot(i)) { continue; } ArtField* new_val = visitor->VisitField( pair.object, DexCacheSourceInfo(kSourceDexCacheResolvedField, pair.index, this)); if (UNLIKELY(new_val != pair.object)) { if (new_val == nullptr) { - pair = FieldDexCachePair(nullptr, FieldDexCachePair::InvalidIndexForSlot(i)); + pair = NativeDexCachePair<ArtField>( + nullptr, NativeDexCachePair<ArtField>::InvalidIndexForSlot(i)); } else { pair.object = new_val; } - SetNativePair(fields, i, pair); + fields->SetNativePair(i, pair); wrote = true; } } - MethodDexCacheType* methods = GetResolvedMethods(); + auto* methods = GetResolvedMethods(); size_t num_methods = NumResolvedMethods(); // Check both the data pointer and count since the array might be initialized // concurrently on other thread, and we might observe just one of the values. for (size_t i = 0; methods != nullptr && i < num_methods; i++) { - auto pair(GetNativePair(methods, i)); - if (pair.index == MethodDexCachePair::InvalidIndexForSlot(i)) { + auto pair(methods->GetNativePair(i)); + if (pair.index == NativeDexCachePair<ArtMethod>::InvalidIndexForSlot(i)) { continue; } ArtMethod* new_val = visitor->VisitMethod( pair.object, DexCacheSourceInfo(kSourceDexCacheResolvedMethod, pair.index, this)); if (UNLIKELY(new_val != pair.object)) { if (new_val == nullptr) { - pair = MethodDexCachePair(nullptr, MethodDexCachePair::InvalidIndexForSlot(i)); + pair = NativeDexCachePair<ArtMethod>( + nullptr, NativeDexCachePair<ArtMethod>::InvalidIndexForSlot(i)); } else { pair.object = new_val; } - SetNativePair(methods, i, pair); + methods->SetNativePair(i, pair); wrote = true; } } @@ -106,12 +108,6 @@ void DexCache::ResetNativeArrays() { SetResolvedFields(nullptr); SetResolvedMethodTypes(nullptr); SetResolvedCallSites(nullptr); - SetField32<false>(NumStringsOffset(), 0); - SetField32<false>(NumResolvedTypesOffset(), 0); - SetField32<false>(NumResolvedMethodsOffset(), 0); - SetField32<false>(NumResolvedFieldsOffset(), 0); - SetField32<false>(NumResolvedMethodTypesOffset(), 0); - SetField32<false>(NumResolvedCallSitesOffset(), 0); } void DexCache::SetLocation(ObjPtr<mirror::String> location) { diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h index 7c7b11f475..7af0fa2e87 100644 --- a/runtime/mirror/dex_cache.h +++ b/runtime/mirror/dex_cache.h @@ -19,15 +19,17 @@ #include "array.h" #include "base/array_ref.h" +#include "base/atomic_pair.h" #include "base/bit_utils.h" #include "base/locks.h" +#include "dex/dex_file.h" #include "dex/dex_file_types.h" #include "gc_root.h" // Note: must not use -inl here to avoid circular dependency. +#include "linear_alloc.h" #include "object.h" #include "object_array.h" namespace art { -enum class LinearAllocKind : uint32_t; namespace linker { class ImageWriter; @@ -46,6 +48,7 @@ namespace mirror { class CallSite; class Class; class ClassLoader; +class DexCache; class MethodType; class String; @@ -115,20 +118,92 @@ template <typename T> struct PACKED(2 * __SIZEOF_POINTER__) NativeDexCachePair { } }; -using TypeDexCachePair = DexCachePair<Class>; -using TypeDexCacheType = std::atomic<TypeDexCachePair>; +template <typename T, size_t size> class NativeDexCachePairArray { + public: + NativeDexCachePairArray() {} + + T* Get(uint32_t index) REQUIRES_SHARED(Locks::mutator_lock_) { + auto pair = GetNativePair(entries_, SlotIndex(index)); + return pair.GetObjectForIndex(index); + } + + void Set(uint32_t index, T* value) { + NativeDexCachePair<T> pair(value, index); + SetNativePair(entries_, SlotIndex(index), pair); + } + + NativeDexCachePair<T> GetNativePair(uint32_t index) REQUIRES_SHARED(Locks::mutator_lock_) { + return GetNativePair(entries_, SlotIndex(index)); + } + + void SetNativePair(uint32_t index, NativeDexCachePair<T> value) { + SetNativePair(entries_, SlotIndex(index), value); + } + + private: + NativeDexCachePair<T> GetNativePair(std::atomic<NativeDexCachePair<T>>* pair_array, size_t idx) { + auto* array = reinterpret_cast<std::atomic<AtomicPair<uintptr_t>>*>(pair_array); + AtomicPair<uintptr_t> value = AtomicPairLoadAcquire(&array[idx]); + return NativeDexCachePair<T>(reinterpret_cast<T*>(value.first), value.second); + } + + void SetNativePair(std::atomic<NativeDexCachePair<T>>* pair_array, + size_t idx, + NativeDexCachePair<T> pair) { + auto* array = reinterpret_cast<std::atomic<AtomicPair<uintptr_t>>*>(pair_array); + AtomicPair<uintptr_t> v(reinterpret_cast<size_t>(pair.object), pair.index); + AtomicPairStoreRelease(&array[idx], v); + } + + uint32_t SlotIndex(uint32_t index) { + return index % size; + } + + std::atomic<NativeDexCachePair<T>> entries_[0]; + + NativeDexCachePairArray(const NativeDexCachePairArray<T, size>&) = delete; + NativeDexCachePairArray& operator=(const NativeDexCachePairArray<T, size>&) = delete; +}; + +template <typename T, size_t size> class DexCachePairArray { + public: + DexCachePairArray() {} + + T* Get(uint32_t index) REQUIRES_SHARED(Locks::mutator_lock_) { + return GetPair(index).GetObjectForIndex(index); + } -using StringDexCachePair = DexCachePair<String>; -using StringDexCacheType = std::atomic<StringDexCachePair>; + void Set(uint32_t index, T* value) { + SetPair(index, DexCachePair<T>(value, index)); + } + + DexCachePair<T> GetPair(uint32_t index) { + return entries_[SlotIndex(index)].load(std::memory_order_relaxed); + } + + void SetPair(uint32_t index, DexCachePair<T> value) { + entries_[SlotIndex(index)].store(value, std::memory_order_relaxed); + } + + void Clear(uint32_t index) { + uint32_t slot = SlotIndex(index); + // This is racy but should only be called from the transactional interpreter. + if (entries_[slot].load(std::memory_order_relaxed).index == index) { + DexCachePair<T> cleared(nullptr, DexCachePair<T>::InvalidIndexForSlot(slot)); + entries_[slot].store(cleared, std::memory_order_relaxed); + } + } -using FieldDexCachePair = NativeDexCachePair<ArtField>; -using FieldDexCacheType = std::atomic<FieldDexCachePair>; + private: + uint32_t SlotIndex(uint32_t index) { + return index % size; + } -using MethodDexCachePair = NativeDexCachePair<ArtMethod>; -using MethodDexCacheType = std::atomic<MethodDexCachePair>; + std::atomic<DexCachePair<T>> entries_[0]; -using MethodTypeDexCachePair = DexCachePair<MethodType>; -using MethodTypeDexCacheType = std::atomic<MethodTypeDexCachePair>; + DexCachePairArray(const DexCachePairArray<T, size>&) = delete; + DexCachePairArray& operator=(const DexCachePairArray<T, size>&) = delete; +}; // C++ mirror of java.lang.DexCache. class MANAGED DexCache final : public Object { @@ -164,26 +239,6 @@ class MANAGED DexCache final : public Object { static_assert(IsPowerOfTwo(kDexCacheMethodTypeCacheSize), "MethodType dex cache size is not a power of 2."); - static constexpr size_t StaticTypeSize() { - return kDexCacheTypeCacheSize; - } - - static constexpr size_t StaticStringSize() { - return kDexCacheStringCacheSize; - } - - static constexpr size_t StaticArtFieldSize() { - return kDexCacheFieldCacheSize; - } - - static constexpr size_t StaticMethodSize() { - return kDexCacheMethodCacheSize; - } - - static constexpr size_t StaticMethodTypeSize() { - return kDexCacheMethodTypeCacheSize; - } - // Size of an instance of java.lang.DexCache not including referenced values. static constexpr uint32_t InstanceSize() { return sizeof(DexCache); @@ -196,7 +251,6 @@ class MANAGED DexCache final : public Object { DexCachePair<Object>* pairs_end) REQUIRES_SHARED(Locks::mutator_lock_); - void Initialize(const DexFile* dex_file, ObjPtr<ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::dex_lock_); @@ -209,66 +263,6 @@ class MANAGED DexCache final : public Object { ReadBarrierOption kReadBarrierOption = kWithReadBarrier> ObjPtr<String> GetLocation() REQUIRES_SHARED(Locks::mutator_lock_); - static constexpr MemberOffset StringsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, strings_); - } - - static constexpr MemberOffset PreResolvedStringsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, preresolved_strings_); - } - - static constexpr MemberOffset ResolvedTypesOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_); - } - - static constexpr MemberOffset ResolvedFieldsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_fields_); - } - - static constexpr MemberOffset ResolvedMethodsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_methods_); - } - - static constexpr MemberOffset ResolvedMethodTypesOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_method_types_); - } - - static constexpr MemberOffset ResolvedCallSitesOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_call_sites_); - } - - static constexpr MemberOffset NumStringsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, num_strings_); - } - - static constexpr MemberOffset NumPreResolvedStringsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, num_preresolved_strings_); - } - - static constexpr MemberOffset NumResolvedTypesOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_types_); - } - - static constexpr MemberOffset NumResolvedFieldsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_fields_); - } - - static constexpr MemberOffset NumResolvedMethodsOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_methods_); - } - - static constexpr MemberOffset NumResolvedMethodTypesOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_method_types_); - } - - static constexpr MemberOffset NumResolvedCallSitesOffset() { - return OFFSET_OF_OBJECT_MEMBER(DexCache, num_resolved_call_sites_); - } - - static constexpr size_t PreResolvedStringsAlignment() { - return alignof(GcRoot<mirror::String>); - } - String* GetResolvedString(dex::StringIndex string_idx) ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_); @@ -317,106 +311,6 @@ class MANAGED DexCache final : public Object { ObjPtr<CallSite> SetResolvedCallSite(uint32_t call_site_idx, ObjPtr<CallSite> resolved) REQUIRES_SHARED(Locks::mutator_lock_) WARN_UNUSED; - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - StringDexCacheType* GetStrings() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) { - return GetFieldPtr64<StringDexCacheType*, kVerifyFlags>(StringsOffset()); - } - - void SetStrings(StringDexCacheType* strings) ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) { - SetFieldPtr<false>(StringsOffset(), strings); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - TypeDexCacheType* GetResolvedTypes() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) { - return GetFieldPtr<TypeDexCacheType*, kVerifyFlags>(ResolvedTypesOffset()); - } - - void SetResolvedTypes(TypeDexCacheType* resolved_types) - ALWAYS_INLINE - REQUIRES_SHARED(Locks::mutator_lock_) { - SetFieldPtr<false>(ResolvedTypesOffset(), resolved_types); - } - - MethodDexCacheType* GetResolvedMethods() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) { - return GetFieldPtr<MethodDexCacheType*>(ResolvedMethodsOffset()); - } - - void SetResolvedMethods(MethodDexCacheType* resolved_methods) - ALWAYS_INLINE - REQUIRES_SHARED(Locks::mutator_lock_) { - SetFieldPtr<false>(ResolvedMethodsOffset(), resolved_methods); - } - - FieldDexCacheType* GetResolvedFields() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) { - return GetFieldPtr<FieldDexCacheType*>(ResolvedFieldsOffset()); - } - - void SetResolvedFields(FieldDexCacheType* resolved_fields) - ALWAYS_INLINE - REQUIRES_SHARED(Locks::mutator_lock_) { - SetFieldPtr<false>(ResolvedFieldsOffset(), resolved_fields); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - MethodTypeDexCacheType* GetResolvedMethodTypes() - ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) { - return GetFieldPtr64<MethodTypeDexCacheType*, kVerifyFlags>(ResolvedMethodTypesOffset()); - } - - void SetResolvedMethodTypes(MethodTypeDexCacheType* resolved_method_types) - ALWAYS_INLINE - REQUIRES_SHARED(Locks::mutator_lock_) { - SetFieldPtr<false>(ResolvedMethodTypesOffset(), resolved_method_types); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - GcRoot<CallSite>* GetResolvedCallSites() - ALWAYS_INLINE - REQUIRES_SHARED(Locks::mutator_lock_) { - return GetFieldPtr<GcRoot<CallSite>*, kVerifyFlags>(ResolvedCallSitesOffset()); - } - - void SetResolvedCallSites(GcRoot<CallSite>* resolved_call_sites) - ALWAYS_INLINE - REQUIRES_SHARED(Locks::mutator_lock_) { - SetFieldPtr<false>(ResolvedCallSitesOffset(), resolved_call_sites); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - size_t NumStrings() REQUIRES_SHARED(Locks::mutator_lock_) { - return GetField32<kVerifyFlags>(NumStringsOffset()); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - size_t NumPreResolvedStrings() REQUIRES_SHARED(Locks::mutator_lock_) { - return GetField32<kVerifyFlags>(NumPreResolvedStringsOffset()); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - size_t NumResolvedTypes() REQUIRES_SHARED(Locks::mutator_lock_) { - return GetField32<kVerifyFlags>(NumResolvedTypesOffset()); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - size_t NumResolvedMethods() REQUIRES_SHARED(Locks::mutator_lock_) { - return GetField32<kVerifyFlags>(NumResolvedMethodsOffset()); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - size_t NumResolvedFields() REQUIRES_SHARED(Locks::mutator_lock_) { - return GetField32<kVerifyFlags>(NumResolvedFieldsOffset()); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - size_t NumResolvedMethodTypes() REQUIRES_SHARED(Locks::mutator_lock_) { - return GetField32<kVerifyFlags>(NumResolvedMethodTypesOffset()); - } - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - size_t NumResolvedCallSites() REQUIRES_SHARED(Locks::mutator_lock_) { - return GetField32<kVerifyFlags>(NumResolvedCallSitesOffset()); - } - const DexFile* GetDexFile() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) { return GetFieldPtr<const DexFile*>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_)); } @@ -427,25 +321,6 @@ class MANAGED DexCache final : public Object { void SetLocation(ObjPtr<String> location) REQUIRES_SHARED(Locks::mutator_lock_); - template <typename T> - static NativeDexCachePair<T> GetNativePair(std::atomic<NativeDexCachePair<T>>* pair_array, - size_t idx); - - template <typename T> - static void SetNativePair(std::atomic<NativeDexCachePair<T>>* pair_array, - size_t idx, - NativeDexCachePair<T> pair); - - static size_t PreResolvedStringsSize(size_t num_strings) { - return sizeof(GcRoot<mirror::String>) * num_strings; - } - - uint32_t StringSlotIndex(dex::StringIndex string_idx) REQUIRES_SHARED(Locks::mutator_lock_); - uint32_t TypeSlotIndex(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_); - uint32_t FieldSlotIndex(uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_); - uint32_t MethodSlotIndex(uint32_t method_idx) REQUIRES_SHARED(Locks::mutator_lock_); - uint32_t MethodTypeSlotIndex(dex::ProtoIndex proto_idx) REQUIRES_SHARED(Locks::mutator_lock_); - void VisitReflectiveTargets(ReflectiveValueVisitor* visitor) REQUIRES(Locks::mutator_lock_); void SetClassLoader(ObjPtr<ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_); @@ -458,10 +333,108 @@ class MANAGED DexCache final : public Object { void VisitNativeRoots(const Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_); + // NOLINTBEGIN(bugprone-macro-parentheses) +#define DEFINE_PAIR_ARRAY(name, pair_kind, getter_setter, type, size, ids, alloc_kind) \ + template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> \ + pair_kind ##Array<type, size>* Get ##getter_setter() \ + ALWAYS_INLINE \ + REQUIRES_SHARED(Locks::mutator_lock_) { \ + return GetFieldPtr<pair_kind ##Array<type, size>*, kVerifyFlags>(getter_setter ##Offset()); \ + } \ + void Set ##getter_setter(pair_kind ##Array<type, size>* value) \ + REQUIRES_SHARED(Locks::mutator_lock_) { \ + SetFieldPtr<false>(getter_setter ##Offset(), value); \ + } \ + static constexpr MemberOffset getter_setter ##Offset() { \ + return OFFSET_OF_OBJECT_MEMBER(DexCache, name); \ + } \ + pair_kind ##Array<type, size>* Allocate ##getter_setter() \ + REQUIRES_SHARED(Locks::mutator_lock_) { \ + return reinterpret_cast<pair_kind ##Array<type, size>*>( \ + AllocArray<std::atomic<pair_kind<type>>, size>( \ + getter_setter ##Offset(), GetDexFile()->ids(), alloc_kind)); \ + } \ + template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> \ + size_t Num ##getter_setter() REQUIRES_SHARED(Locks::mutator_lock_) { \ + return Get ##getter_setter() == nullptr ? 0u : std::min<size_t>(GetDexFile()->ids(), size); \ + } \ + +#define DEFINE_ARRAY(name, getter_setter, type, ids, alloc_kind) \ + template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> \ + type* Get ##getter_setter() \ + ALWAYS_INLINE \ + REQUIRES_SHARED(Locks::mutator_lock_) { \ + return GetFieldPtr<type*, kVerifyFlags>(getter_setter ##Offset()); \ + } \ + void Set ##getter_setter(type* value) \ + REQUIRES_SHARED(Locks::mutator_lock_) { \ + SetFieldPtr<false>(getter_setter ##Offset(), value); \ + } \ + static constexpr MemberOffset getter_setter ##Offset() { \ + return OFFSET_OF_OBJECT_MEMBER(DexCache, name); \ + } \ + type* Allocate ##getter_setter() \ + REQUIRES_SHARED(Locks::mutator_lock_) { \ + return reinterpret_cast<type*>(AllocArray<type, std::numeric_limits<size_t>::max()>( \ + getter_setter ##Offset(), GetDexFile()->ids(), alloc_kind)); \ + } \ + template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> \ + size_t Num ##getter_setter() REQUIRES_SHARED(Locks::mutator_lock_) { \ + return GetDexFile()->ids(); \ + } \ + + DEFINE_ARRAY(resolved_call_sites_, + ResolvedCallSites, + GcRoot<CallSite>, + NumCallSiteIds, + LinearAllocKind::kGCRootArray) + + DEFINE_PAIR_ARRAY(resolved_fields_, + NativeDexCachePair, + ResolvedFields, + ArtField, + kDexCacheFieldCacheSize, + NumFieldIds, + LinearAllocKind::kNoGCRoots) + + DEFINE_PAIR_ARRAY(resolved_method_types_, + DexCachePair, + ResolvedMethodTypes, + mirror::MethodType, + kDexCacheMethodTypeCacheSize, + NumProtoIds, + LinearAllocKind::kDexCacheArray); + + DEFINE_PAIR_ARRAY(resolved_methods_, + NativeDexCachePair, + ResolvedMethods, + ArtMethod, + kDexCacheMethodCacheSize, + NumMethodIds, + LinearAllocKind::kNoGCRoots) + + DEFINE_PAIR_ARRAY(resolved_types_, + DexCachePair, + ResolvedTypes, + mirror::Class, + kDexCacheTypeCacheSize, + NumTypeIds, + LinearAllocKind::kDexCacheArray); + + DEFINE_PAIR_ARRAY(strings_, + DexCachePair, + Strings, + mirror::String, + kDexCacheStringCacheSize, + NumStringIds, + LinearAllocKind::kDexCacheArray); + +// NOLINTEND(bugprone-macro-parentheses) + private: // Allocate new array in linear alloc and save it in the given fields. template<typename T, size_t kMaxCacheSize> - T* AllocArray(MemberOffset obj_offset, MemberOffset num_offset, size_t num, LinearAllocKind kind) + T* AllocArray(MemberOffset obj_offset, size_t num, LinearAllocKind kind) REQUIRES_SHARED(Locks::mutator_lock_); // Visit instance fields of the dex cache as well as its associated arrays. @@ -476,26 +449,13 @@ class MANAGED DexCache final : public Object { HeapReference<String> location_; uint64_t dex_file_; // const DexFile* - uint64_t preresolved_strings_; // GcRoot<mirror::String*> array with num_preresolved_strings - // elements. - uint64_t resolved_call_sites_; // GcRoot<CallSite>* array with num_resolved_call_sites_ - // elements. - uint64_t resolved_fields_; // std::atomic<FieldDexCachePair>*, array with - // num_resolved_fields_ elements. - uint64_t resolved_method_types_; // std::atomic<MethodTypeDexCachePair>* array with - // num_resolved_method_types_ elements. - uint64_t resolved_methods_; // ArtMethod*, array with num_resolved_methods_ elements. - uint64_t resolved_types_; // TypeDexCacheType*, array with num_resolved_types_ elements. - uint64_t strings_; // std::atomic<StringDexCachePair>*, array with num_strings_ - // elements. - - uint32_t num_preresolved_strings_; // Number of elements in the preresolved_strings_ array. - uint32_t num_resolved_call_sites_; // Number of elements in the call_sites_ array. - uint32_t num_resolved_fields_; // Number of elements in the resolved_fields_ array. - uint32_t num_resolved_method_types_; // Number of elements in the resolved_method_types_ array. - uint32_t num_resolved_methods_; // Number of elements in the resolved_methods_ array. - uint32_t num_resolved_types_; // Number of elements in the resolved_types_ array. - uint32_t num_strings_; // Number of elements in the strings_ array. + + uint64_t resolved_call_sites_; // Array of call sites + uint64_t resolved_fields_; // NativeDexCacheArray holding ArtField's + uint64_t resolved_method_types_; // DexCacheArray holding mirror::MethodType's + uint64_t resolved_methods_; // NativeDexCacheArray holding ArtMethod's + uint64_t resolved_types_; // DexCacheArray holding mirror::Class's + uint64_t strings_; // DexCacheArray holding mirror::String's friend struct art::DexCacheOffsets; // for verifying offset information friend class linker::ImageWriter; diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc index a0e8fda888..bc695fad92 100644 --- a/runtime/mirror/dex_cache_test.cc +++ b/runtime/mirror/dex_cache_test.cc @@ -147,10 +147,10 @@ TEST_F(DexCacheMethodHandlesTest, TestResolvedMethodTypes) { // methods. It must therefore contain precisely two method IDs. ASSERT_EQ(2u, dex_file.NumProtoIds()); ASSERT_EQ(dex_file.NumProtoIds(), dex_cache->NumResolvedMethodTypes()); - MethodTypeDexCacheType* method_types_cache = dex_cache->GetResolvedMethodTypes(); + auto* method_types_cache = dex_cache->GetResolvedMethodTypes(); for (size_t i = 0; i < dex_file.NumProtoIds(); ++i) { - const MethodTypeDexCachePair pair = method_types_cache[i].load(std::memory_order_relaxed); + const DexCachePair<MethodType> pair = method_types_cache->GetPair(i); if (dex::ProtoIndex(pair.index) == method1_id.proto_idx_) { ASSERT_EQ(method1_type.Get(), pair.object.Read()); } else if (dex::ProtoIndex(pair.index) == method2_id.proto_idx_) { diff --git a/test/497-inlining-and-class-loader/clear_dex_cache.cc b/test/497-inlining-and-class-loader/clear_dex_cache.cc index 36ec4eb65c..ddbcef59c8 100644 --- a/test/497-inlining-and-class-loader/clear_dex_cache.cc +++ b/test/497-inlining-and-class-loader/clear_dex_cache.cc @@ -34,7 +34,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_Main_cloneResolvedMethods(JNIEnv* env, ScopedObjectAccess soa(Thread::Current()); ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::Class>(cls)->GetDexCache(); size_t num_methods = dex_cache->NumResolvedMethods(); - mirror::MethodDexCacheType* methods = dex_cache->GetResolvedMethods(); + auto* methods = dex_cache->GetResolvedMethods(); CHECK_EQ(num_methods != 0u, methods != nullptr); if (num_methods == 0u) { return nullptr; @@ -48,7 +48,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_Main_cloneResolvedMethods(JNIEnv* env, CHECK(array != nullptr); ObjPtr<mirror::Array> decoded_array = soa.Decode<mirror::Array>(array); for (size_t i = 0; i != num_methods; ++i) { - auto pair = mirror::DexCache::GetNativePair(methods, i); + auto pair = methods->GetNativePair(i); uint32_t index = pair.index; ArtMethod* method = pair.object; if (sizeof(void*) == 4) { @@ -69,7 +69,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_restoreResolvedMethods( ScopedObjectAccess soa(Thread::Current()); ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::Class>(cls)->GetDexCache(); size_t num_methods = dex_cache->NumResolvedMethods(); - mirror::MethodDexCacheType* methods = dex_cache->GetResolvedMethods(); + auto* methods = dex_cache->GetResolvedMethods(); CHECK_EQ(num_methods != 0u, methods != nullptr); ObjPtr<mirror::Array> old = soa.Decode<mirror::Array>(old_cache); CHECK_EQ(methods != nullptr, old != nullptr); @@ -86,8 +86,8 @@ extern "C" JNIEXPORT void JNICALL Java_Main_restoreResolvedMethods( index = dchecked_integral_cast<uint32_t>(long_array->Get(2u * i)); method = reinterpret_cast64<ArtMethod*>(long_array->Get(2u * i + 1u)); } - mirror::MethodDexCachePair pair(method, index); - mirror::DexCache::SetNativePair(methods, i, pair); + mirror::NativeDexCachePair<ArtMethod> pair(method, index); + methods->SetNativePair(i, pair); } } diff --git a/test/626-const-class-linking/clear_dex_cache_types.cc b/test/626-const-class-linking/clear_dex_cache_types.cc index 1aa3cce40f..ef230ad38a 100644 --- a/test/626-const-class-linking/clear_dex_cache_types.cc +++ b/test/626-const-class-linking/clear_dex_cache_types.cc @@ -28,8 +28,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_nativeClearResolvedTypes(JNIEnv*, jc ScopedObjectAccess soa(Thread::Current()); ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::Class>(cls)->GetDexCache(); for (size_t i = 0, num_types = dex_cache->NumResolvedTypes(); i != num_types; ++i) { - mirror::TypeDexCachePair cleared(nullptr, mirror::TypeDexCachePair::InvalidIndexForSlot(i)); - dex_cache->GetResolvedTypes()[i].store(cleared, std::memory_order_relaxed); + dex_cache->GetResolvedTypes()->Clear(i); } } |