Don't do a read barrier in JIT GC code.
The ArtMethod the JIT GC iterates over might be in the
process of being unloaded.
bug: 74369794
Test: test.py --jit
Test: test-art-host-run-test-debug-no-prebuild-jit-no-relocate-ntrace-cms-checkjni-picimage-npictest-ndebuggable-no-jvmti-cdex-fast-674-hiddenapi64
Change-Id: Ibf8acb0df26f90c479420ef9d0c1b1bc1fcd3b0d
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 5d9b729..579e554 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -176,8 +176,9 @@
return (GetAccessFlags() & kAccFinal) != 0;
}
+ template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
bool IsIntrinsic() {
- return (GetAccessFlags() & kAccIntrinsic) != 0;
+ return (GetAccessFlags<kReadBarrierOption>() & kAccIntrinsic) != 0;
}
ALWAYS_INLINE void SetIntrinsic(uint32_t intrinsic) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -315,12 +316,13 @@
return (GetAccessFlags() & kAccPreviouslyWarm) != 0;
}
+ template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
void SetPreviouslyWarm() {
- if (IsIntrinsic()) {
+ if (IsIntrinsic<kReadBarrierOption>()) {
// kAccPreviouslyWarm overlaps with kAccIntrinsicBits.
return;
}
- AddAccessFlags(kAccPreviouslyWarm);
+ AddAccessFlags<kReadBarrierOption>(kAccPreviouslyWarm);
}
// Should this method be run in the interpreter and count locks (e.g., failed structured-
@@ -839,8 +841,11 @@
}
// This setter guarantees atomicity.
+ template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
void AddAccessFlags(uint32_t flag) {
- DCHECK(!IsIntrinsic() || !OverlapsIntrinsicBits(flag) || IsValidIntrinsicUpdate(flag));
+ DCHECK(!IsIntrinsic<kReadBarrierOption>() ||
+ !OverlapsIntrinsicBits(flag) ||
+ IsValidIntrinsicUpdate(flag));
uint32_t old_access_flags;
uint32_t new_access_flags;
do {
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 0941b0b..b2d58da 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -671,7 +671,11 @@
static void ClearMethodCounter(ArtMethod* method, bool was_warm) {
if (was_warm) {
- method->SetPreviouslyWarm();
+ // Don't do any read barrier, as the declaring class of `method` may
+ // be in the process of being GC'ed (reading the declaring class is done
+ // when DCHECKing the declaring class is resolved, which we know it is
+ // at this point).
+ method->SetPreviouslyWarm<kWithoutReadBarrier>();
}
// We reset the counter to 1 so that the profile knows that the method was executed at least once.
// This is required for layout purposes.