Add GcRoot to clean up and enforce read barriers.

Introduce a value-type wrapper around Object* for GC roots so that 1)
we won't have to directly add the read barrier code in many places and
2) we can avoid accidentally bypassing/missing read barriers on GC
roots (the GcRoot interface ensures that the read barrier is executed
on a read).

The jdwp test passed.

Bug: 12687968
Change-Id: Ib167c7c325b3c7e3900133578815f04d219972a1
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index f3c8250..2c0ea36 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -166,8 +166,8 @@
 
 template<class T>
 inline void PrimitiveArray<T>::VisitRoots(RootCallback* callback, void* arg) {
-  if (array_class_ != nullptr) {
-    callback(reinterpret_cast<mirror::Object**>(&array_class_), arg, 0, kRootStickyClass);
+  if (!array_class_.IsNull()) {
+    array_class_.VisitRoot(callback, arg, 0, kRootStickyClass);
   }
 }
 
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 63f9860..f54af85 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -124,7 +124,7 @@
   art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
 }
 
-template <typename T> Class* PrimitiveArray<T>::array_class_ = NULL;
+template <typename T> GcRoot<Class> PrimitiveArray<T>::array_class_;
 
 // Explicitly instantiate all the primitive array types.
 template class PrimitiveArray<uint8_t>;   // BooleanArray
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 6588b57..7af88d6 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -17,10 +17,10 @@
 #ifndef ART_RUNTIME_MIRROR_ARRAY_H_
 #define ART_RUNTIME_MIRROR_ARRAY_H_
 
+#include "gc_root.h"
 #include "gc/allocator_type.h"
 #include "object.h"
 #include "object_callbacks.h"
-#include "read_barrier.h"
 
 namespace art {
 
@@ -159,27 +159,26 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void SetArrayClass(Class* array_class) {
-    CHECK(array_class_ == nullptr);
+    CHECK(array_class_.IsNull());
     CHECK(array_class != nullptr);
-    array_class_ = array_class;
+    array_class_ = GcRoot<Class>(array_class);
   }
 
   static Class* GetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(array_class_ != nullptr);
-    return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
-        &array_class_);
+    DCHECK(!array_class_.IsNull());
+    return array_class_.Read();
   }
 
   static void ResetArrayClass() {
-    CHECK(array_class_ != nullptr);
-    array_class_ = nullptr;
+    CHECK(!array_class_.IsNull());
+    array_class_ = GcRoot<Class>(nullptr);
   }
 
   static void VisitRoots(RootCallback* callback, void* arg)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
-  static Class* array_class_;
+  static GcRoot<Class> array_class_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray);
 };
diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc
index da21dfe..3c7c6ce 100644
--- a/runtime/mirror/art_field.cc
+++ b/runtime/mirror/art_field.cc
@@ -29,7 +29,7 @@
 namespace mirror {
 
 // TODO: Get global references for these
-Class* ArtField::java_lang_reflect_ArtField_ = NULL;
+GcRoot<Class> ArtField::java_lang_reflect_ArtField_;
 
 ArtField* ArtField::FromReflectedField(const ScopedObjectAccessAlreadyRunnable& soa,
                                        jobject jlr_field) {
@@ -40,14 +40,14 @@
 }
 
 void ArtField::SetClass(Class* java_lang_reflect_ArtField) {
-  CHECK(java_lang_reflect_ArtField_ == NULL);
+  CHECK(java_lang_reflect_ArtField_.IsNull());
   CHECK(java_lang_reflect_ArtField != NULL);
-  java_lang_reflect_ArtField_ = java_lang_reflect_ArtField;
+  java_lang_reflect_ArtField_ = GcRoot<Class>(java_lang_reflect_ArtField);
 }
 
 void ArtField::ResetClass() {
-  CHECK(java_lang_reflect_ArtField_ != NULL);
-  java_lang_reflect_ArtField_ = NULL;
+  CHECK(!java_lang_reflect_ArtField_.IsNull());
+  java_lang_reflect_ArtField_ = GcRoot<Class>(nullptr);
 }
 
 void ArtField::SetOffset(MemberOffset num_bytes) {
@@ -64,9 +64,8 @@
 }
 
 void ArtField::VisitRoots(RootCallback* callback, void* arg) {
-  if (java_lang_reflect_ArtField_ != nullptr) {
-    callback(reinterpret_cast<mirror::Object**>(&java_lang_reflect_ArtField_), arg, 0,
-             kRootStickyClass);
+  if (!java_lang_reflect_ArtField_.IsNull()) {
+    java_lang_reflect_ArtField_.VisitRoot(callback, arg, 0, kRootStickyClass);
   }
 }
 
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
index 741c6eb..f3dfa15 100644
--- a/runtime/mirror/art_field.h
+++ b/runtime/mirror/art_field.h
@@ -19,11 +19,12 @@
 
 #include <jni.h>
 
+#include "gc_root.h"
 #include "modifiers.h"
 #include "object.h"
 #include "object_callbacks.h"
 #include "primitive.h"
-#include "read_barrier.h"
+#include "read_barrier_option.h"
 
 namespace art {
 
@@ -135,9 +136,8 @@
 
   template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
   static Class* GetJavaLangReflectArtField()  SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(java_lang_reflect_ArtField_ != nullptr);
-    return ReadBarrier::BarrierForRoot<mirror::Class, kReadBarrierOption>(
-        &java_lang_reflect_ArtField_);
+    DCHECK(!java_lang_reflect_ArtField_.IsNull());
+    return java_lang_reflect_ArtField_.Read<kReadBarrierOption>();
   }
 
   static void SetClass(Class* java_lang_reflect_ArtField);
@@ -180,7 +180,7 @@
   // Offset of field within an instance or in the Class' static fields
   uint32_t offset_;
 
-  static Class* java_lang_reflect_ArtField_;
+  static GcRoot<Class> java_lang_reflect_ArtField_;
 
   friend struct art::ArtFieldOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(ArtField);
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 01b05a6..73de683 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -41,9 +41,8 @@
 
 template<ReadBarrierOption kReadBarrierOption>
 inline Class* ArtMethod::GetJavaLangReflectArtMethod() {
-  DCHECK(java_lang_reflect_ArtMethod_ != nullptr);
-  return ReadBarrier::BarrierForRoot<mirror::Class, kReadBarrierOption>(
-      &java_lang_reflect_ArtMethod_);
+  DCHECK(!java_lang_reflect_ArtMethod_.IsNull());
+  return java_lang_reflect_ArtMethod_.Read<kReadBarrierOption>();
 }
 
 inline Class* ArtMethod::GetDeclaringClass() {
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 211ba1d..4882728 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -47,7 +47,7 @@
 #endif
 
 // TODO: get global references for these
-Class* ArtMethod::java_lang_reflect_ArtMethod_ = NULL;
+GcRoot<Class> ArtMethod::java_lang_reflect_ArtMethod_;
 
 ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
                                           jobject jlr_method) {
@@ -60,9 +60,8 @@
 
 
 void ArtMethod::VisitRoots(RootCallback* callback, void* arg) {
-  if (java_lang_reflect_ArtMethod_ != nullptr) {
-    callback(reinterpret_cast<mirror::Object**>(&java_lang_reflect_ArtMethod_), arg, 0,
-             kRootStickyClass);
+  if (!java_lang_reflect_ArtMethod_.IsNull()) {
+    java_lang_reflect_ArtMethod_.VisitRoot(callback, arg, 0, kRootStickyClass);
   }
 }
 
@@ -80,14 +79,14 @@
 }
 
 void ArtMethod::SetClass(Class* java_lang_reflect_ArtMethod) {
-  CHECK(java_lang_reflect_ArtMethod_ == NULL);
+  CHECK(java_lang_reflect_ArtMethod_.IsNull());
   CHECK(java_lang_reflect_ArtMethod != NULL);
-  java_lang_reflect_ArtMethod_ = java_lang_reflect_ArtMethod;
+  java_lang_reflect_ArtMethod_ = GcRoot<Class>(java_lang_reflect_ArtMethod);
 }
 
 void ArtMethod::ResetClass() {
-  CHECK(java_lang_reflect_ArtMethod_ != NULL);
-  java_lang_reflect_ArtMethod_ = NULL;
+  CHECK(!java_lang_reflect_ArtMethod_.IsNull());
+  java_lang_reflect_ArtMethod_ = GcRoot<Class>(nullptr);
 }
 
 void ArtMethod::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) {
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 081bee1..01e6149 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_MIRROR_ART_METHOD_H_
 
 #include "dex_file.h"
+#include "gc_root.h"
 #include "invoke_type.h"
 #include "modifiers.h"
 #include "object.h"
@@ -514,7 +515,7 @@
   // ifTable.
   uint32_t method_index_;
 
-  static Class* java_lang_reflect_ArtMethod_;
+  static GcRoot<Class> java_lang_reflect_ArtMethod_;
 
  private:
   friend struct art::ArtMethodOffsets;  // for verifying offset information
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index a218b1c..f29ba73 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -36,24 +36,24 @@
 namespace art {
 namespace mirror {
 
-Class* Class::java_lang_Class_ = nullptr;
+GcRoot<Class> Class::java_lang_Class_;
 
 void Class::SetClassClass(Class* java_lang_Class) {
-  CHECK(java_lang_Class_ == nullptr)
-      << ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(&java_lang_Class_)
+  CHECK(java_lang_Class_.IsNull())
+      << java_lang_Class_.Read()
       << " " << java_lang_Class;
   CHECK(java_lang_Class != nullptr);
-  java_lang_Class_ = java_lang_Class;
+  java_lang_Class_ = GcRoot<Class>(java_lang_Class);
 }
 
 void Class::ResetClass() {
-  CHECK(java_lang_Class_ != nullptr);
-  java_lang_Class_ = nullptr;
+  CHECK(!java_lang_Class_.IsNull());
+  java_lang_Class_ = GcRoot<Class>(nullptr);
 }
 
 void Class::VisitRoots(RootCallback* callback, void* arg) {
-  if (java_lang_Class_ != nullptr) {
-    callback(reinterpret_cast<mirror::Object**>(&java_lang_Class_), arg, 0, kRootStickyClass);
+  if (!java_lang_Class_.IsNull()) {
+    java_lang_Class_.VisitRoot(callback, arg, 0, kRootStickyClass);
   }
 }
 
@@ -879,8 +879,9 @@
   CopyClassVisitor visitor(self, &h_this, new_length, sizeof(Class));
 
   mirror::Object* new_class =
-      kMovingClasses ? heap->AllocObject<true>(self, java_lang_Class_, new_length, visitor)
-                     : heap->AllocNonMovableObject<true>(self, java_lang_Class_, new_length, visitor);
+      kMovingClasses
+         ? heap->AllocObject<true>(self, java_lang_Class_.Read(), new_length, visitor)
+         : heap->AllocNonMovableObject<true>(self, java_lang_Class_.Read(), new_length, visitor);
   if (UNLIKELY(new_class == nullptr)) {
     CHECK(self->IsExceptionPending());  // Expect an OOME.
     return NULL;
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 0525abf..1e254fa 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_MIRROR_CLASS_H_
 
 #include "dex_file.h"
+#include "gc_root.h"
 #include "gc/allocator_type.h"
 #include "invoke_type.h"
 #include "modifiers.h"
@@ -25,7 +26,7 @@
 #include "object_array.h"
 #include "object_callbacks.h"
 #include "primitive.h"
-#include "read_barrier.h"
+#include "read_barrier_option.h"
 
 /*
  * A magic value for refOffsets. Ignore the bits and walk the super
@@ -936,9 +937,8 @@
   }
 
   static Class* GetJavaLangClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(java_lang_Class_ != NULL);
-    return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
-        &java_lang_Class_);
+    DCHECK(!java_lang_Class_.IsNull());
+    return java_lang_Class_.Read();
   }
 
   // Can't call this SetClass or else gets called instead of Object::SetClass in places.
@@ -1156,7 +1156,7 @@
   uint32_t fields_[0];
 
   // java.lang.Class
-  static Class* java_lang_Class_;
+  static GcRoot<Class> java_lang_Class_;
 
   friend struct art::ClassOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(Class);
diff --git a/runtime/mirror/reference.cc b/runtime/mirror/reference.cc
index 077cd4b..c36bd98 100644
--- a/runtime/mirror/reference.cc
+++ b/runtime/mirror/reference.cc
@@ -19,23 +19,22 @@
 namespace art {
 namespace mirror {
 
-Class* Reference::java_lang_ref_Reference_ = nullptr;
+GcRoot<Class> Reference::java_lang_ref_Reference_;
 
 void Reference::SetClass(Class* java_lang_ref_Reference) {
-  CHECK(java_lang_ref_Reference_ == nullptr);
+  CHECK(java_lang_ref_Reference_.IsNull());
   CHECK(java_lang_ref_Reference != nullptr);
-  java_lang_ref_Reference_ = java_lang_ref_Reference;
+  java_lang_ref_Reference_ = GcRoot<Class>(java_lang_ref_Reference);
 }
 
 void Reference::ResetClass() {
-  CHECK(java_lang_ref_Reference_ != nullptr);
-  java_lang_ref_Reference_ = nullptr;
+  CHECK(!java_lang_ref_Reference_.IsNull());
+  java_lang_ref_Reference_ = GcRoot<Class>(nullptr);
 }
 
 void Reference::VisitRoots(RootCallback* callback, void* arg) {
-  if (java_lang_ref_Reference_ != nullptr) {
-    callback(reinterpret_cast<mirror::Object**>(&java_lang_ref_Reference_),
-             arg, 0, kRootStickyClass);
+  if (!java_lang_ref_Reference_.IsNull()) {
+    java_lang_ref_Reference_.VisitRoot(callback, arg, 0, kRootStickyClass);
   }
 }
 
diff --git a/runtime/mirror/reference.h b/runtime/mirror/reference.h
index 07d47d3..7345448 100644
--- a/runtime/mirror/reference.h
+++ b/runtime/mirror/reference.h
@@ -18,9 +18,10 @@
 #define ART_RUNTIME_MIRROR_REFERENCE_H_
 
 #include "class.h"
+#include "gc_root.h"
 #include "object.h"
 #include "object_callbacks.h"
-#include "read_barrier.h"
+#include "read_barrier_option.h"
 #include "thread.h"
 
 namespace art {
@@ -94,9 +95,8 @@
 
   template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
   static Class* GetJavaLangRefReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(java_lang_ref_Reference_ != nullptr);
-    return ReadBarrier::BarrierForRoot<mirror::Class, kReadBarrierOption>(
-        &java_lang_ref_Reference_);
+    DCHECK(!java_lang_ref_Reference_.IsNull());
+    return java_lang_ref_Reference_.Read<kReadBarrierOption>();
   }
   static void SetClass(Class* klass);
   static void ResetClass(void);
@@ -114,7 +114,7 @@
   HeapReference<Reference> queue_next_;  // Note this is Java volatile:
   HeapReference<Object> referent_;  // Note this is Java volatile:
 
-  static Class* java_lang_ref_Reference_;
+  static GcRoot<Class> java_lang_ref_Reference_;
 
   friend struct art::ReferenceOffsets;  // for verifying offset information
   friend class gc::ReferenceProcessor;
diff --git a/runtime/mirror/stack_trace_element.cc b/runtime/mirror/stack_trace_element.cc
index b1de2b6..1eb20f7 100644
--- a/runtime/mirror/stack_trace_element.cc
+++ b/runtime/mirror/stack_trace_element.cc
@@ -26,17 +26,17 @@
 namespace art {
 namespace mirror {
 
-Class* StackTraceElement::java_lang_StackTraceElement_ = NULL;
+GcRoot<Class> StackTraceElement::java_lang_StackTraceElement_;
 
 void StackTraceElement::SetClass(Class* java_lang_StackTraceElement) {
-  CHECK(java_lang_StackTraceElement_ == NULL);
+  CHECK(java_lang_StackTraceElement_.IsNull());
   CHECK(java_lang_StackTraceElement != NULL);
-  java_lang_StackTraceElement_ = java_lang_StackTraceElement;
+  java_lang_StackTraceElement_ = GcRoot<Class>(java_lang_StackTraceElement);
 }
 
 void StackTraceElement::ResetClass() {
-  CHECK(java_lang_StackTraceElement_ != NULL);
-  java_lang_StackTraceElement_ = NULL;
+  CHECK(!java_lang_StackTraceElement_.IsNull());
+  java_lang_StackTraceElement_ = GcRoot<Class>(nullptr);
 }
 
 StackTraceElement* StackTraceElement::Alloc(Thread* self, Handle<String> declaring_class,
@@ -68,9 +68,8 @@
 }
 
 void StackTraceElement::VisitRoots(RootCallback* callback, void* arg) {
-  if (java_lang_StackTraceElement_ != nullptr) {
-    callback(reinterpret_cast<mirror::Object**>(&java_lang_StackTraceElement_), arg, 0,
-             kRootStickyClass);
+  if (!java_lang_StackTraceElement_.IsNull()) {
+    java_lang_StackTraceElement_.VisitRoot(callback, arg, 0, kRootStickyClass);
   }
 }
 
diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h
index 52b0927..70acd1c 100644
--- a/runtime/mirror/stack_trace_element.h
+++ b/runtime/mirror/stack_trace_element.h
@@ -17,9 +17,9 @@
 #ifndef ART_RUNTIME_MIRROR_STACK_TRACE_ELEMENT_H_
 #define ART_RUNTIME_MIRROR_STACK_TRACE_ELEMENT_H_
 
+#include "gc_root.h"
 #include "object.h"
 #include "object_callbacks.h"
-#include "read_barrier.h"
 
 namespace art {
 
@@ -57,9 +57,8 @@
   static void VisitRoots(RootCallback* callback, void* arg)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static Class* GetStackTraceElement() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(java_lang_StackTraceElement_ != NULL);
-    return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
-        &java_lang_StackTraceElement_);
+    DCHECK(!java_lang_StackTraceElement_.IsNull());
+    return java_lang_StackTraceElement_.Read();
   }
 
  private:
@@ -74,7 +73,7 @@
             int32_t line_number)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static Class* java_lang_StackTraceElement_;
+  static GcRoot<Class> java_lang_StackTraceElement_;
 
   friend struct art::StackTraceElementOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceElement);
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index 5c57dce..e81e431 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -31,7 +31,7 @@
 namespace mirror {
 
 // TODO: get global references for these
-Class* String::java_lang_String_ = NULL;
+GcRoot<Class> String::java_lang_String_;
 
 int32_t String::FastIndexOf(int32_t ch, int32_t start) {
   int32_t count = GetLength();
@@ -52,14 +52,14 @@
 }
 
 void String::SetClass(Class* java_lang_String) {
-  CHECK(java_lang_String_ == NULL);
+  CHECK(java_lang_String_.IsNull());
   CHECK(java_lang_String != NULL);
-  java_lang_String_ = java_lang_String;
+  java_lang_String_ = GcRoot<Class>(java_lang_String);
 }
 
 void String::ResetClass() {
-  CHECK(java_lang_String_ != NULL);
-  java_lang_String_ = NULL;
+  CHECK(!java_lang_String_.IsNull());
+  java_lang_String_ = GcRoot<Class>(nullptr);
 }
 
 int32_t String::GetHashCode() {
@@ -233,8 +233,8 @@
 }
 
 void String::VisitRoots(RootCallback* callback, void* arg) {
-  if (java_lang_String_ != nullptr) {
-    callback(reinterpret_cast<mirror::Object**>(&java_lang_String_), arg, 0, kRootStickyClass);
+  if (!java_lang_String_.IsNull()) {
+    java_lang_String_.VisitRoot(callback, arg, 0, kRootStickyClass);
   }
 }
 
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 46bdd59..66a5dd8 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -19,9 +19,9 @@
 
 #include <gtest/gtest.h>
 
+#include "gc_root.h"
 #include "object.h"
 #include "object_callbacks.h"
-#include "read_barrier.h"
 
 namespace art {
 
@@ -111,9 +111,8 @@
   int32_t CompareTo(String* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static Class* GetJavaLangString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(java_lang_String_ != NULL);
-    return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
-        &java_lang_String_);
+    DCHECK(!java_lang_String_.IsNull());
+    return java_lang_String_.Read();
   }
 
   static void SetClass(Class* java_lang_String);
@@ -160,7 +159,7 @@
 
   int32_t offset_;
 
-  static Class* java_lang_String_;
+  static GcRoot<Class> java_lang_String_;
 
   friend struct art::StringOffsets;  // for verifying offset information
   FRIEND_TEST(ObjectTest, StringLength);  // for SetOffset and SetCount
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index 1c3f1ed..93ed4d4 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -30,7 +30,7 @@
 namespace art {
 namespace mirror {
 
-Class* Throwable::java_lang_Throwable_ = NULL;
+GcRoot<Class> Throwable::java_lang_Throwable_;
 
 void Throwable::SetDetailMessage(String* new_detail_message) {
   if (Runtime::Current()->IsActiveTransaction()) {
@@ -127,19 +127,19 @@
 }
 
 void Throwable::SetClass(Class* java_lang_Throwable) {
-  CHECK(java_lang_Throwable_ == NULL);
+  CHECK(java_lang_Throwable_.IsNull());
   CHECK(java_lang_Throwable != NULL);
-  java_lang_Throwable_ = java_lang_Throwable;
+  java_lang_Throwable_ = GcRoot<Class>(java_lang_Throwable);
 }
 
 void Throwable::ResetClass() {
-  CHECK(java_lang_Throwable_ != NULL);
-  java_lang_Throwable_ = NULL;
+  CHECK(!java_lang_Throwable_.IsNull());
+  java_lang_Throwable_ = GcRoot<Class>(nullptr);
 }
 
 void Throwable::VisitRoots(RootCallback* callback, void* arg) {
-  if (java_lang_Throwable_ != nullptr) {
-    callback(reinterpret_cast<mirror::Object**>(&java_lang_Throwable_), arg, 0, kRootStickyClass);
+  if (!java_lang_Throwable_.IsNull()) {
+    java_lang_Throwable_.VisitRoot(callback, arg, 0, kRootStickyClass);
   }
 }
 
diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h
index cf54ad6..f90812d 100644
--- a/runtime/mirror/throwable.h
+++ b/runtime/mirror/throwable.h
@@ -17,9 +17,9 @@
 #ifndef ART_RUNTIME_MIRROR_THROWABLE_H_
 #define ART_RUNTIME_MIRROR_THROWABLE_H_
 
+#include "gc_root.h"
 #include "object.h"
 #include "object_callbacks.h"
-#include "read_barrier.h"
 #include "string.h"
 
 namespace art {
@@ -47,9 +47,8 @@
   bool IsCheckedException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static Class* GetJavaLangThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(java_lang_Throwable_ != NULL);
-    return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
-        &java_lang_Throwable_);
+    DCHECK(!java_lang_Throwable_.IsNull());
+    return java_lang_Throwable_.Read();
   }
 
   static void SetClass(Class* java_lang_Throwable);
@@ -72,7 +71,7 @@
   HeapReference<Object> stack_trace_;
   HeapReference<Object> suppressed_exceptions_;
 
-  static Class* java_lang_Throwable_;
+  static GcRoot<Class> java_lang_Throwable_;
 
   friend struct art::ThrowableOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(Throwable);