diff options
author | 2024-06-25 09:53:44 +0000 | |
---|---|---|
committer | 2024-07-10 08:48:50 +0000 | |
commit | 894751180d273b68487f12f3532f24a219deb580 (patch) | |
tree | b6e10df8f23bff068335098d248ae21cb0dc3dbe /runtime/class_linker-inl.h | |
parent | d668220ac5d2fc06b7dce283a25da57c4227a95c (diff) |
Use atomics for find_array_class_cache_
find_array_class_cache_ is used to cache the array classes. This is
accessed concurrently by mutator threads that are looking for an array
class. These threads both read entries and update the cache with the new
array class if it wasn't found in the cache. GC also accesses this cache
to clear it when visiting the roots of class linker. GC uses std::fill_n
to clear the cache. Under ideal circumstances these operations could
work as expected and the updates to each entry could be atomic. Though
some valid compiler optimizations could break this and it is possible we
see a partially initialized / cleared entry. To prevent these we use
atomics to make it safe to access concurrently.
Bug: 330843930
Test: art/test.py
Change-Id: I493e0b0d47bf03603a4970855608cbe82a87c1a4
Diffstat (limited to 'runtime/class_linker-inl.h')
-rw-r--r-- | runtime/class_linker-inl.h | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 6951e35791..6461f54f5f 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -43,7 +43,8 @@ inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self, ObjPtr<mirror::Class> element_class) { for (size_t i = 0; i < kFindArrayCacheSize; ++i) { // Read the cached array class once to avoid races with other threads setting it. - ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read(); + ObjPtr<mirror::Class> array_class = + find_array_class_cache_[i].load(std::memory_order_acquire).Read(); if (array_class != nullptr && array_class->GetComponentType() == element_class) { return array_class; } @@ -57,7 +58,8 @@ inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self, if (array_class != nullptr) { // Benign races in storing array class and incrementing index. size_t victim_index = find_array_class_cache_next_victim_; - find_array_class_cache_[victim_index] = GcRoot<mirror::Class>(array_class); + find_array_class_cache_[victim_index].store(GcRoot<mirror::Class>(array_class), + std::memory_order_release); find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize; } else { // We should have a NoClassDefFoundError. |