Add read barriers for the roots in Runtime.

Bug: 12687968
Change-Id: If26518a8251702cfe4d5cd7d1f50e80e342704cf
diff --git a/runtime/arch/arm64/asm_support_arm64.h b/runtime/arch/arm64/asm_support_arm64.h
index 422e20cf..f353408 100644
--- a/runtime/arch/arm64/asm_support_arm64.h
+++ b/runtime/arch/arm64/asm_support_arm64.h
@@ -21,6 +21,7 @@
 
 // TODO Thread offsets need to be checked when on Aarch64.
 
+// Note: these callee save methods loads require read barriers.
 // Offset of field Runtime::callee_save_methods_[kSaveAll]
 #define RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET 0
 // Offset of field Runtime::callee_save_methods_[kRefsOnly]
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 7907b6e..2201b55 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -31,6 +31,7 @@
     ldr x9,[x9]  // x9 = & (art::Runtime * art::Runtime.instance_) .
 
     // x9 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
+    THIS_LOAD_REQUIRES_READ_BARRIER
     ldr x9, [x9, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET ]
 
     sub sp, sp, #368
@@ -109,6 +110,7 @@
     ldr x9,[x9]  // x9 = & (art::Runtime * art::Runtime.instance_) .
 
     // x9 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
+    THIS_LOAD_REQUIRES_READ_BARRIER
     ldr x9, [x9, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET ]
 
     sub sp, sp, #176
@@ -280,6 +282,7 @@
     ldr x9,[x9]  // x9 = & (art::Runtime * art::Runtime.instance_) .
 
     // x9 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
+    THIS_LOAD_REQUIRES_READ_BARRIER
     ldr x9, [x9, RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET ]
 
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
diff --git a/runtime/arch/x86_64/asm_support_x86_64.h b/runtime/arch/x86_64/asm_support_x86_64.h
index 05d0ef8..c3637ef 100644
--- a/runtime/arch/x86_64/asm_support_x86_64.h
+++ b/runtime/arch/x86_64/asm_support_x86_64.h
@@ -19,6 +19,7 @@
 
 #include "asm_support.h"
 
+// Note: these callee save methods loads require read barriers.
 // Offset of field Runtime::callee_save_methods_[kSaveAll]
 #define RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET 0
 // Offset of field Runtime::callee_save_methods_[kRefsOnly]
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 885fbfd..50b2de4 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -68,6 +68,7 @@
     subq MACRO_LITERAL(8), %rsp  // Space for Method* (also aligns the frame).
     CFI_ADJUST_CFA_OFFSET(8)
     // R10 := ArtMethod* for save all callee save frame method.
+    THIS_LOAD_REQUIRES_READ_BARRIER
     movq RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
     // Store ArtMethod* to bottom of stack.
     movq %r10, 0(%rsp)
@@ -108,6 +109,7 @@
     movq %xmm14, 24(%rsp)
     movq %xmm15, 32(%rsp)
     // R10 := ArtMethod* for refs only callee save frame method.
+    THIS_LOAD_REQUIRES_READ_BARRIER
     movq RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
     // Store ArtMethod* to bottom of stack.
     movq %r10, 0(%rsp)
@@ -164,6 +166,7 @@
     subq MACRO_LITERAL(80 + 4 * 8), %rsp
     CFI_ADJUST_CFA_OFFSET(80 + 4 * 8)
     // R10 := ArtMethod* for ref and args callee save frame method.
+    THIS_LOAD_REQUIRES_READ_BARRIER
     movq RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
     // Save FPRs.
     movq %xmm0, 16(%rsp)
diff --git a/runtime/read_barrier_c.h b/runtime/read_barrier_c.h
index f4af61f..1385c60 100644
--- a/runtime/read_barrier_c.h
+++ b/runtime/read_barrier_c.h
@@ -35,4 +35,9 @@
 #error "Only one of Baker or Brooks can be enabled at a time."
 #endif
 
+// A placeholder marker to indicate places to add read barriers in the
+// assembly code. This is a development time aid and to be removed
+// after read barriers are added.
+#define THIS_LOAD_REQUIRES_READ_BARRIER
+
 #endif  // ART_RUNTIME_READ_BARRIER_C_H_
diff --git a/runtime/runtime-inl.h b/runtime/runtime-inl.h
index 29ddd1d..d08e658 100644
--- a/runtime/runtime-inl.h
+++ b/runtime/runtime-inl.h
@@ -21,18 +21,18 @@
 
 namespace art {
 
-inline QuickMethodFrameInfo Runtime::GetRuntimeMethodFrameInfo(mirror::ArtMethod* method) const {
+inline QuickMethodFrameInfo Runtime::GetRuntimeMethodFrameInfo(mirror::ArtMethod* method) {
   DCHECK(method != nullptr);
   // Cannot be imt-conflict-method or resolution-method.
   DCHECK(method != GetImtConflictMethod());
   DCHECK(method != GetResolutionMethod());
   // Don't use GetCalleeSaveMethod(), some tests don't set all callee save methods.
-  if (method == callee_save_methods_[Runtime::kRefsAndArgs]) {
+  if (method == GetCalleeSaveMethodUnchecked(Runtime::kRefsAndArgs)) {
     return GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
-  } else if (method == callee_save_methods_[Runtime::kSaveAll]) {
+  } else if (method == GetCalleeSaveMethodUnchecked(Runtime::kSaveAll)) {
     return GetCalleeSaveMethodFrameInfo(Runtime::kSaveAll);
   } else {
-    DCHECK(method == callee_save_methods_[Runtime::kRefsOnly]);
+    DCHECK(method == GetCalleeSaveMethodUnchecked(Runtime::kRefsOnly));
     return GetCalleeSaveMethodFrameInfo(Runtime::kRefsOnly);
   }
 }
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 94d6cdf..c354ad5 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -910,11 +910,13 @@
   thread_list_->Unregister(self);
 }
 
-  mirror::Throwable* Runtime::GetPreAllocatedOutOfMemoryError() const {
-  if (pre_allocated_OutOfMemoryError_ == NULL) {
+mirror::Throwable* Runtime::GetPreAllocatedOutOfMemoryError() {
+  mirror::Throwable* oome = ReadBarrier::BarrierForRoot<mirror::Throwable, kWithReadBarrier>(
+      &pre_allocated_OutOfMemoryError_);
+  if (oome == NULL) {
     LOG(ERROR) << "Failed to return pre-allocated OOME";
   }
-  return pre_allocated_OutOfMemoryError_;
+  return oome;
 }
 
 void Runtime::VisitConstantRoots(RootCallback* callback, void* arg) {
diff --git a/runtime/runtime.h b/runtime/runtime.h
index f839be1..45af437 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -32,6 +32,7 @@
 #include "offsets.h"
 #include "profiler_options.h"
 #include "quick/quick_method_frame_info.h"
+#include "read_barrier-inl.h"
 #include "runtime_stats.h"
 #include "safe_map.h"
 
@@ -219,8 +220,7 @@
     return monitor_pool_;
   }
 
-  mirror::Throwable* GetPreAllocatedOutOfMemoryError() const
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  mirror::Throwable* GetPreAllocatedOutOfMemoryError() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   const std::vector<std::string>& GetProperties() const {
     return properties_;
@@ -266,9 +266,9 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns a special method that calls into a trampoline for runtime method resolution
-  mirror::ArtMethod* GetResolutionMethod() const {
+  mirror::ArtMethod* GetResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     CHECK(HasResolutionMethod());
-    return resolution_method_;
+    return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(&resolution_method_);
   }
 
   bool HasResolutionMethod() const {
@@ -282,9 +282,9 @@
   mirror::ArtMethod* CreateResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns a special method that calls into a trampoline for runtime imt conflicts
-  mirror::ArtMethod* GetImtConflictMethod() const {
+  mirror::ArtMethod* GetImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     CHECK(HasImtConflictMethod());
-    return imt_conflict_method_;
+    return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(&imt_conflict_method_);
   }
 
   bool HasImtConflictMethod() const {
@@ -298,9 +298,11 @@
   mirror::ArtMethod* CreateImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns an imt with every entry set to conflict, used as default imt for all classes.
-  mirror::ObjectArray<mirror::ArtMethod>* GetDefaultImt() const {
+  mirror::ObjectArray<mirror::ArtMethod>* GetDefaultImt()
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     CHECK(HasDefaultImt());
-    return default_imt_;
+    return ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::ArtMethod>, kWithReadBarrier>(
+        &default_imt_);
   }
 
   bool HasDefaultImt() const {
@@ -326,16 +328,25 @@
     return callee_save_methods_[type] != NULL;
   }
 
-  mirror::ArtMethod* GetCalleeSaveMethod(CalleeSaveType type) const {
+  mirror::ArtMethod* GetCalleeSaveMethod(CalleeSaveType type)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(HasCalleeSaveMethod(type));
-    return callee_save_methods_[type];
+    return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(
+        &callee_save_methods_[type]);
+  }
+
+  mirror::ArtMethod* GetCalleeSaveMethodUnchecked(CalleeSaveType type)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(
+        &callee_save_methods_[type]);
   }
 
   QuickMethodFrameInfo GetCalleeSaveMethodFrameInfo(CalleeSaveType type) const {
     return callee_save_method_frame_infos_[type];
   }
 
-  QuickMethodFrameInfo GetRuntimeMethodFrameInfo(mirror::ArtMethod* method) const;
+  QuickMethodFrameInfo GetRuntimeMethodFrameInfo(mirror::ArtMethod* method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static size_t GetCalleeSaveMethodOffset(CalleeSaveType type) {
     return OFFSETOF_MEMBER(Runtime, callee_save_methods_[type]);