Make entries in dex cache arrays atomic. am: 8c0fcaad77 am: fd71c10c90
Original change: https://android-review.googlesource.com/c/platform/art/+/2469483
Change-Id: I10bf383c59dda4826797dc9a2e9fc3dc6d9e17e2
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 2e8f6be..c200223 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -398,7 +398,7 @@
}
uint32_t size = reinterpret_cast<uint32_t*>(array)[-1];
for (uint32_t i = 0; i < size; ++i) {
- PatchGcRoot(&array->GetGcRoot(i));
+ PatchGcRoot(array->GetGcRootAddress(i));
}
}
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 3452f17..ddfc6b2 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -118,12 +118,12 @@
template <typename T>
inline void GcRootArray<T>::Set(uint32_t index, T* value) {
GcRoot<T> root(value);
- entries_[index] = root;
+ entries_[index].store(root, std::memory_order_relaxed);
}
template <typename T>
inline T* GcRootArray<T>::Get(uint32_t index) {
- return entries_[index].Read();
+ return entries_[index].load(std::memory_order_relaxed).Read();
}
inline uint32_t DexCache::ClassSize(PointerSize pointer_size) {
@@ -214,10 +214,8 @@
if (UNLIKELY(call_sites == nullptr)) {
return nullptr;
}
- GcRoot<mirror::CallSite>& target = call_sites->GetGcRoot(call_site_idx);
- Atomic<GcRoot<mirror::CallSite>>& ref =
- reinterpret_cast<Atomic<GcRoot<mirror::CallSite>>&>(target);
- return ref.load(std::memory_order_seq_cst).Read();
+ Atomic<GcRoot<mirror::CallSite>>* target = call_sites->GetGcRoot(call_site_idx);
+ return target->load(std::memory_order_seq_cst).Read();
}
inline ObjPtr<CallSite> DexCache::SetResolvedCallSite(uint32_t call_site_idx,
@@ -231,17 +229,15 @@
if (UNLIKELY(call_sites == nullptr)) {
call_sites = AllocateResolvedCallSites();
}
- GcRoot<mirror::CallSite>& target = call_sites->GetGcRoot(call_site_idx);
+ Atomic<GcRoot<mirror::CallSite>>* target = call_sites->GetGcRoot(call_site_idx);
// The first assignment for a given call site wins.
- Atomic<GcRoot<mirror::CallSite>>& ref =
- reinterpret_cast<Atomic<GcRoot<mirror::CallSite>>&>(target);
- if (ref.CompareAndSetStrongSequentiallyConsistent(null_call_site, candidate)) {
+ if (target->CompareAndSetStrongSequentiallyConsistent(null_call_site, candidate)) {
// TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
WriteBarrier::ForEveryFieldWrite(this);
return call_site;
} else {
- return target.Read();
+ return target->load(std::memory_order_relaxed).Read();
}
}
@@ -323,26 +319,26 @@
GcRootArray<mirror::CallSite>* resolved_call_sites = GetResolvedCallSites<kVerifyFlags>();
size_t num_call_sites = NumResolvedCallSites<kVerifyFlags>();
for (size_t i = 0; resolved_call_sites != nullptr && i != num_call_sites; ++i) {
- visitor.VisitRootIfNonNull(resolved_call_sites->GetGcRoot(i).AddressWithoutBarrier());
+ visitor.VisitRootIfNonNull(resolved_call_sites->GetGcRootAddress(i)->AddressWithoutBarrier());
}
GcRootArray<mirror::Class>* resolved_types = GetResolvedTypesArray<kVerifyFlags>();
size_t num_resolved_types = NumResolvedTypesArray<kVerifyFlags>();
for (size_t i = 0; resolved_types != nullptr && i != num_resolved_types; ++i) {
- visitor.VisitRootIfNonNull(resolved_types->GetGcRoot(i).AddressWithoutBarrier());
+ visitor.VisitRootIfNonNull(resolved_types->GetGcRootAddress(i)->AddressWithoutBarrier());
}
GcRootArray<mirror::String>* resolved_strings = GetStringsArray<kVerifyFlags>();
size_t num_resolved_strings = NumStringsArray<kVerifyFlags>();
for (size_t i = 0; resolved_strings != nullptr && i != num_resolved_strings; ++i) {
- visitor.VisitRootIfNonNull(resolved_strings->GetGcRoot(i).AddressWithoutBarrier());
+ visitor.VisitRootIfNonNull(resolved_strings->GetGcRootAddress(i)->AddressWithoutBarrier());
}
GcRootArray<mirror::MethodType>* resolved_method_types =
GetResolvedMethodTypesArray<kVerifyFlags>();
size_t num_resolved_method_types = NumResolvedMethodTypesArray<kVerifyFlags>();
for (size_t i = 0; resolved_method_types != nullptr && i != num_resolved_method_types; ++i) {
- visitor.VisitRootIfNonNull(resolved_method_types->GetGcRoot(i).AddressWithoutBarrier());
+ visitor.VisitRootIfNonNull(resolved_method_types->GetGcRootAddress(i)->AddressWithoutBarrier());
}
}
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 856dd1f..099fe00 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -211,14 +211,21 @@
T* Get(uint32_t index) REQUIRES_SHARED(Locks::mutator_lock_);
- GcRoot<T>& GetGcRoot(uint32_t index) REQUIRES_SHARED(Locks::mutator_lock_) {
- return entries_[index];
+ Atomic<GcRoot<T>>* GetGcRoot(uint32_t index) REQUIRES_SHARED(Locks::mutator_lock_) {
+ return &entries_[index];
+ }
+
+ // Only to be used in locations that don't need the atomic or will later load
+ // and read atomically.
+ GcRoot<T>* GetGcRootAddress(uint32_t index) REQUIRES_SHARED(Locks::mutator_lock_) {
+ static_assert(sizeof(GcRoot<T>) == sizeof(Atomic<GcRoot<T>>));
+ return reinterpret_cast<GcRoot<T>*>(&entries_[index]);
}
void Set(uint32_t index, T* value) REQUIRES_SHARED(Locks::mutator_lock_);
private:
- GcRoot<T> entries_[0];
+ Atomic<GcRoot<T>> entries_[0];
};
template <typename T> class NativeArray {
@@ -226,7 +233,7 @@
NativeArray() {}
T* Get(uint32_t index) {
- return entries_[index];
+ return entries_[index].load(std::memory_order_relaxed);
}
T** GetPtrEntryPtrSize(uint32_t index, PointerSize ptr_size) {
@@ -240,11 +247,11 @@
}
void Set(uint32_t index, T* value) {
- entries_[index] = value;
+ entries_[index].store(value, std::memory_order_relaxed);
}
private:
- T* entries_[0];
+ Atomic<T*> entries_[0];
};
// C++ mirror of java.lang.DexCache.