Make the support code for read barriers a bit more general.

Add an option for Baker in addition to Brooks.

Bug: 12687968
Change-Id: I8a31db817ff6686c72951b6534f588228e270b11
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 6824183..0405198 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -610,11 +610,13 @@
 void ImageWriter::FixupObject(Object* orig, Object* copy) {
   DCHECK(orig != nullptr);
   DCHECK(copy != nullptr);
-  if (kUseBrooksPointer) {
-    orig->AssertSelfBrooksPointer();
-    // Note the address 'copy' isn't the same as the image address of 'orig'.
-    copy->SetBrooksPointer(GetImageAddress(orig));
-    DCHECK_EQ(copy->GetBrooksPointer(), GetImageAddress(orig));
+  if (kUseBakerOrBrooksReadBarrier) {
+    orig->AssertReadBarrierPointer();
+    if (kUseBrooksReadBarrier) {
+      // Note the address 'copy' isn't the same as the image address of 'orig'.
+      copy->SetReadBarrierPointer(GetImageAddress(orig));
+      DCHECK_EQ(copy->GetReadBarrierPointer(), GetImageAddress(orig));
+    }
   }
   FixupVisitor visitor(this, copy);
   orig->VisitReferences<true /*visit class*/>(visitor, visitor);
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 0c1a72a..8ef407d 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -17,7 +17,7 @@
 #ifndef ART_RUNTIME_ASM_SUPPORT_H_
 #define ART_RUNTIME_ASM_SUPPORT_H_
 
-#include "brooks_pointer.h"
+#include "read_barrier.h"
 
 // Value loaded into rSUSPEND for quick. When this value is counted down to zero we do a suspend
 // check.
@@ -27,7 +27,7 @@
 #define CLASS_OFFSET 0
 #define LOCK_WORD_OFFSET 4
 
-#ifndef USE_BROOKS_POINTER
+#ifndef USE_BAKER_OR_BROOKS_READ_BARRIER
 
 // Offsets within java.lang.Class.
 #define CLASS_COMPONENT_TYPE_OFFSET 12
diff --git a/runtime/brooks_pointer.h b/runtime/brooks_pointer.h
deleted file mode 100644
index 3dac6e9..0000000
--- a/runtime/brooks_pointer.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_BROOKS_POINTER_H_
-#define ART_RUNTIME_BROOKS_POINTER_H_
-
-// This is in a separate file (from globals.h) because asm_support.h
-// (a C header, not C++) can't include globals.h.
-
-// Uncomment this and the two fields in Object.java (libcore) to
-// enable brooks pointers.
-// #define USE_BROOKS_POINTER
-
-#endif  // ART_RUNTIME_BROOKS_POINTER_H_
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 08ea123..3957493 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -206,8 +206,8 @@
   CHECK(java_lang_Class.get() != NULL);
   mirror::Class::SetClassClass(java_lang_Class.get());
   java_lang_Class->SetClass(java_lang_Class.get());
-  if (kUseBrooksPointer) {
-    java_lang_Class->AssertSelfBrooksPointer();
+  if (kUseBakerOrBrooksReadBarrier) {
+    java_lang_Class->AssertReadBarrierPointer();
   }
   java_lang_Class->SetClassSize(sizeof(mirror::ClassClass));
   heap->DecrementDisableMovingGC(self);
@@ -1864,8 +1864,8 @@
   CHECK(descriptor != NULL);
 
   klass->SetClass(GetClassRoot(kJavaLangClass));
-  if (kUseBrooksPointer) {
-    klass->AssertSelfBrooksPointer();
+  if (kUseBakerOrBrooksReadBarrier) {
+    klass->AssertReadBarrierPointer();
   }
   uint32_t access_flags = dex_class_def.access_flags_;
   // Make sure that none of our runtime-only flags are set.
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 7eb7b01..5b72a44 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -452,9 +452,9 @@
 
     // alphabetical 32-bit
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, monitor_), "shadow$_monitor_"));
-#ifdef USE_BROOKS_POINTER
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, x_brooks_ptr_), "shadow$_x_brooks_ptr_"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, x_padding_), "shadow$_x_padding_"));
+#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, x_rb_ptr_), "shadow$_x_rb_ptr_"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, x_xpadding_), "shadow$_x_xpadding_"));
 #endif
   };
 };
@@ -731,7 +731,7 @@
   EXPECT_FALSE(JavaLangObject->IsSynthetic());
   EXPECT_EQ(2U, JavaLangObject->NumDirectMethods());
   EXPECT_EQ(11U, JavaLangObject->NumVirtualMethods());
-  if (!kUseBrooksPointer) {
+  if (!kUseBakerOrBrooksReadBarrier) {
     EXPECT_EQ(2U, JavaLangObject->NumInstanceFields());
   } else {
     EXPECT_EQ(4U, JavaLangObject->NumInstanceFields());
@@ -740,11 +740,11 @@
   EXPECT_STREQ(fh.GetName(), "shadow$_klass_");
   fh.ChangeField(JavaLangObject->GetInstanceField(1));
   EXPECT_STREQ(fh.GetName(), "shadow$_monitor_");
-  if (kUseBrooksPointer) {
+  if (kUseBakerOrBrooksReadBarrier) {
     fh.ChangeField(JavaLangObject->GetInstanceField(2));
-    EXPECT_STREQ(fh.GetName(), "shadow$_x_brooks_ptr_");
+    EXPECT_STREQ(fh.GetName(), "shadow$_x_rb_ptr_");
     fh.ChangeField(JavaLangObject->GetInstanceField(3));
-    EXPECT_STREQ(fh.GetName(), "shadow$_x_padding_");
+    EXPECT_STREQ(fh.GetName(), "shadow$_x_xpadding_");
   }
 
   EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 91ccd64..ca2d0bd 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -343,9 +343,9 @@
 
 inline void MarkSweep::MarkObjectNonNull(Object* obj) {
   DCHECK(obj != nullptr);
-  if (kUseBrooksPointer) {
-    // Verify all the objects have the correct Brooks pointer installed.
-    obj->AssertSelfBrooksPointer();
+  if (kUseBakerOrBrooksReadBarrier) {
+    // Verify all the objects have the correct pointer installed.
+    obj->AssertReadBarrierPointer();
   }
   if (immune_region_.ContainsObject(obj)) {
     if (kCountMarkedObjects) {
@@ -415,9 +415,9 @@
 
 inline bool MarkSweep::MarkObjectParallel(const Object* obj) {
   DCHECK(obj != nullptr);
-  if (kUseBrooksPointer) {
-    // Verify all the objects have the correct Brooks pointer installed.
-    obj->AssertSelfBrooksPointer();
+  if (kUseBakerOrBrooksReadBarrier) {
+    // Verify all the objects have the correct pointer installed.
+    obj->AssertReadBarrierPointer();
   }
   if (immune_region_.ContainsObject(obj)) {
     DCHECK(IsMarked(obj));
diff --git a/runtime/gc/collector/semi_space-inl.h b/runtime/gc/collector/semi_space-inl.h
index d60298b6..df731ff 100644
--- a/runtime/gc/collector/semi_space-inl.h
+++ b/runtime/gc/collector/semi_space-inl.h
@@ -45,9 +45,9 @@
   if (obj == nullptr) {
     return;
   }
-  if (kUseBrooksPointer) {
+  if (kUseBakerOrBrooksReadBarrier) {
     // Verify all the objects have the correct forward pointer installed.
-    obj->AssertSelfBrooksPointer();
+    obj->AssertReadBarrierPointer();
   }
   if (!immune_region_.ContainsObject(obj)) {
     if (from_space_->HasAddress(obj)) {
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index 222bd63..1366858 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -561,11 +561,13 @@
   // references.
   saved_bytes_ +=
       CopyAvoidingDirtyingPages(reinterpret_cast<void*>(forward_address), obj, object_size);
-  if (kUseBrooksPointer) {
-    obj->AssertSelfBrooksPointer();
-    DCHECK_EQ(forward_address->GetBrooksPointer(), obj);
-    forward_address->SetBrooksPointer(forward_address);
-    forward_address->AssertSelfBrooksPointer();
+  if (kUseBakerOrBrooksReadBarrier) {
+    obj->AssertReadBarrierPointer();
+    if (kUseBrooksReadBarrier) {
+      DCHECK_EQ(forward_address->GetReadBarrierPointer(), obj);
+      forward_address->SetReadBarrierPointer(forward_address);
+    }
+    forward_address->AssertReadBarrierPointer();
   }
   if (to_space_live_bitmap_ != nullptr) {
     to_space_live_bitmap_->Set(forward_address);
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index 8bfe793..25f20d6 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -73,9 +73,11 @@
   DCHECK_GT(bytes_allocated, 0u);
   DCHECK_GT(usable_size, 0u);
   obj->SetClass(klass);
-  if (kUseBrooksPointer) {
-    obj->SetBrooksPointer(obj);
-    obj->AssertSelfBrooksPointer();
+  if (kUseBakerOrBrooksReadBarrier) {
+    if (kUseBrooksReadBarrier) {
+      obj->SetReadBarrierPointer(obj);
+    }
+    obj->AssertReadBarrierPointer();
   }
   if (collector::SemiSpace::kUseRememberedSet && UNLIKELY(allocator == kAllocatorTypeNonMoving)) {
     // (Note this if statement will be constant folded away for the
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 1a32a9a..bc50668 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1605,11 +1605,13 @@
     }
     // Copy the object over to its new location.
     memcpy(reinterpret_cast<void*>(forward_address), obj, object_size);
-    if (kUseBrooksPointer) {
-      obj->AssertSelfBrooksPointer();
-      DCHECK_EQ(forward_address->GetBrooksPointer(), obj);
-      forward_address->SetBrooksPointer(forward_address);
-      forward_address->AssertSelfBrooksPointer();
+    if (kUseBakerOrBrooksReadBarrier) {
+      obj->AssertReadBarrierPointer();
+      if (kUseBrooksReadBarrier) {
+        DCHECK_EQ(forward_address->GetReadBarrierPointer(), obj);
+        forward_address->SetReadBarrierPointer(forward_address);
+      }
+      forward_address->AssertReadBarrierPointer();
     }
     return forward_address;
   }
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index bb52c66..9a2815a 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -166,10 +166,8 @@
     mirror::Object* obj = reinterpret_cast<mirror::Object*>(current);
     CHECK(live_bitmap_->Test(obj));
     CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class";
-    if (kUseBrooksPointer) {
-      CHECK(obj->GetBrooksPointer() == obj)
-          << "Bad Brooks pointer: obj=" << reinterpret_cast<void*>(obj)
-          << " brooks_ptr=" << reinterpret_cast<void*>(obj->GetBrooksPointer());
+    if (kUseBakerOrBrooksReadBarrier) {
+      obj->AssertReadBarrierPointer();
     }
     current += RoundUp(obj->SizeOf(), kObjectAlignment);
   }
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index 6d3602c..5c735df 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -85,8 +85,8 @@
     EXPECT_GE(size, SizeOfZeroLengthByteArray());
     EXPECT_TRUE(byte_array_class != nullptr);
     o->SetClass(byte_array_class);
-    if (kUseBrooksPointer) {
-      o->SetBrooksPointer(o);
+    if (kUseBrooksReadBarrier) {
+      o->SetReadBarrierPointer(o);
     }
     mirror::Array* arr = o->AsArray<kVerifyNone>();
     size_t header_size = SizeOfZeroLengthByteArray();
diff --git a/runtime/globals.h b/runtime/globals.h
index 9c6fa0d..f2d6862 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -19,7 +19,7 @@
 
 #include <stddef.h>
 #include <stdint.h>
-#include "brooks_pointer.h"
+#include "read_barrier.h"
 
 namespace art {
 
@@ -97,12 +97,20 @@
 // code, if possible.
 static constexpr bool kEmbedClassInCode = true;
 
-#ifdef USE_BROOKS_POINTER
-static constexpr bool kUseBrooksPointer = true;
+#ifdef USE_BAKER_READ_BARRIER
+static constexpr bool kUseBakerReadBarrier = true;
 #else
-static constexpr bool kUseBrooksPointer = false;
+static constexpr bool kUseBakerReadBarrier = false;
 #endif
 
+#ifdef USE_BROOKS_READ_BARRIER
+static constexpr bool kUseBrooksReadBarrier = true;
+#else
+static constexpr bool kUseBrooksReadBarrier = false;
+#endif
+
+static constexpr bool kUseBakerOrBrooksReadBarrier = kUseBakerReadBarrier || kUseBrooksReadBarrier;
+
 // If true, references within the heap are poisoned (negated).
 static constexpr bool kPoisonHeapReferences = false;
 
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 527b8a6..b6c140d 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -93,33 +93,41 @@
   Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
 }
 
-inline Object* Object::GetBrooksPointer() {
-#ifdef USE_BROOKS_POINTER
-  DCHECK(kUseBrooksPointer);
-  return GetFieldObject<Object, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Object, x_brooks_ptr_), false);
+inline Object* Object::GetReadBarrierPointer() {
+#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
+  DCHECK(kUseBakerOrBrooksReadBarrier);
+  return GetFieldObject<Object, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), false);
 #else
   LOG(FATAL) << "Unreachable";
   return nullptr;
 #endif
 }
 
-inline void Object::SetBrooksPointer(Object* brooks_pointer) {
-#ifdef USE_BROOKS_POINTER
-  DCHECK(kUseBrooksPointer);
+inline void Object::SetReadBarrierPointer(Object* rb_pointer) {
+#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_brooks_ptr_), brooks_pointer, false);
+      OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), rb_pointer, false);
 #else
   LOG(FATAL) << "Unreachable";
 #endif
 }
 
-inline void Object::AssertSelfBrooksPointer() const {
-#ifdef USE_BROOKS_POINTER
-  DCHECK(kUseBrooksPointer);
+inline void Object::AssertReadBarrierPointer() const {
+#if defined(USE_BAKER_READ_BARRIER)
+  DCHECK(kUseBakerReadBarrier);
   Object* obj = const_cast<Object*>(this);
-  DCHECK_EQ(obj, obj->GetBrooksPointer());
+  DCHECK(obj->GetReadBarrierPointer() == nullptr)
+      << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj)
+      << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
+#elif defined(USE_BROOKS_READ_BARRIER)
+  DCHECK(kUseBrooksReadBarrier);
+  Object* obj = const_cast<Object*>(this);
+  DCHECK_EQ(obj, obj->GetReadBarrierPointer())
+      << "Bad Brooks pointer: obj=" << reinterpret_cast<void*>(obj)
+      << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
 #else
   LOG(FATAL) << "Unreachable";
 #endif
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 0a77828..1ac23ce 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -78,9 +78,9 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetClass(Class* new_klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Object* GetBrooksPointer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void SetBrooksPointer(Object* brooks_pointer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void AssertSelfBrooksPointer() const 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 AssertReadBarrierPointer() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // The verifier treats all interfaces as java.lang.Object and relies on runtime checks in
   // invoke-interface to detect incompatible interface types.
@@ -289,12 +289,12 @@
   // Monitor and hash code information.
   uint32_t monitor_;
 
-#ifdef USE_BROOKS_POINTER
-  // Note names use a 'x' prefix and the x_brooks_ptr_ is of type int
+#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
+  // Note names use a 'x' prefix and the x_rb_ptr_ is of type int
   // instead of Object to go with the alphabetical/by-type field order
   // on the Java side.
-  uint32_t x_brooks_ptr_;  // For the Brooks pointer.
-  uint32_t x_padding_;     // For 8-byte alignment. TODO: get rid of this.
+  uint32_t x_rb_ptr_;      // For the Baker or Brooks pointer.
+  uint32_t x_xpadding_;    // For 8-byte alignment. TODO: get rid of this.
 #endif
 
   friend class art::ImageWriter;
diff --git a/runtime/read_barrier.h b/runtime/read_barrier.h
new file mode 100644
index 0000000..ba0d830
--- /dev/null
+++ b/runtime/read_barrier.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_READ_BARRIER_H_
+#define ART_RUNTIME_READ_BARRIER_H_
+
+// This is in a separate file (from globals.h) because asm_support.h
+// (a C header, not C++) can't include globals.h.
+
+// Uncomment one of the following two and the two fields in
+// Object.java (libcore) to enable baker or brooks pointers.
+
+// #define USE_BAKER_READ_BARRIER
+// #define USE_BROOKS_READ_BARRIER
+
+#if defined(USE_BAKER_READ_BARRIER) || defined(USE_BROOKS_READ_BARRIER)
+#define USE_BAKER_OR_BROOKS_READ_BARRIER
+#endif
+
+#if defined(USE_BAKER_READ_BARRIER) && defined(USE_BROOKS_READ_BARRIER)
+#error "Only one of Baker or Brooks can be enabled at a time."
+#endif
+
+#endif  // ART_RUNTIME_READ_BARRIER_H_