More code for the read barrier support.

Make it possible to disable the RB in Object::SizeOf() (and the
functions it calls transitively) which the collector will need to call
to get the size of an object when copying.

Add Object::AtomicSetReadBarrierPointer() for atomic write of a RB
pointer.

Bug: 12687968
Change-Id: Ibedd252860ac7ccd17e4e7d71b377a8892b48ff0
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index a6db387..fd4b5ff 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -34,9 +34,10 @@
 namespace art {
 namespace mirror {
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline Class* Object::GetClass() {
-  return GetFieldObject<Class, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
+  return GetFieldObject<Class, kVerifyFlags, kDoReadBarrier>(
+      OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -104,18 +105,45 @@
 #endif
 }
 
-inline void Object::SetReadBarrierPointer(Object* rb_pointer) {
+inline void Object::SetReadBarrierPointer(Object* rb_ptr) {
 #ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
   DCHECK(kUseBakerOrBrooksReadBarrier);
   // We don't mark the card as this occurs as part of object allocation. Not all objects have
   // backing cards, such as large objects.
   SetFieldObjectWithoutWriteBarrier<false, false, kVerifyNone>(
-      OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), rb_pointer, false);
+      OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), rb_ptr, false);
 #else
   LOG(FATAL) << "Unreachable";
 #endif
 }
 
+inline bool Object::AtomicSetReadBarrierPointer(Object* expected_rb_ptr, Object* rb_ptr) {
+#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
+  DCHECK(kUseBakerOrBrooksReadBarrier);
+  MemberOffset offset = OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_);
+  byte* raw_addr = reinterpret_cast<byte*>(this) + offset.SizeValue();
+  HeapReference<Object>* ref = reinterpret_cast<HeapReference<Object>*>(raw_addr);
+  HeapReference<Object> expected_ref(HeapReference<Object>::FromMirrorPtr(expected_rb_ptr));
+  HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(rb_ptr));
+  uint32_t expected_val = expected_ref.reference_;
+  uint32_t new_val;
+  do {
+    uint32_t old_val = ref->reference_;
+    if (old_val != expected_val) {
+      // Lost the race.
+      return false;
+    }
+    new_val = new_ref.reference_;
+  } while (!__sync_bool_compare_and_swap(
+      reinterpret_cast<uint32_t*>(raw_addr), expected_val, new_val));
+  DCHECK_EQ(new_val, ref->reference_);
+  return true;
+#else
+  LOG(FATAL) << "Unreachable";
+  return false;
+#endif
+}
+
 inline void Object::AssertReadBarrierPointer() const {
   if (kUseBakerReadBarrier) {
     Object* obj = const_cast<Object*>(this);
@@ -146,16 +174,17 @@
   return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline bool Object::IsClass() {
-  Class* java_lang_Class = GetClass<kVerifyFlags>()->GetClass();
-  return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ==
+  Class* java_lang_Class =
+      GetClass<kVerifyFlags, kDoReadBarrier>()->template GetClass<kVerifyFlags, kDoReadBarrier>();
+  return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis), kDoReadBarrier>() ==
       java_lang_Class;
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline Class* Object::AsClass() {
-  DCHECK(IsClass<kVerifyFlags>());
+  DCHECK((IsClass<kVerifyFlags, kDoReadBarrier>()));
   return down_cast<Class*>(this);
 }
 
@@ -172,14 +201,15 @@
   return down_cast<ObjectArray<T>*>(this);
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline bool Object::IsArrayInstance() {
-  return GetClass<kVerifyFlags>()->IsArrayClass();
+  return GetClass<kVerifyFlags, kDoReadBarrier>()->
+      template IsArrayClass<kVerifyFlags, kDoReadBarrier>();
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline bool Object::IsArtField() {
-  return GetClass<kVerifyFlags>()->IsArtFieldClass();
+  return GetClass<kVerifyFlags, kDoReadBarrier>()->template IsArtFieldClass<kDoReadBarrier>();
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -188,9 +218,9 @@
   return down_cast<ArtField*>(this);
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline bool Object::IsArtMethod() {
-  return GetClass<kVerifyFlags>()->IsArtMethodClass();
+  return GetClass<kVerifyFlags, kDoReadBarrier>()->template IsArtMethodClass<kDoReadBarrier>();
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -210,9 +240,9 @@
   return down_cast<Reference*>(this);
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline Array* Object::AsArray() {
-  DCHECK(IsArrayInstance<kVerifyFlags>());
+  DCHECK((IsArrayInstance<kVerifyFlags, kDoReadBarrier>()));
   return down_cast<Array*>(this);
 }
 
@@ -338,20 +368,21 @@
   return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline size_t Object::SizeOf() {
   size_t result;
   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
-  if (IsArrayInstance<kVerifyFlags>()) {
-    result = AsArray<kNewFlags>()->template SizeOf<kNewFlags>();
-  } else if (IsClass<kNewFlags>()) {
-    result = AsClass<kNewFlags>()->template SizeOf<kNewFlags>();
+  if (IsArrayInstance<kVerifyFlags, kDoReadBarrier>()) {
+    result = AsArray<kNewFlags, kDoReadBarrier>()->template SizeOf<kNewFlags, kDoReadBarrier>();
+  } else if (IsClass<kNewFlags, kDoReadBarrier>()) {
+    result = AsClass<kNewFlags, kDoReadBarrier>()->template SizeOf<kNewFlags, kDoReadBarrier>();
   } else {
-    result = GetClass<kNewFlags>()->GetObjectSize();
+    result = GetClass<kNewFlags, kDoReadBarrier>()->GetObjectSize();
   }
-  DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(GetClass<kNewFlags>());
-  DCHECK(!IsArtField<kNewFlags>()  || result == sizeof(ArtField));
-  DCHECK(!IsArtMethod<kNewFlags>() || result == sizeof(ArtMethod));
+  DCHECK_GE(result, sizeof(Object))
+      << " class=" << PrettyTypeOf(GetClass<kNewFlags, kDoReadBarrier>());
+  DCHECK(!(IsArtField<kNewFlags, kDoReadBarrier>())  || result == sizeof(ArtField));
+  DCHECK(!(IsArtMethod<kNewFlags, kDoReadBarrier>()) || result == sizeof(ArtMethod));
   return result;
 }