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/array-inl.h b/runtime/mirror/array-inl.h
index 3d2fd7b..7f974d0 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -27,10 +27,11 @@
 namespace art {
 namespace mirror {
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline size_t Array::SizeOf() {
   // This is safe from overflow because the array was already allocated, so we know it's sane.
-  size_t component_size = GetClass<kVerifyFlags>()->GetComponentSize();
+  size_t component_size =
+      GetClass<kVerifyFlags, kDoReadBarrier>()->template GetComponentSize<kDoReadBarrier>();
   // Don't need to check this since we already check this in GetClass.
   int32_t component_count =
       GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>();
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 772d303..6bfd5c8 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -41,7 +41,7 @@
                                  const SirtRef<IntArray>& dimensions)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   int32_t GetLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index fd5ac19..f513a04 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -423,7 +423,9 @@
 
   static void SetClass(Class* java_lang_reflect_ArtMethod);
 
+  template <bool kDoReadBarrier = true>
   static Class* GetJavaLangReflectArtMethod() {
+    // This does not need a RB because it is a root.
     return java_lang_reflect_ArtMethod_;
   }
 
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 025e62a..3c02aa0 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -478,6 +478,19 @@
   VisitStaticFieldsReferences<kVisitClass>(this, visitor);
 }
 
+template<bool kDoReadBarrier>
+bool Class::IsArtFieldClass() {
+  Class* java_lang_Class = GetClass<kVerifyNone, kDoReadBarrier>();
+  Class* java_lang_reflect_ArtField =
+      java_lang_Class->GetInstanceField(0)->GetClass<kVerifyNone, kDoReadBarrier>();
+  return this == java_lang_reflect_ArtField;
+}
+
+template<bool kDoReadBarrier>
+bool Class::IsArtMethodClass() {
+  return this == ArtMethod::GetJavaLangReflectArtMethod<kDoReadBarrier>();
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 6dbb29d..ad86e1f 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -328,16 +328,6 @@
   return WellKnownClasses::ToClass(WellKnownClasses::java_lang_Throwable)->IsAssignableFrom(this);
 }
 
-bool Class::IsArtFieldClass() {
-  Class* java_lang_Class = GetClass();
-  Class* java_lang_reflect_ArtField = java_lang_Class->GetInstanceField(0)->GetClass();
-  return this == java_lang_reflect_ArtField;
-}
-
-bool Class::IsArtMethodClass() {
-  return this == ArtMethod::GetJavaLangReflectArtMethod();
-}
-
 void Class::SetClassLoader(ClassLoader* new_class_loader) {
   if (Runtime::Current()->IsActiveTransaction()) {
     SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader, false);
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index d955b97..226dee0 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -364,9 +364,9 @@
     return depth;
   }
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   bool IsArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetComponentType<kVerifyFlags>() != NULL;
+    return GetComponentType<kVerifyFlags, kDoReadBarrier>() != NULL;
   }
 
   bool IsClassClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -375,17 +375,19 @@
 
   bool IsThrowableClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<bool kDoReadBarrier = true>
   bool IsArtFieldClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<bool kDoReadBarrier = true>
   bool IsArtMethodClass();
 
   static MemberOffset ComponentTypeOffset() {
     return OFFSET_OF_OBJECT_MEMBER(Class, component_type_);
   }
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   Class* GetComponentType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetFieldObject<Class, kVerifyFlags>(ComponentTypeOffset(), false);
+    return GetFieldObject<Class, kVerifyFlags, kDoReadBarrier>(ComponentTypeOffset(), false);
   }
 
   void SetComponentType(Class* new_component_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -395,8 +397,10 @@
     SetFieldObject<false, false>(ComponentTypeOffset(), new_component_type, false);
   }
 
+  template<bool kDoReadBarrier = true>
   size_t GetComponentSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return Primitive::ComponentSize(GetComponentType()->GetPrimitiveType());
+    return Primitive::ComponentSize(
+        GetComponentType<kDefaultVerifyFlags, kDoReadBarrier>()->GetPrimitiveType());
   }
 
   bool IsObjectClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -427,7 +431,7 @@
     return IsClassClass() || IsArrayClass();
   }
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   uint32_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
   }
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;
 }
 
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index f652202..7e222a4 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -72,14 +72,16 @@
     return OFFSET_OF_OBJECT_MEMBER(Object, klass_);
   }
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   Class* GetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetClass(Class* new_klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   Object* GetReadBarrierPointer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void SetReadBarrierPointer(Object* rb_pointer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetReadBarrierPointer(Object* rb_ptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool AtomicSetReadBarrierPointer(Object* expected_rb_ptr, Object* rb_ptr)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void AssertReadBarrierPointer() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // The verifier treats all interfaces as java.lang.Object and relies on runtime checks in
@@ -89,7 +91,7 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool InstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -114,9 +116,9 @@
   void Wait(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void Wait(Thread* self, int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   bool IsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   Class* AsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -124,9 +126,9 @@
   template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ObjectArray<T>* AsObjectArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   bool IsArrayInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   Array* AsArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -159,12 +161,12 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   Throwable* AsThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   bool IsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ArtMethod* AsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   bool IsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ArtField* AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);