diff options
-rw-r--r-- | runtime/entrypoints/quick/quick_field_entrypoints.cc | 6 | ||||
-rw-r--r-- | runtime/image.cc | 2 | ||||
-rw-r--r-- | runtime/native/sun_misc_Unsafe.cc | 11 | ||||
-rw-r--r-- | runtime/read_barrier-inl.h | 13 | ||||
-rw-r--r-- | runtime/read_barrier.h | 12 |
5 files changed, 30 insertions, 14 deletions
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc index 25c0bda9fb..185025412a 100644 --- a/runtime/entrypoints/quick/quick_field_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc @@ -574,9 +574,9 @@ extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUS constexpr ReadBarrierOption kReadBarrierOption = kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier; mirror::Object* result = - ReadBarrier::Barrier<mirror::Object, kReadBarrierOption, true>(obj, - MemberOffset(offset), - ref_addr); + ReadBarrier::Barrier<mirror::Object, kReadBarrierOption>(obj, + MemberOffset(offset), + ref_addr); return result; } diff --git a/runtime/image.cc b/runtime/image.cc index 7d2ef75c06..f8f930b1dd 100644 --- a/runtime/image.cc +++ b/runtime/image.cc @@ -126,7 +126,7 @@ mirror::ObjectArray<mirror::Object>* ImageHeader::GetImageRoots() const { mirror::ObjectArray<mirror::Object>* image_roots = reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(image_roots_); mirror::ObjectArray<mirror::Object>* result = - ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::Object>, kWithReadBarrier, true>( + ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::Object>, kWithReadBarrier>( &image_roots); DCHECK_EQ(image_roots, result); return result; diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc index 770644cef0..83125cedda 100644 --- a/runtime/native/sun_misc_Unsafe.cc +++ b/runtime/native/sun_misc_Unsafe.cc @@ -52,6 +52,17 @@ static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaOb mirror::Object* expectedValue = soa.Decode<mirror::Object*>(javaExpectedValue); mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue); // JNI must use non transactional mode. + if (kUseReadBarrier) { + // Need to make sure the reference stored in the field is a to-space one before attempting the + // CAS or the CAS could fail incorrectly. + mirror::HeapReference<mirror::Object>* field_addr = + reinterpret_cast<mirror::HeapReference<mirror::Object>*>( + reinterpret_cast<uint8_t*>(obj) + static_cast<size_t>(offset)); + ReadBarrier::Barrier<mirror::Object, kWithReadBarrier, /*kAlwaysUpdateField*/true>( + obj, + MemberOffset(offset), + field_addr); + } bool success = obj->CasFieldStrongSequentiallyConsistentObject<false>(MemberOffset(offset), expectedValue, newValue); return success ? JNI_TRUE : JNI_FALSE; diff --git a/runtime/read_barrier-inl.h b/runtime/read_barrier-inl.h index ea193d742f..19cf7593e4 100644 --- a/runtime/read_barrier-inl.h +++ b/runtime/read_barrier-inl.h @@ -28,7 +28,7 @@ namespace art { -template <typename MirrorType, ReadBarrierOption kReadBarrierOption, bool kMaybeDuringStartup> +template <typename MirrorType, ReadBarrierOption kReadBarrierOption, bool kAlwaysUpdateField> inline MirrorType* ReadBarrier::Barrier( mirror::Object* obj, MemberOffset offset, mirror::HeapReference<MirrorType>* ref_addr) { constexpr bool with_read_barrier = kReadBarrierOption == kWithReadBarrier; @@ -42,9 +42,16 @@ inline MirrorType* ReadBarrier::Barrier( ref_addr = reinterpret_cast<mirror::HeapReference<MirrorType>*>( rb_ptr_high_bits | reinterpret_cast<uintptr_t>(ref_addr)); MirrorType* ref = ref_addr->AsMirrorPtr(); + MirrorType* old_ref = ref; if (is_gray) { // Slow-path. ref = reinterpret_cast<MirrorType*>(Mark(ref)); + // If kAlwaysUpdateField is true, update the field atomically. This may fail if mutator + // updates before us, but it's ok. + if (kAlwaysUpdateField && ref != old_ref) { + obj->CasFieldStrongRelaxedObjectWithoutWriteBarrier<false, false>( + offset, old_ref, ref); + } } if (kEnableReadBarrierInvariantChecks) { CHECK_EQ(rb_ptr_high_bits, 0U) << obj << " rb_ptr=" << obj->GetReadBarrierPointer(); @@ -75,7 +82,7 @@ inline MirrorType* ReadBarrier::Barrier( } } -template <typename MirrorType, ReadBarrierOption kReadBarrierOption, bool kMaybeDuringStartup> +template <typename MirrorType, ReadBarrierOption kReadBarrierOption> inline MirrorType* ReadBarrier::BarrierForRoot(MirrorType** root, GcRootSource* gc_root_source) { MirrorType* ref = *root; @@ -112,7 +119,7 @@ inline MirrorType* ReadBarrier::BarrierForRoot(MirrorType** root, } // TODO: Reduce copy paste -template <typename MirrorType, ReadBarrierOption kReadBarrierOption, bool kMaybeDuringStartup> +template <typename MirrorType, ReadBarrierOption kReadBarrierOption> inline MirrorType* ReadBarrier::BarrierForRoot(mirror::CompressedReference<MirrorType>* root, GcRootSource* gc_root_source) { MirrorType* ref = root->AsMirrorPtr(); diff --git a/runtime/read_barrier.h b/runtime/read_barrier.h index 600b7f928e..3169a8bd54 100644 --- a/runtime/read_barrier.h +++ b/runtime/read_barrier.h @@ -43,26 +43,24 @@ class ReadBarrier { // Enable the read barrier checks. static constexpr bool kEnableReadBarrierInvariantChecks = true; - // It's up to the implementation whether the given field gets - // updated whereas the return value must be an updated reference. + // It's up to the implementation whether the given field gets updated whereas the return value + // must be an updated reference unless kAlwaysUpdateField is true. template <typename MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier, - bool kMaybeDuringStartup = false> + bool kAlwaysUpdateField = false> ALWAYS_INLINE static MirrorType* Barrier( mirror::Object* obj, MemberOffset offset, mirror::HeapReference<MirrorType>* ref_addr) SHARED_REQUIRES(Locks::mutator_lock_); // It's up to the implementation whether the given root gets updated // whereas the return value must be an updated reference. - template <typename MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier, - bool kMaybeDuringStartup = false> + template <typename MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier> ALWAYS_INLINE static MirrorType* BarrierForRoot(MirrorType** root, GcRootSource* gc_root_source = nullptr) SHARED_REQUIRES(Locks::mutator_lock_); // It's up to the implementation whether the given root gets updated // whereas the return value must be an updated reference. - template <typename MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier, - bool kMaybeDuringStartup = false> + template <typename MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier> ALWAYS_INLINE static MirrorType* BarrierForRoot(mirror::CompressedReference<MirrorType>* root, GcRootSource* gc_root_source = nullptr) SHARED_REQUIRES(Locks::mutator_lock_); |