Move mirror::ObjectArray to ObjPtr

Also reduce calls to ObjPtr::Ptr.

Bug: 31113334

Test: test-art-host -j32

Change-Id: I73e1b356972bb079b66332f00f7f07451601044e
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index 3b24aab..24bbcfb 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -116,9 +116,9 @@
   DCHECK(object != nullptr) << PrettyField(this);
   DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   if (UNLIKELY(IsVolatile())) {
-    object->SetFieldObjectVolatile<kTransactionActive>(GetOffset(), new_value.Ptr());
+    object->SetFieldObjectVolatile<kTransactionActive>(GetOffset(), new_value);
   } else {
-    object->SetFieldObject<kTransactionActive>(GetOffset(), new_value.Ptr());
+    object->SetFieldObject<kTransactionActive>(GetOffset(), new_value);
   }
 }
 
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 14cbf24..eb2316b 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4202,9 +4202,9 @@
   // Set the class access flags incl. VerificationAttempted, so we do not try to set the flag on
   // the methods.
   klass->SetAccessFlags(kAccClassIsProxy | kAccPublic | kAccFinal | kAccVerificationAttempted);
-  klass->SetClassLoader(soa.Decode<mirror::ClassLoader>(loader).Ptr());
+  klass->SetClassLoader(soa.Decode<mirror::ClassLoader>(loader));
   DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot);
-  klass->SetName(soa.Decode<mirror::String>(name).Ptr());
+  klass->SetName(soa.Decode<mirror::String>(name));
   klass->SetDexCache(GetClassRoot(kJavaLangReflectProxy)->GetDexCache());
   mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, self);
   std::string descriptor(GetDescriptorForProxy(klass.Get()));
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 84752f0..193f6ee 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -514,9 +514,9 @@
       soa.Decode<mirror::ClassLoader>(jclass_loader));
 
   DCHECK_EQ(class_loader->GetClass(),
-            soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader).Ptr());
+            soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
   DCHECK_EQ(class_loader->GetParent()->GetClass(),
-            soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader).Ptr());
+            soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
 
   // The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
   // We need to get the DexPathList and loop through it.
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 126e26c..750efac 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -834,7 +834,7 @@
 void BuildQuickArgumentVisitor::FixupReferences() {
   // Fixup any references which may have changed.
   for (const auto& pair : references_) {
-    pair.second->Assign(soa_->Decode<mirror::Object>(pair.first).Ptr());
+    pair.second->Assign(soa_->Decode<mirror::Object>(pair.first));
     soa_->Env()->DeleteLocalRef(pair.first);
   }
 }
@@ -926,7 +926,7 @@
 void RememberForGcArgumentVisitor::FixupReferences() {
   // Fixup any references which may have changed.
   for (const auto& pair : references_) {
-    pair.second->Assign(soa_->Decode<mirror::Object>(pair.first).Ptr());
+    pair.second->Assign(soa_->Decode<mirror::Object>(pair.first));
     soa_->Env()->DeleteLocalRef(pair.first);
   }
 }
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 0d3af93..f3cd25c 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -52,7 +52,7 @@
         ScopedThreadStateChange tsc(self, kNative);
         jresult = fn(soa.Env(), klass.get());
       }
-      result->SetL(soa.Decode<Object>(jresult).Ptr());
+      result->SetL(soa.Decode<Object>(jresult));
     } else if (shorty == "V") {
       typedef void (fntype)(JNIEnv*, jclass);
       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
@@ -94,7 +94,7 @@
         ScopedThreadStateChange tsc(self, kNative);
         jresult = fn(soa.Env(), klass.get(), arg0.get());
       }
-      result->SetL(soa.Decode<Object>(jresult).Ptr());
+      result->SetL(soa.Decode<Object>(jresult));
     } else if (shorty == "IIZ") {
       typedef jint (fntype)(JNIEnv*, jclass, jint, jboolean);
       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
@@ -192,7 +192,7 @@
         ScopedThreadStateChange tsc(self, kNative);
         jresult = fn(soa.Env(), rcvr.get());
       }
-      result->SetL(soa.Decode<Object>(jresult).Ptr());
+      result->SetL(soa.Decode<Object>(jresult));
     } else if (shorty == "V") {
       typedef void (fntype)(JNIEnv*, jobject);
       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
@@ -213,7 +213,7 @@
         ScopedThreadStateChange tsc(self, kNative);
         jresult = fn(soa.Env(), rcvr.get(), arg0.get());
       }
-      result->SetL(soa.Decode<Object>(jresult).Ptr());
+      result->SetL(soa.Decode<Object>(jresult));
       ScopedThreadStateChange tsc(self, kNative);
     } else if (shorty == "III") {
       typedef jint (fntype)(JNIEnv*, jobject, jint, jint);
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index e12a699..46b9e80 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -953,7 +953,7 @@
     ObjPtr<mirror::Object> dex = GetDexFromDexCache(self, src->AsDexCache());
     if (dex != nullptr) {
       have_dex = true;
-      result->SetL(dex.Ptr());
+      result->SetL(dex);
     }
   }
   if (!have_dex) {
@@ -1457,7 +1457,7 @@
   ScopedLocalRef<jobject> result_jobj(env,
       InvokeMethod(soa, java_method.get(), java_receiver.get(), java_args.get()));
 
-  result->SetL(self->DecodeJObject(result_jobj.get()).Ptr());
+  result->SetL(self->DecodeJObject(result_jobj.get()));
 
   // Conservatively flag all exceptions as transaction aborts. This way we don't need to unwrap
   // InvocationTargetExceptions.
@@ -1620,9 +1620,9 @@
     uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
   ScopedObjectAccessUnchecked soa(self);
   if (Runtime::Current()->IsActiveTransaction()) {
-    result->SetL(soa.Decode<mirror::Object>(self->CreateInternalStackTrace<true>(soa)).Ptr());
+    result->SetL(soa.Decode<mirror::Object>(self->CreateInternalStackTrace<true>(soa)));
   } else {
-    result->SetL(soa.Decode<mirror::Object>(self->CreateInternalStackTrace<false>(soa)).Ptr());
+    result->SetL(soa.Decode<mirror::Object>(self->CreateInternalStackTrace<false>(soa)));
   }
 }
 
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 6828124..8eebe56 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -379,7 +379,7 @@
       // Not even a java.lang.reflect.Field, return null. TODO, is this check necessary?
       return nullptr;
     }
-    ObjPtr<mirror::Field> field = down_cast<mirror::Field*>(obj_field.Ptr());
+    ObjPtr<mirror::Field> field = ObjPtr<mirror::Field>::DownCast(obj_field);
     return soa.EncodeField(field->GetArtField());
   }
 
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 7cbcac8..d18781a 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -25,6 +25,7 @@
 #include "base/stringprintf.h"
 #include "class-inl.h"
 #include "gc/heap-inl.h"
+#include "obj_ptr-inl.h"
 #include "thread.h"
 
 namespace art {
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index aee48cc..1aa38dd 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -121,7 +121,7 @@
   art::ThrowArrayIndexOutOfBoundsException(index, GetLength());
 }
 
-void Array::ThrowArrayStoreException(Object* object) {
+void Array::ThrowArrayStoreException(ObjPtr<Object> object) {
   art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
 }
 
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 6c82eb9..04d02f7 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -20,6 +20,7 @@
 #include "base/enums.h"
 #include "gc_root.h"
 #include "gc/allocator_type.h"
+#include "obj_ptr.h"
 #include "object.h"
 #include "object_callbacks.h"
 
@@ -89,7 +90,7 @@
       REQUIRES(!Roles::uninterruptible_);
 
  protected:
-  void ThrowArrayStoreException(Object* object) REQUIRES_SHARED(Locks::mutator_lock_)
+  void ThrowArrayStoreException(ObjPtr<Object> object) REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
  private:
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 62c583b..14bd243 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -655,7 +655,7 @@
   return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Class, name_));
 }
 
-inline void Class::SetName(String* name) {
+inline void Class::SetName(ObjPtr<String> name) {
   if (Runtime::Current()->IsActiveTransaction()) {
     SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name);
   } else {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 12ce014..a5b61fd 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -347,7 +347,7 @@
   }
 
   String* GetName() REQUIRES_SHARED(Locks::mutator_lock_);  // Returns the cached name.
-  void SetName(String* name) REQUIRES_SHARED(Locks::mutator_lock_);  // Sets the cached name.
+  void SetName(ObjPtr<String> name) REQUIRES_SHARED(Locks::mutator_lock_);  // Sets the cached name.
   // Computes the name, then sets the cached value.
   static String* ComputeName(Handle<Class> h_this) REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index 940e824..adc5107 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -48,7 +48,7 @@
       self->ClearException();
     }
   }
-  auto ret = hs.NewHandle(static_cast<Field*>(StaticClass()->AllocObject(self).Ptr()));
+  auto ret = hs.NewHandle(ObjPtr<Field>::DownCast(StaticClass()->AllocObject(self)));
   if (UNLIKELY(ret.Get() == nullptr)) {
     self->AssertPendingOOMException();
     return nullptr;
@@ -80,7 +80,7 @@
 
 template<bool kTransactionActive>
 void Field::SetDeclaringClass(ObjPtr<mirror::Class> c) {
-  SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), c.Ptr());
+  SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), c);
 }
 
 }  // namespace mirror
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index d5bc256..3c2390b 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -25,6 +25,7 @@
 #include "base/stringprintf.h"
 #include "gc/heap.h"
 #include "mirror/class.h"
+#include "obj_ptr-inl.h"
 #include "runtime.h"
 #include "handle_scope-inl.h"
 #include "thread.h"
@@ -34,24 +35,29 @@
 namespace mirror {
 
 template<class T>
-inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class,
+inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
+                                             ObjPtr<Class> object_array_class,
                                              int32_t length, gc::AllocatorType allocator_type) {
-  Array* array = Array::Alloc<true>(self, object_array_class, length,
-                                    ComponentSizeShiftWidth(sizeof(HeapReference<Object>)),
+  Array* array = Array::Alloc<true>(self,
+                                    object_array_class.Ptr(),
+                                    length,
+                                    ComponentSizeShiftWidth(kHeapReferenceSize),
                                     allocator_type);
   if (UNLIKELY(array == nullptr)) {
     return nullptr;
-  } else {
-    DCHECK_EQ(array->GetClass()->GetComponentSizeShift(),
-              ComponentSizeShiftWidth(sizeof(HeapReference<Object>)));
-    return array->AsObjectArray<T>();
   }
+  DCHECK_EQ(array->GetClass()->GetComponentSizeShift(),
+            ComponentSizeShiftWidth(kHeapReferenceSize));
+  return array->AsObjectArray<T>();
 }
 
 template<class T>
-inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class,
+inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
+                                             ObjPtr<Class> object_array_class,
                                              int32_t length) {
-  return Alloc(self, object_array_class, length,
+  return Alloc(self,
+               object_array_class,
+               length,
                Runtime::Current()->GetHeap()->GetCurrentAllocator());
 }
 
@@ -65,7 +71,7 @@
 }
 
 template<class T> template<VerifyObjectFlags kVerifyFlags>
-inline bool ObjectArray<T>::CheckAssignable(T* object) {
+inline bool ObjectArray<T>::CheckAssignable(ObjPtr<T> object) {
   if (object != nullptr) {
     Class* element_class = GetClass<kVerifyFlags>()->GetComponentType();
     if (UNLIKELY(!object->InstanceOf(element_class))) {
@@ -77,7 +83,7 @@
 }
 
 template<class T>
-inline void ObjectArray<T>::Set(int32_t i, T* object) {
+inline void ObjectArray<T>::Set(int32_t i, ObjPtr<T> object) {
   if (Runtime::Current()->IsActiveTransaction()) {
     Set<true>(i, object);
   } else {
@@ -87,7 +93,7 @@
 
 template<class T>
 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
-inline void ObjectArray<T>::Set(int32_t i, T* object) {
+inline void ObjectArray<T>::Set(int32_t i, ObjPtr<T> object) {
   if (CheckIsValidIndex(i) && CheckAssignable<kVerifyFlags>(object)) {
     SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object);
   } else {
@@ -97,7 +103,7 @@
 
 template<class T>
 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
-inline void ObjectArray<T>::SetWithoutChecks(int32_t i, T* object) {
+inline void ObjectArray<T>::SetWithoutChecks(int32_t i, ObjPtr<T> object) {
   DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
   DCHECK(CheckAssignable<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(object));
   SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object);
@@ -105,7 +111,7 @@
 
 template<class T>
 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
-inline void ObjectArray<T>::SetWithoutChecksAndWriteBarrier(int32_t i, T* object) {
+inline void ObjectArray<T>::SetWithoutChecksAndWriteBarrier(int32_t i, ObjPtr<T> object) {
   DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
   // TODO:  enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
   // DCHECK(CheckAssignable(object));
@@ -120,8 +126,10 @@
 }
 
 template<class T>
-inline void ObjectArray<T>::AssignableMemmove(int32_t dst_pos, ObjectArray<T>* src,
-                                              int32_t src_pos, int32_t count) {
+inline void ObjectArray<T>::AssignableMemmove(int32_t dst_pos,
+                                              ObjPtr<ObjectArray<T>> src,
+                                              int32_t src_pos,
+                                              int32_t count) {
   if (kIsDebugBuild) {
     for (int i = 0; i < count; ++i) {
       // The get will perform the VerifyObject.
@@ -160,8 +168,10 @@
 }
 
 template<class T>
-inline void ObjectArray<T>::AssignableMemcpy(int32_t dst_pos, ObjectArray<T>* src,
-                                             int32_t src_pos, int32_t count) {
+inline void ObjectArray<T>::AssignableMemcpy(int32_t dst_pos,
+                                             ObjPtr<ObjectArray<T>> src,
+                                             int32_t src_pos,
+                                             int32_t count) {
   if (kIsDebugBuild) {
     for (int i = 0; i < count; ++i) {
       // The get will perform the VerifyObject.
@@ -190,8 +200,10 @@
 
 template<class T>
 template<bool kTransactionActive>
-inline void ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos, ObjectArray<T>* src,
-                                                     int32_t src_pos, int32_t count,
+inline void ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos,
+                                                     ObjPtr<ObjectArray<T>> src,
+                                                     int32_t src_pos,
+                                                     int32_t count,
                                                      bool throw_exception) {
   DCHECK_NE(this, src)
       << "This case should be handled with memmove that handles overlaps correctly";
@@ -258,8 +270,7 @@
 
 template<class T>
 inline MemberOffset ObjectArray<T>::OffsetOfElement(int32_t i) {
-  return MemberOffset(DataOffset(sizeof(HeapReference<Object>)).Int32Value() +
-                      (i * sizeof(HeapReference<Object>)));
+  return MemberOffset(DataOffset(kHeapReferenceSize).Int32Value() + (i * kHeapReferenceSize));
 }
 
 template<class T> template<typename Visitor>
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index 19b9d87..e4e954e 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_MIRROR_OBJECT_ARRAY_H_
 
 #include "array.h"
+#include "obj_ptr.h"
 
 namespace art {
 namespace mirror {
@@ -30,11 +31,15 @@
     return Array::ClassSize(pointer_size);
   }
 
-  static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length,
+  static ObjectArray<T>* Alloc(Thread* self,
+                               ObjPtr<Class> object_array_class,
+                               int32_t length,
                                gc::AllocatorType allocator_type)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
-  static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length)
+  static ObjectArray<T>* Alloc(Thread* self,
+                               ObjPtr<Class> object_array_class,
+                               int32_t length)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
@@ -45,13 +50,13 @@
   // an ArrayStoreException and returns false.
   // TODO fix thread safety analysis: should be REQUIRES_SHARED(Locks::mutator_lock_).
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  bool CheckAssignable(T* object) NO_THREAD_SAFETY_ANALYSIS;
+  bool CheckAssignable(ObjPtr<T> object) NO_THREAD_SAFETY_ANALYSIS;
 
-  ALWAYS_INLINE void Set(int32_t i, T* object) REQUIRES_SHARED(Locks::mutator_lock_);
+  ALWAYS_INLINE void Set(int32_t i, ObjPtr<T> object) REQUIRES_SHARED(Locks::mutator_lock_);
   // TODO fix thread safety analysis: should be REQUIRES_SHARED(Locks::mutator_lock_).
   template<bool kTransactionActive, bool kCheckTransaction = true,
       VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ALWAYS_INLINE void Set(int32_t i, T* object) NO_THREAD_SAFETY_ANALYSIS;
+  ALWAYS_INLINE void Set(int32_t i, ObjPtr<T> object) NO_THREAD_SAFETY_ANALYSIS;
 
   // Set element without bound and element type checks, to be used in limited
   // circumstances, such as during boot image writing.
@@ -59,32 +64,42 @@
   // REQUIRES_SHARED(Locks::mutator_lock_).
   template<bool kTransactionActive, bool kCheckTransaction = true,
       VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ALWAYS_INLINE void SetWithoutChecks(int32_t i, T* object) NO_THREAD_SAFETY_ANALYSIS;
+  ALWAYS_INLINE void SetWithoutChecks(int32_t i, ObjPtr<T> object) NO_THREAD_SAFETY_ANALYSIS;
   // TODO fix thread safety analysis broken by the use of template. This should be
   // REQUIRES_SHARED(Locks::mutator_lock_).
   template<bool kTransactionActive, bool kCheckTransaction = true,
       VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ALWAYS_INLINE void SetWithoutChecksAndWriteBarrier(int32_t i, T* object)
+  ALWAYS_INLINE void SetWithoutChecksAndWriteBarrier(int32_t i, ObjPtr<T> object)
       NO_THREAD_SAFETY_ANALYSIS;
 
   ALWAYS_INLINE T* GetWithoutChecks(int32_t i) REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Copy src into this array (dealing with overlaps as memmove does) without assignability checks.
-  void AssignableMemmove(int32_t dst_pos, ObjectArray<T>* src, int32_t src_pos,
-                         int32_t count) REQUIRES_SHARED(Locks::mutator_lock_);
+  void AssignableMemmove(int32_t dst_pos,
+                         ObjPtr<ObjectArray<T>> src,
+                         int32_t src_pos,
+                         int32_t count)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Copy src into this array assuming no overlap and without assignability checks.
-  void AssignableMemcpy(int32_t dst_pos, ObjectArray<T>* src, int32_t src_pos,
-                        int32_t count) REQUIRES_SHARED(Locks::mutator_lock_);
+  void AssignableMemcpy(int32_t dst_pos,
+                        ObjPtr<ObjectArray<T>> src,
+                        int32_t src_pos,
+                        int32_t count)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Copy src into this array with assignability checks.
   template<bool kTransactionActive>
-  void AssignableCheckingMemcpy(int32_t dst_pos, ObjectArray<T>* src, int32_t src_pos,
-                                int32_t count, bool throw_exception)
+  void AssignableCheckingMemcpy(int32_t dst_pos,
+                                ObjPtr<ObjectArray<T>> src,
+                                int32_t src_pos,
+                                int32_t count,
+                                bool throw_exception)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   ObjectArray<T>* CopyOf(Thread* self, int32_t new_length)
-      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!Roles::uninterruptible_);
 
   static MemberOffset OffsetOfElement(int32_t i);
 
diff --git a/runtime/mirror/object_reference-inl.h b/runtime/mirror/object_reference-inl.h
index 60955d6..e70b936 100644
--- a/runtime/mirror/object_reference-inl.h
+++ b/runtime/mirror/object_reference-inl.h
@@ -24,7 +24,11 @@
 namespace art {
 namespace mirror {
 
-// References between objects within the managed heap.
+template<bool kPoisonReferences, class MirrorType>
+void ObjectReference<kPoisonReferences, MirrorType>::Assign(ObjPtr<MirrorType> ptr) {
+  Assign(ptr.Ptr());
+}
+
 template<class MirrorType>
 HeapReference<MirrorType> HeapReference<MirrorType>::FromObjPtr(ObjPtr<MirrorType> ptr) {
   return HeapReference<MirrorType>(ptr.Ptr());
diff --git a/runtime/mirror/object_reference.h b/runtime/mirror/object_reference.h
index 573cb30..71f34c6 100644
--- a/runtime/mirror/object_reference.h
+++ b/runtime/mirror/object_reference.h
@@ -42,6 +42,9 @@
     reference_ = Compress(other);
   }
 
+  void Assign(ObjPtr<MirrorType> ptr)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   void Clear() {
     reference_ = 0;
     DCHECK(IsNull());
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 7563161..ceb37c4 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -354,8 +354,8 @@
   ObjPtr<mirror::Constructor> result =
       mirror::Class::GetDeclaredConstructorInternal<kRuntimePointerSize, false>(
       soa.Self(),
-      DecodeClass(soa, javaThis).Ptr(),
-      soa.Decode<mirror::ObjectArray<mirror::Class>>(args).Ptr());
+      DecodeClass(soa, javaThis),
+      soa.Decode<mirror::ObjectArray<mirror::Class>>(args));
   return soa.AddLocalReference<jobject>(result);
 }
 
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index e317c25..a0a6a12 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -38,7 +38,7 @@
     ObjPtr<mirror::Class> annotation_array_class =
         soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
     ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
-        mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class.Ptr(), 0);
+        mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
     return soa.AddLocalReference<jobjectArray>(empty_array);
   }
   return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForMethod(method));
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index 0bdb5a4..670c4ac 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -71,8 +71,8 @@
         field_addr);
   }
   bool success = obj->CasFieldStrongSequentiallyConsistentObject<false>(MemberOffset(offset),
-                                                                        expectedValue.Ptr(),
-                                                                        newValue.Ptr());
+                                                                        expectedValue,
+                                                                        newValue);
   return success ? JNI_TRUE : JNI_FALSE;
 }
 
@@ -168,7 +168,7 @@
   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
   // JNI must use non transactional mode.
-  obj->SetFieldObject<false>(MemberOffset(offset), newValue.Ptr());
+  obj->SetFieldObject<false>(MemberOffset(offset), newValue);
 }
 
 static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
@@ -177,7 +177,7 @@
   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
   // JNI must use non transactional mode.
-  obj->SetFieldObjectVolatile<false>(MemberOffset(offset), newValue.Ptr());
+  obj->SetFieldObjectVolatile<false>(MemberOffset(offset), newValue);
 }
 
 static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
@@ -187,7 +187,7 @@
   ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
   QuasiAtomic::ThreadFenceRelease();
   // JNI must use non transactional mode.
-  obj->SetFieldObject<false>(MemberOffset(offset), newValue.Ptr());
+  obj->SetFieldObject<false>(MemberOffset(offset), newValue);
 }
 
 static jint Unsafe_getArrayBaseOffsetForComponentType(JNIEnv* env, jclass, jobject component_class) {
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 098eb03..72db827 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -772,7 +772,7 @@
       }
       return false;
     }
-    unboxed_value->SetL(o.Ptr());
+    unboxed_value->SetL(o);
     return true;
   }
   if (UNLIKELY(dst_class->GetPrimitiveType() == Primitive::kPrimVoid)) {
diff --git a/runtime/scoped_thread_state_change-inl.h b/runtime/scoped_thread_state_change-inl.h
index 1ebfd30..bde23c8 100644
--- a/runtime/scoped_thread_state_change-inl.h
+++ b/runtime/scoped_thread_state_change-inl.h
@@ -83,7 +83,7 @@
 inline ObjPtr<T, kPoison> ScopedObjectAccessAlreadyRunnable::Decode(jobject obj) const {
   Locks::mutator_lock_->AssertSharedHeld(Self());
   DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
-  return down_cast<T*>(Self()->DecodeJObject(obj).Ptr());
+  return ObjPtr<T, kPoison>::DownCast(Self()->DecodeJObject(obj));
 }
 
 inline ArtField* ScopedObjectAccessAlreadyRunnable::DecodeField(jfieldID fid) const {