Merge "Fix (non-intrinsic) UnsafeCASObject for the read barrier config."
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index 25c0bda..1850254 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -574,9 +574,9 @@
   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 7d2ef75..f8f930b 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -126,7 +126,7 @@
   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 770644c..83125ce 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -52,6 +52,17 @@
   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 ea193d7..19cf759 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 @@
     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 @@
   }
 }
 
-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 @@
 }
 
 // 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 600b7f9..3169a8b 100644
--- a/runtime/read_barrier.h
+++ b/runtime/read_barrier.h
@@ -43,26 +43,24 @@
   // 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_);