DexCache: Add support for updating MethodType references during GC.
Fixes flakiness in 956-methodhandles
Test: make test-art-host
bug: 30550796
Change-Id: Ia5359390d59e65fc6efc16cc55c11bc65029104d
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index be849a3..df3865b 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -24,6 +24,7 @@
#include "base/casts.h"
#include "base/enums.h"
#include "base/logging.h"
+#include "gc_root.h"
#include "mirror/class.h"
#include "mirror/method_type.h"
#include "runtime.h"
@@ -159,6 +160,33 @@
}
}
+template <typename T,
+ ReadBarrierOption kReadBarrierOption,
+ typename Visitor>
+inline void VisitDexCachePairs(std::atomic<DexCachePair<T>>* pairs,
+ size_t num_pairs,
+ const Visitor& visitor)
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
+ for (size_t i = 0; i < num_pairs; ++i) {
+ DexCachePair<T> source = pairs[i].load(std::memory_order_relaxed);
+ // 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* before = source.object.template Read<kReadBarrierOption>();
+ // TODO(narayan): This additional GC root construction and assignment
+ // is unnecessary. We're already operating on a copy of the DexCachePair
+ // that's in the cache.
+ GcRoot<T> root(before);
+ visitor.VisitRootIfNonNull(root.AddressWithoutBarrier());
+ if (root.Read() != before) {
+ source.object = GcRoot<T>(root.Read());
+ pairs[i].store(source, std::memory_order_relaxed);
+ }
+ }
+}
+
template <bool kVisitNativeRoots,
VerifyObjectFlags kVerifyFlags,
ReadBarrierOption kReadBarrierOption,
@@ -168,21 +196,16 @@
VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
// Visit arrays after.
if (kVisitNativeRoots) {
- mirror::StringDexCacheType* strings = GetStrings();
- for (size_t i = 0, num_strings = NumStrings(); i != num_strings; ++i) {
- StringDexCachePair source = strings[i].load(std::memory_order_relaxed);
- mirror::String* before = source.object.Read<kReadBarrierOption>();
- GcRoot<mirror::String> root(before);
- visitor.VisitRootIfNonNull(root.AddressWithoutBarrier());
- if (root.Read() != before) {
- source.object = GcRoot<String>(root.Read());
- strings[i].store(source, std::memory_order_relaxed);
- }
- }
+ VisitDexCachePairs<mirror::String, kReadBarrierOption, Visitor>(
+ GetStrings(), NumStrings(), visitor);
+
GcRoot<mirror::Class>* resolved_types = GetResolvedTypes();
for (size_t i = 0, num_types = NumResolvedTypes(); i != num_types; ++i) {
visitor.VisitRootIfNonNull(resolved_types[i].AddressWithoutBarrier());
}
+
+ VisitDexCachePairs<mirror::MethodType, kReadBarrierOption, Visitor>(
+ GetResolvedMethodTypes(), NumResolvedMethodTypes(), visitor);
}
}