Insert an empty read barrier call.

Bug: 12687968
Change-Id: Ie1d28658e16e09f6a983cb5c1f0d5b375b7ae069
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 8ef407d..62f3593 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 "read_barrier.h"
+#include "read_barrier_c.h"
 
 // Value loaded into rSUSPEND for quick. When this value is counted down to zero we do a suspend
 // check.
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index 5c735df..9896a48 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -85,8 +85,13 @@
     EXPECT_GE(size, SizeOfZeroLengthByteArray());
     EXPECT_TRUE(byte_array_class != nullptr);
     o->SetClass(byte_array_class);
-    if (kUseBrooksReadBarrier) {
-      o->SetReadBarrierPointer(o);
+    if (kUseBakerOrBrooksReadBarrier) {
+      // Like the proper heap object allocation, install and verify
+      // the correct read barrier pointer.
+      if (kUseBrooksReadBarrier) {
+        o->SetReadBarrierPointer(o);
+      }
+      o->AssertReadBarrierPointer();
     }
     mirror::Array* arr = o->AsArray<kVerifyNone>();
     size_t header_size = SizeOfZeroLengthByteArray();
diff --git a/runtime/globals.h b/runtime/globals.h
index f2d6862..bd85d3b 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -19,7 +19,7 @@
 
 #include <stddef.h>
 #include <stdint.h>
-#include "read_barrier.h"
+#include "read_barrier_c.h"
 
 namespace art {
 
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index b6c140d..a6db387 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -26,6 +26,7 @@
 #include "class.h"
 #include "lock_word-inl.h"
 #include "monitor.h"
+#include "read_barrier-inl.h"
 #include "runtime.h"
 #include "reference.h"
 #include "throwable.h"
@@ -96,7 +97,7 @@
 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);
+  return GetFieldObject<Object, kVerifyNone, false>(OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), false);
 #else
   LOG(FATAL) << "Unreachable";
   return nullptr;
@@ -116,21 +117,19 @@
 }
 
 inline void Object::AssertReadBarrierPointer() const {
-#if defined(USE_BAKER_READ_BARRIER)
-  DCHECK(kUseBakerReadBarrier);
-  Object* obj = const_cast<Object*>(this);
-  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
+  if (kUseBakerReadBarrier) {
+    Object* obj = const_cast<Object*>(this);
+    DCHECK(obj->GetReadBarrierPointer() == nullptr)
+        << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj)
+        << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
+  } else if (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";
+  }
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -470,19 +469,17 @@
   return QuasiAtomic::Cas64(old_value, new_value, addr);
 }
 
-template<class T, VerifyObjectFlags kVerifyFlags>
+template<class T, VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline T* Object::GetFieldObject(MemberOffset field_offset, bool is_volatile) {
   if (kVerifyFlags & kVerifyThis) {
     VerifyObject(this);
   }
   byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
   HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
-  HeapReference<T> objref = *objref_addr;
-
+  T* result = ReadBarrier::Barrier<T, kDoReadBarrier>(this, field_offset, objref_addr);
   if (UNLIKELY(is_volatile)) {
     QuasiAtomic::MembarLoadLoad();  // Ensure loads don't re-order.
   }
-  T* result = objref.AsMirrorPtr();
   if (kVerifyFlags & kVerifyReads) {
     VerifyObject(result);
   }
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 1ac23ce..f652202 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -185,7 +185,7 @@
   bool IsPhantomReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Accessor for Java type fields.
-  template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   T* GetFieldObject(MemberOffset field_offset, bool is_volatile)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<bool kTransactionActive, bool kCheckTransaction = true,
diff --git a/runtime/read_barrier-inl.h b/runtime/read_barrier-inl.h
new file mode 100644
index 0000000..ea2f830
--- /dev/null
+++ b/runtime/read_barrier-inl.h
@@ -0,0 +1,47 @@
+/*
+ * 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_INL_H_
+#define ART_RUNTIME_READ_BARRIER_INL_H_
+
+#include "read_barrier.h"
+
+#include "mirror/object_reference.h"
+
+namespace art {
+
+template <typename MirrorType, bool kDoReadBarrier>
+inline MirrorType* ReadBarrier::Barrier(
+    mirror::Object* obj, MemberOffset offset, mirror::HeapReference<MirrorType>* ref_addr) {
+  // Unused for now.
+  UNUSED(obj);
+  UNUSED(offset);
+  UNUSED(ref_addr);
+  if (kDoReadBarrier && kUseBakerReadBarrier) {
+    // To be implemented.
+    return ref_addr->AsMirrorPtr();
+  } else if (kDoReadBarrier && kUseBrooksReadBarrier) {
+    // To be implemented.
+    return ref_addr->AsMirrorPtr();
+  } else {
+    // No read barrier.
+    return ref_addr->AsMirrorPtr();
+  }
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_READ_BARRIER_INL_H_
diff --git a/runtime/read_barrier.h b/runtime/read_barrier.h
index ba0d830..6f59004 100644
--- a/runtime/read_barrier.h
+++ b/runtime/read_barrier.h
@@ -17,21 +17,28 @@
 #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.
+#include "base/mutex.h"
+#include "base/macros.h"
+#include "offsets.h"
+#include "read_barrier_c.h"
 
-// Uncomment one of the following two and the two fields in
-// Object.java (libcore) to enable baker or brooks pointers.
+// This is a C++ (not C) header file, separate from read_barrier_c.h
+// which needs to be a C header file for asm_support.h.
 
-// #define USE_BAKER_READ_BARRIER
-// #define USE_BROOKS_READ_BARRIER
+namespace art {
+namespace mirror {
+  class Object;
+  template<typename MirrorType> class HeapReference;
+}  // namespace mirror
 
-#if defined(USE_BAKER_READ_BARRIER) || defined(USE_BROOKS_READ_BARRIER)
-#define USE_BAKER_OR_BROOKS_READ_BARRIER
-#endif
+class ReadBarrier {
+ public:
+  template <typename MirrorType, bool kDoReadBarrier = true>
+  ALWAYS_INLINE static MirrorType* Barrier(
+      mirror::Object* obj, MemberOffset offset, mirror::HeapReference<MirrorType>* ref_addr)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+};
 
-#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
+}  // namespace art
 
 #endif  // ART_RUNTIME_READ_BARRIER_H_
diff --git a/runtime/read_barrier_c.h b/runtime/read_barrier_c.h
new file mode 100644
index 0000000..f4af61f
--- /dev/null
+++ b/runtime/read_barrier_c.h
@@ -0,0 +1,38 @@
+/*
+ * 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_C_H_
+#define ART_RUNTIME_READ_BARRIER_C_H_
+
+// This is a C (not C++) header file and is in a separate file (from
+// globals.h) because asm_support.h is a C header file and 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_C_H_