Use ObjPtr for reflection.cc/h/inl

Changed Pretty helpers to use this to reduce usage of Decode. The
eventual goal is not have almost any calls to ObjPtr::Decode.

Moved ObjPtr out of mirror namespace for convenience. Added more
PoisonObjectPointers calls in class linker, thread suspension.

Bug: 31113334

Test: test-art-host

Change-Id: I44d08db5143d95ed1b65e2f00f9749ef5cf379f7
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index caabcde..d5b3090 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -70,6 +70,7 @@
         mirror::StringDexCachePair::LookupString(declaring_class->GetDexCacheStrings(),
                                                  string_idx,
                                                  mirror::DexCache::kDexCacheStringCacheSize).Read();
+  Thread::PoisonObjectPointersIfDebug();
   if (UNLIKELY(string == nullptr)) {
     StackHandleScope<1> hs(Thread::Current());
     Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
@@ -84,6 +85,7 @@
 
 inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, ArtMethod* referrer) {
   mirror::Class* resolved_type = referrer->GetDexCacheResolvedType(type_idx, image_pointer_size_);
+  Thread::PoisonObjectPointersIfDebug();
   if (UNLIKELY(resolved_type == nullptr)) {
     mirror::Class* declaring_class = referrer->GetDeclaringClass();
     StackHandleScope<2> hs(Thread::Current());
@@ -101,6 +103,7 @@
   mirror::Class* declaring_class = referrer->GetDeclaringClass();
   mirror::DexCache* dex_cache_ptr = declaring_class->GetDexCache();
   mirror::Class* resolved_type = dex_cache_ptr->GetResolvedType(type_idx);
+  Thread::PoisonObjectPointersIfDebug();
   if (UNLIKELY(resolved_type == nullptr)) {
     StackHandleScope<2> hs(Thread::Current());
     Handle<mirror::DexCache> dex_cache(hs.NewHandle(dex_cache_ptr));
@@ -148,6 +151,7 @@
                                              ArtMethod* referrer,
                                              InvokeType type) {
   ArtMethod* resolved_method = GetResolvedMethod(method_idx, referrer);
+  Thread::PoisonObjectPointersIfDebug();
   if (UNLIKELY(resolved_method == nullptr)) {
     mirror::Class* declaring_class = referrer->GetDeclaringClass();
     StackHandleScope<2> hs(self);
@@ -179,6 +183,7 @@
                                            bool is_static) {
   mirror::Class* declaring_class = referrer->GetDeclaringClass();
   ArtField* resolved_field = GetResolvedField(field_idx, declaring_class);
+  Thread::PoisonObjectPointersIfDebug();
   if (UNLIKELY(resolved_field == nullptr)) {
     StackHandleScope<2> hs(Thread::Current());
     Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index ecaa4c2..eb38a8c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2167,6 +2167,7 @@
                                            const char* descriptor,
                                            mirror::Class* klass) {
   DCHECK(klass != nullptr);
+  self->PoisonObjectPointers();
 
   // For temporary classes we must wait for them to be retired.
   if (init_done_ && klass->IsTemp()) {
@@ -2378,7 +2379,7 @@
   DCHECK_NE(*descriptor, '\0') << "descriptor is empty string";
   DCHECK(self != nullptr);
   self->AssertNoPendingException();
-  self->PoisonObjectPointers();
+  self->PoisonObjectPointers();  // For DefineClass, CreateArrayClass, etc...
   if (descriptor[1] == '\0') {
     // only the descriptors of primitive types should be 1 character long, also avoid class lookup
     // for primitive classes that aren't backed by dex files.
@@ -7524,6 +7525,7 @@
                                            Handle<mirror::DexCache> dex_cache) {
   DCHECK(dex_cache.Get() != nullptr);
   mirror::String* resolved = dex_cache->GetResolvedString(string_idx);
+  Thread::PoisonObjectPointersIfDebug();
   if (resolved != nullptr) {
     return resolved;
   }
@@ -7566,6 +7568,7 @@
                                         Handle<mirror::ClassLoader> class_loader) {
   DCHECK(dex_cache.Get() != nullptr);
   mirror::Class* resolved = dex_cache->GetResolvedType(type_idx);
+  Thread::PoisonObjectPointersIfDebug();
   if (resolved == nullptr) {
     Thread* self = Thread::Current();
     const char* descriptor = dex_file.StringByTypeIdx(type_idx);
@@ -7604,6 +7607,7 @@
   DCHECK(dex_cache.Get() != nullptr);
   // Check for hit in the dex cache.
   ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, image_pointer_size_);
+  Thread::PoisonObjectPointersIfDebug();
   if (resolved != nullptr && !resolved->IsRuntimeMethod()) {
     DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex();
     if (kResolveMode == ClassLinker::kForceICCECheck) {
@@ -7807,6 +7811,7 @@
                                                        Handle<mirror::DexCache> dex_cache,
                                                        Handle<mirror::ClassLoader> class_loader) {
   ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, image_pointer_size_);
+  Thread::PoisonObjectPointersIfDebug();
   if (resolved != nullptr && !resolved->IsRuntimeMethod()) {
     DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex();
     return resolved;
@@ -7839,6 +7844,7 @@
                                     bool is_static) {
   DCHECK(dex_cache.Get() != nullptr);
   ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
+  Thread::PoisonObjectPointersIfDebug();
   if (resolved != nullptr) {
     return resolved;
   }
@@ -7881,6 +7887,7 @@
                                        Handle<mirror::ClassLoader> class_loader) {
   DCHECK(dex_cache.Get() != nullptr);
   ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
+  Thread::PoisonObjectPointersIfDebug();
   if (resolved != nullptr) {
     return resolved;
   }
diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc
index c6c87fd..c3cf53b 100644
--- a/runtime/dex_file_annotations.cc
+++ b/runtime/dex_file_annotations.cc
@@ -572,7 +572,7 @@
   *annotation_ptr = annotation;
 
   if (result_style == DexFile::kAllObjects && primitive_type != Primitive::kPrimVoid) {
-    element_object = BoxPrimitive(primitive_type, annotation_value->value_);
+    element_object = BoxPrimitive(primitive_type, annotation_value->value_).Decode();
     set_object = true;
   }
 
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index fd9ffbd..bfa2b69 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -160,7 +160,7 @@
       } else {
         JValue jv;
         jv.SetJ(args.at(i).j);
-        mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv);
+        mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv).Decode();
         if (val == nullptr) {
           CHECK(soa.Self()->IsExceptionPending());
           return zero;
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index b0ca18e..6d61c64 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -50,6 +50,7 @@
     CHECK_EQ(self->GetState(), kRunnable);
     self->AssertThreadSuspensionIsAllowable();
     self->AssertNoPendingException();
+    self->PoisonObjectPointers();
   }
   // Need to check that we arent the large object allocator since the large object allocation code
   // path this function. If we didn't check we would have an infinite loop.
diff --git a/runtime/handle.h b/runtime/handle.h
index d4c13d4..c41010a 100644
--- a/runtime/handle.h
+++ b/runtime/handle.h
@@ -23,6 +23,7 @@
 #include "base/mutex.h"
 #include "base/value_object.h"
 #include "jni.h"
+#include "obj_ptr.h"
 #include "stack_reference.h"
 
 namespace art {
@@ -130,6 +131,14 @@
     return old;
   }
 
+  ALWAYS_INLINE T* Assign(ObjPtr<T> reference) REQUIRES_SHARED(Locks::mutator_lock_) {
+    StackReference<mirror::Object>* ref = Handle<T>::GetReference();
+    T* old = down_cast<T*>(ref->AsMirrorPtr());
+    ref->Assign(reference.Decode());
+    return old;
+  }
+
+
   template<typename S>
   explicit MutableHandle(const MutableHandle<S>& handle) REQUIRES_SHARED(Locks::mutator_lock_)
       : Handle<T>(handle) {
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 0f5cbb2..ad7558c 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -31,6 +31,7 @@
 #include "lock_word-inl.h"
 #include "monitor.h"
 #include "object_array-inl.h"
+#include "obj_ptr-inl.h"
 #include "read_barrier-inl.h"
 #include "reference.h"
 #include "runtime.h"
@@ -281,7 +282,7 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline bool Object::InstanceOf(Class* klass) {
+inline bool Object::InstanceOf(ObjPtr<Class> klass) {
   DCHECK(klass != nullptr);
   DCHECK(GetClass<kVerifyNone>() != nullptr);
   return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
@@ -509,7 +510,7 @@
         template GetObjectSize<kNewFlags, kReadBarrierOption>();
   }
   DCHECK_GE(result, sizeof(Object))
-      << " class=" << PrettyTypeOf(GetClass<kNewFlags, kReadBarrierOption>());
+      << " class=" << PrettyClass(GetClass<kNewFlags, kReadBarrierOption>());
   return result;
 }
 
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 262cb57..10faf60 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -20,6 +20,7 @@
 #include "base/casts.h"
 #include "base/enums.h"
 #include "globals.h"
+#include "obj_ptr.h"
 #include "object_reference.h"
 #include "offsets.h"
 #include "verify_object.h"
@@ -120,7 +121,7 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool VerifierInstanceOf(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ALWAYS_INLINE bool InstanceOf(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
+  ALWAYS_INLINE bool InstanceOf(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index f4ecfb5..0f3447e 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -746,7 +746,7 @@
   ObjPtr<mirror::Object, /*kPoison*/ true> null_ptr;
   EXPECT_TRUE(null_ptr.IsNull());
   EXPECT_TRUE(null_ptr.IsValid());
-  EXPECT_TRUE(null_ptr.Get() == nullptr);
+  EXPECT_TRUE(null_ptr.Decode() == nullptr);
   EXPECT_TRUE(null_ptr == nullptr);
   EXPECT_TRUE(null_ptr == null_ptr);
   EXPECT_FALSE(null_ptr != null_ptr);
@@ -758,13 +758,13 @@
   ObjPtr<Class, /*kPoison*/ true> X(h_X.Get());
   EXPECT_TRUE(!X.IsNull());
   EXPECT_TRUE(X.IsValid());
-  EXPECT_TRUE(X.Get() != nullptr);
-  EXPECT_EQ(h_X.Get(), X.Get());
+  EXPECT_TRUE(X.Decode() != nullptr);
+  EXPECT_EQ(h_X.Get(), X.Decode());
   // FindClass may cause thread suspension, it should invalidate X.
   ObjPtr<Class, /*kPoison*/ true> Y(class_linker_->FindClass(soa.Self(), "LY;", class_loader));
   EXPECT_TRUE(!Y.IsNull());
   EXPECT_TRUE(Y.IsValid());
-  EXPECT_TRUE(Y.Get() != nullptr);
+  EXPECT_TRUE(Y.Decode() != nullptr);
 
   // Should IsNull be safe to call on null ObjPtr? I'll allow it for now.
   EXPECT_TRUE(!X.IsNull());
@@ -773,7 +773,7 @@
   X.Assign(h_X.Get());
   EXPECT_TRUE(!X.IsNull());
   EXPECT_TRUE(X.IsValid());
-  EXPECT_EQ(h_X.Get(), X.Get());
+  EXPECT_EQ(h_X.Get(), X.Decode());
 
   // Allow thread suspension to invalidate Y.
   soa.Self()->AllowThreadSuspension();
@@ -784,7 +784,7 @@
   ObjPtr<mirror::Object, /*kPoison*/ false> unpoisoned;
   EXPECT_TRUE(unpoisoned.IsNull());
   EXPECT_TRUE(unpoisoned.IsValid());
-  EXPECT_TRUE(unpoisoned.Get() == nullptr);
+  EXPECT_TRUE(unpoisoned.Decode() == nullptr);
   EXPECT_TRUE(unpoisoned == nullptr);
   EXPECT_TRUE(unpoisoned == unpoisoned);
   EXPECT_FALSE(unpoisoned != unpoisoned);
@@ -793,7 +793,7 @@
   unpoisoned = h_X.Get();
   EXPECT_FALSE(unpoisoned.IsNull());
   EXPECT_TRUE(unpoisoned == h_X.Get());
-  EXPECT_EQ(unpoisoned.Get(), h_X.Get());
+  EXPECT_EQ(unpoisoned.Decode(), h_X.Get());
 }
 
 }  // namespace mirror
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index af9b68f..b6260e9 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -33,6 +33,7 @@
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/string-inl.h"
+#include "obj_ptr-inl.h"
 #include "reflection.h"
 #include "scoped_thread_state_change.h"
 #include "scoped_fast_native_object_access.h"
@@ -669,7 +670,10 @@
       caller.Assign(GetCallingClass(soa.Self(), 1));
     }
     if (UNLIKELY(caller.Get() != nullptr && !VerifyAccess(
-        receiver.Get(), declaring_class, constructor->GetAccessFlags(), caller.Get()))) {
+        MakeObjPtr(receiver.Get()),
+        MakeObjPtr(declaring_class),
+        constructor->GetAccessFlags(),
+        MakeObjPtr(caller.Get())))) {
       soa.Self()->ThrowNewExceptionF(
           "Ljava/lang/IllegalAccessException;", "%s is not accessible from %s",
           PrettyMethod(constructor).c_str(), PrettyClass(caller.Get()).c_str());
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index d001d0c..47c49d5 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -73,7 +73,7 @@
   if (!m->IsAccessible() && !c->IsPublic()) {
     // Go 2 frames back, this method is always called from newInstance0, which is called from
     // Constructor.newInstance(Object... args).
-    auto* caller = GetCallingClass(soa.Self(), 2);
+    ObjPtr<mirror::Class> caller = GetCallingClass(soa.Self(), 2);
     // If caller is null, then we called from JNI, just avoid the check since JNI avoids most
     // access checks anyways. TODO: Investigate if this the correct behavior.
     if (caller != nullptr && !caller->CanAccess(c.Get())) {
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 412445f..dab510d 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -43,9 +43,13 @@
                     PrettyClass(field->GetDeclaringClass()).c_str()).c_str());
     return false;
   }
-  mirror::Class* calling_class = nullptr;
-  if (!VerifyAccess(self, obj, field->GetDeclaringClass(), field->GetAccessFlags(),
-                    &calling_class, 1)) {
+  ObjPtr<mirror::Class> calling_class;
+  if (!VerifyAccess(self,
+                    MakeObjPtr(obj),
+                    MakeObjPtr(field->GetDeclaringClass()),
+                    field->GetAccessFlags(),
+                    &calling_class,
+                    1)) {
     ThrowIllegalAccessException(
             StringPrintf("Class %s cannot access %s field %s of class %s",
                 calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(),
@@ -124,7 +128,7 @@
     return true;
   }
   *class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr);
-  if (!VerifyObjectIsClass(*class_or_rcvr, declaringClass)) {
+  if (!VerifyObjectIsClass(MakeObjPtr(*class_or_rcvr), MakeObjPtr(declaringClass))) {
     DCHECK(soa.Self()->IsExceptionPending());
     return false;
   }
@@ -152,7 +156,7 @@
     DCHECK(soa.Self()->IsExceptionPending());
     return nullptr;
   }
-  return soa.AddLocalReference<jobject>(BoxPrimitive(field_type, value));
+  return soa.AddLocalReference<jobject>(BoxPrimitive(field_type, value).Decode());
 }
 
 template<Primitive::Type kPrimitiveType>
@@ -323,7 +327,10 @@
   // Unbox the value, if necessary.
   mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue);
   JValue unboxed_value;
-  if (!UnboxPrimitiveForField(boxed_value, field_type, f->GetArtField(), &unboxed_value)) {
+  if (!UnboxPrimitiveForField(MakeObjPtr(boxed_value),
+                              MakeObjPtr(field_type),
+                              f->GetArtField(),
+                              &unboxed_value)) {
     DCHECK(soa.Self()->IsExceptionPending());
     return;
   }
diff --git a/runtime/obj_ptr-inl.h b/runtime/obj_ptr-inl.h
new file mode 100644
index 0000000..3dfcf9e
--- /dev/null
+++ b/runtime/obj_ptr-inl.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 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_OBJ_PTR_INL_H_
+#define ART_RUNTIME_OBJ_PTR_INL_H_
+
+#include "obj_ptr.h"
+#include "thread-inl.h"
+
+namespace art {
+
+template<class MirrorType, bool kPoison>
+inline bool ObjPtr<MirrorType, kPoison>::IsValid() const {
+  if (!kPoison || IsNull()) {
+    return true;
+  }
+  return GetCookie() == TrimCookie(Thread::Current()->GetPoisonObjectCookie());
+}
+
+template<class MirrorType, bool kPoison>
+inline void ObjPtr<MirrorType, kPoison>::AssertValid() const {
+  if (kPoison) {
+    CHECK(IsValid()) << "Stale object pointer " << DecodeUnchecked() << " , expected cookie "
+        << TrimCookie(Thread::Current()->GetPoisonObjectCookie()) << " but got " << GetCookie();
+  }
+}
+
+template<class MirrorType, bool kPoison>
+inline uintptr_t ObjPtr<MirrorType, kPoison>::Encode(MirrorType* ptr) {
+  uintptr_t ref = reinterpret_cast<uintptr_t>(ptr);
+  if (kPoison && ref != 0) {
+    DCHECK_LE(ref, 0xFFFFFFFFU);
+    ref >>= kObjectAlignmentShift;
+    // Put cookie in high bits.
+    Thread* self = Thread::Current();
+    DCHECK(self != nullptr);
+    ref |= self->GetPoisonObjectCookie() << kCookieShift;
+  }
+  return ref;
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_OBJ_PTR_INL_H_
diff --git a/runtime/mirror/obj_ptr.h b/runtime/obj_ptr.h
similarity index 73%
rename from runtime/mirror/obj_ptr.h
rename to runtime/obj_ptr.h
index 10378e8..d4076be 100644
--- a/runtime/mirror/obj_ptr.h
+++ b/runtime/obj_ptr.h
@@ -14,23 +14,18 @@
  * limitations under the License.
  */
 
-#ifndef ART_RUNTIME_MIRROR_OBJ_PTR_H_
-#define ART_RUNTIME_MIRROR_OBJ_PTR_H_
+#ifndef ART_RUNTIME_OBJ_PTR_H_
+#define ART_RUNTIME_OBJ_PTR_H_
 
 #include "base/mutex.h"  // For Locks::mutator_lock_.
 #include "globals.h"
 #include "mirror/object_reference.h"
-#include "utils.h"
 
 namespace art {
-namespace mirror {
-
-class Object;
 
 // Value type representing a pointer to a mirror::Object of type MirrorType
 // Pass kPoison as a template boolean for testing in non-debug builds.
-// Note that the functions are not 100% thread safe and may have spurious positive check passes in
-// these cases.
+// Since the cookie is thread based, it is not safe to share an ObjPtr between threads.
 template<class MirrorType, bool kPoison = kIsDebugBuild>
 class ObjPtr {
   static constexpr size_t kCookieShift =
@@ -44,11 +39,13 @@
  public:
   ALWAYS_INLINE ObjPtr() REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
 
-  ALWAYS_INLINE explicit ObjPtr(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_)
-      : reference_(Encode(ptr)) {}
+  ALWAYS_INLINE ObjPtr(std::nullptr_t) REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
 
-  ALWAYS_INLINE explicit ObjPtr(const ObjPtr& other) REQUIRES_SHARED(Locks::mutator_lock_)
-      = default;
+  template <typename Type>
+  ALWAYS_INLINE ObjPtr(Type* ptr) REQUIRES_SHARED(Locks::mutator_lock_)
+      : reference_(Encode(static_cast<MirrorType*>(ptr))) {}
+
+  ALWAYS_INLINE ObjPtr(const ObjPtr& other) REQUIRES_SHARED(Locks::mutator_lock_) = default;
 
   ALWAYS_INLINE ObjPtr& operator=(const ObjPtr& other) {
     reference_ = other.reference_;
@@ -65,30 +62,23 @@
   }
 
   ALWAYS_INLINE MirrorType* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
-    return Get();
-  }
-
-  ALWAYS_INLINE MirrorType* Get() const REQUIRES_SHARED(Locks::mutator_lock_) {
     return Decode();
   }
 
+
   ALWAYS_INLINE bool IsNull() const {
     return reference_ == 0;
   }
 
-  ALWAYS_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (!kPoison || IsNull()) {
-      return true;
-    }
-    return GetCookie() == TrimCookie(Thread::Current()->GetPoisonObjectCookie());
+  // Decode makes sure that the object pointer is valid.
+  ALWAYS_INLINE MirrorType* Decode() const REQUIRES_SHARED(Locks::mutator_lock_) {
+    AssertValid();
+    return DecodeUnchecked();
   }
 
-  ALWAYS_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (kPoison) {
-      CHECK(IsValid()) << "Stale object pointer, expected cookie "
-          << TrimCookie(Thread::Current()->GetPoisonObjectCookie()) << " but got " << GetCookie();
-    }
-  }
+  ALWAYS_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_);
+
+  ALWAYS_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_);
 
   ALWAYS_INLINE bool operator==(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
     return Decode() == ptr.Decode();
@@ -124,22 +114,8 @@
     return reference_ >> kCookieShift;
   }
 
-  ALWAYS_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
-    uintptr_t ref = reinterpret_cast<uintptr_t>(ptr);
-    if (kPoison && ref != 0) {
-      DCHECK_LE(ref, 0xFFFFFFFFU);
-      ref >>= kObjectAlignmentShift;
-      // Put cookie in high bits.
-      Thread* self = Thread::Current();
-      DCHECK(self != nullptr);
-      ref |= self->GetPoisonObjectCookie() << kCookieShift;
-    }
-    return ref;
-  }
-
   // Decode makes sure that the object pointer is valid.
-  ALWAYS_INLINE MirrorType* Decode() const REQUIRES_SHARED(Locks::mutator_lock_) {
-    AssertValid();
+  ALWAYS_INLINE MirrorType* DecodeUnchecked() const REQUIRES_SHARED(Locks::mutator_lock_) {
     if (kPoison) {
       return reinterpret_cast<MirrorType*>(
           static_cast<uintptr_t>(static_cast<uint32_t>(reference_ << kObjectAlignmentShift)));
@@ -148,12 +124,16 @@
     }
   }
 
+  ALWAYS_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
   // The encoded reference and cookie.
   uintptr_t reference_;
 };
 
+template<class MirrorType, bool kPoison = kIsDebugBuild>
+static inline ObjPtr<MirrorType, kPoison> MakeObjPtr(MirrorType* ptr) {
+  return ObjPtr<MirrorType, kPoison>(ptr);
+}
 
-}  // namespace mirror
 }  // namespace art
 
-#endif  // ART_RUNTIME_MIRROR_OBJ_PTR_H_
+#endif  // ART_RUNTIME_OBJ_PTR_H_
diff --git a/runtime/reflection-inl.h b/runtime/reflection-inl.h
index f54d4ca..d7db8a4 100644
--- a/runtime/reflection-inl.h
+++ b/runtime/reflection-inl.h
@@ -23,14 +23,17 @@
 #include "common_throws.h"
 #include "jvalue.h"
 #include "mirror/object-inl.h"
+#include "obj_ptr-inl.h"
 #include "primitive.h"
 #include "utils.h"
 
 namespace art {
 
 inline bool ConvertPrimitiveValue(bool unbox_for_result,
-                                  Primitive::Type srcType, Primitive::Type dstType,
-                                  const JValue& src, JValue* dst) {
+                                  Primitive::Type srcType,
+                                  Primitive::Type dstType,
+                                  const JValue& src,
+                                  JValue* dst) {
   DCHECK(srcType != Primitive::kPrimNot && dstType != Primitive::kPrimNot);
   if (LIKELY(srcType == dstType)) {
     dst->SetJ(src.GetJ());
@@ -100,11 +103,11 @@
   return false;
 }
 
-inline bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) {
+inline bool VerifyObjectIsClass(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c) {
   if (UNLIKELY(o == nullptr)) {
     ThrowNullPointerException("null receiver");
     return false;
-  } else if (UNLIKELY(!o->InstanceOf(c))) {
+  } else if (UNLIKELY(!o->InstanceOf(c.Decode()))) {
     InvalidReceiverError(o, c);
     return false;
   }
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 30b10d8..7c0f2b5 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -72,8 +72,8 @@
     num_bytes_ += 4;
   }
 
-  void Append(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
-    Append(StackReference<mirror::Object>::FromMirrorPtr(obj).AsVRegValue());
+  void Append(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) {
+    Append(StackReference<mirror::Object>::FromMirrorPtr(obj.Decode()).AsVRegValue());
   }
 
   void AppendWide(uint64_t value) {
@@ -95,7 +95,8 @@
   }
 
   void BuildArgArrayFromVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
-                                mirror::Object* receiver, va_list ap)
+                                ObjPtr<mirror::Object> receiver,
+                                va_list ap)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     // Set receiver if non-null (method is not static)
     if (receiver != nullptr) {
@@ -131,7 +132,7 @@
   }
 
   void BuildArgArrayFromJValues(const ScopedObjectAccessAlreadyRunnable& soa,
-                                mirror::Object* receiver, jvalue* args)
+                                ObjPtr<mirror::Object> receiver, jvalue* args)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     // Set receiver if non-null (method is not static)
     if (receiver != nullptr) {
@@ -212,8 +213,9 @@
                      PrettyDescriptor(found_descriptor).c_str()).c_str());
   }
 
-  bool BuildArgArrayFromObjectArray(mirror::Object* receiver,
-                                    mirror::ObjectArray<mirror::Object>* args, ArtMethod* m)
+  bool BuildArgArrayFromObjectArray(ObjPtr<mirror::Object> receiver,
+                                    ObjPtr<mirror::ObjectArray<mirror::Object>> args,
+                                    ArtMethod* m)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     const DexFile::TypeList* classes = m->GetParameterTypeList();
     // Set receiver if non-null (method is not static)
@@ -221,13 +223,13 @@
       Append(receiver);
     }
     for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
-      mirror::Object* arg = args->Get(args_offset);
+      ObjPtr<mirror::Object> arg(args->Get(args_offset));
       if (((shorty_[i] == 'L') && (arg != nullptr)) || ((arg == nullptr && shorty_[i] != 'L'))) {
         PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
-        mirror::Class* dst_class =
+        ObjPtr<mirror::Class> dst_class(
             m->GetClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_,
                                      true /* resolve */,
-                                     pointer_size);
+                                     pointer_size));
         if (UNLIKELY(arg == nullptr || !arg->InstanceOf(dst_class))) {
           ThrowIllegalArgumentException(
               StringPrintf("method %s argument %zd has type %s, got %s",
@@ -240,15 +242,15 @@
       }
 
 #define DO_FIRST_ARG(match_descriptor, get_fn, append) { \
-          if (LIKELY(arg != nullptr && arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
+          if (LIKELY(arg != nullptr && arg->GetClass()->DescriptorEquals(match_descriptor))) { \
             ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
-            append(primitive_field-> get_fn(arg));
+            append(primitive_field-> get_fn(arg.Decode()));
 
 #define DO_ARG(match_descriptor, get_fn, append) \
           } else if (LIKELY(arg != nullptr && \
                             arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
             ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
-            append(primitive_field-> get_fn(arg));
+            append(primitive_field-> get_fn(arg.Decode()));
 
 #define DO_FAIL(expected) \
           } else { \
@@ -362,9 +364,9 @@
   PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
   for (uint32_t i = 0; i < num_params; i++) {
     uint16_t type_idx = params->GetTypeItem(i).type_idx_;
-    mirror::Class* param_type = m->GetClassFromTypeIndex(type_idx,
-                                                         true /* resolve*/,
-                                                         pointer_size);
+    ObjPtr<mirror::Class> param_type(m->GetClassFromTypeIndex(type_idx,
+                                                              true /* resolve*/,
+                                                              pointer_size));
     if (param_type == nullptr) {
       CHECK(self->IsExceptionPending());
       LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: "
@@ -376,7 +378,7 @@
       // TODO: There is a compaction bug here since GetClassFromTypeIdx can cause thread suspension,
       // this is a hard to fix problem since the args can contain Object*, we need to save and
       // restore them by using a visitor similar to the ones used in the trampoline entrypoints.
-      mirror::Object* argument =
+      ObjPtr<mirror::Object> argument =
           (reinterpret_cast<StackReference<mirror::Object>*>(&args[i + offset]))->AsMirrorPtr();
       if (argument != nullptr && !argument->InstanceOf(param_type)) {
         LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of "
@@ -423,7 +425,7 @@
   }
 }
 
-static ArtMethod* FindVirtualMethod(mirror::Object* receiver, ArtMethod* method)
+static ArtMethod* FindVirtualMethod(ObjPtr<mirror::Object> receiver, ArtMethod* method)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method, kRuntimePointerSize);
 }
@@ -457,7 +459,7 @@
     // Replace calls to String.<init> with equivalent StringFactory call.
     method = WellKnownClasses::StringInitToStringFactory(method);
   }
-  mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj);
+  ObjPtr<mirror::Object> receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj);
   uint32_t shorty_len = 0;
   const char* shorty =
       method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
@@ -488,7 +490,7 @@
     // Replace calls to String.<init> with equivalent StringFactory call.
     method = WellKnownClasses::StringInitToStringFactory(method);
   }
-  mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj);
+  ObjPtr<mirror::Object> receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj);
   uint32_t shorty_len = 0;
   const char* shorty =
       method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
@@ -513,7 +515,7 @@
     return JValue();
   }
 
-  mirror::Object* receiver = soa.Decode<mirror::Object*>(obj);
+  ObjPtr<mirror::Object> receiver = soa.Decode<mirror::Object*>(obj);
   ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
   bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
   if (is_string_init) {
@@ -545,7 +547,7 @@
     return JValue();
   }
 
-  mirror::Object* receiver = soa.Decode<mirror::Object*>(obj);
+  ObjPtr<mirror::Object> receiver = soa.Decode<mirror::Object*>(obj);
   ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
   bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
   if (is_string_init) {
@@ -578,21 +580,21 @@
     return nullptr;
   }
 
-  auto* executable = soa.Decode<mirror::Executable*>(javaMethod);
+  ObjPtr<mirror::Executable> executable = soa.Decode<mirror::Executable*>(javaMethod);
   const bool accessible = executable->IsAccessible();
   ArtMethod* m = executable->GetArtMethod();
 
-  mirror::Class* declaring_class = m->GetDeclaringClass();
+  ObjPtr<mirror::Class> declaring_class = m->GetDeclaringClass();
   if (UNLIKELY(!declaring_class->IsInitialized())) {
     StackHandleScope<1> hs(soa.Self());
-    Handle<mirror::Class> h_class(hs.NewHandle(declaring_class));
+    Handle<mirror::Class> h_class(hs.NewHandle(declaring_class.Decode()));
     if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(soa.Self(), h_class, true, true)) {
       return nullptr;
     }
     declaring_class = h_class.Get();
   }
 
-  mirror::Object* receiver = nullptr;
+  ObjPtr<mirror::Object> receiver;
   if (!m->IsStatic()) {
     // Replace calls to String.<init> with equivalent StringFactory call.
     if (declaring_class->IsStringClass() && m->IsConstructor()) {
@@ -623,7 +625,7 @@
   }
 
   // If method is not set to be accessible, verify it can be accessed by the caller.
-  mirror::Class* calling_class = nullptr;
+  ObjPtr<mirror::Class> calling_class;
   if (!accessible && !VerifyAccess(soa.Self(),
                                    receiver,
                                    declaring_class,
@@ -674,10 +676,11 @@
   }
 
   // Box if necessary and return.
-  return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result));
+  return soa.AddLocalReference<jobject>(
+      BoxPrimitive(Primitive::GetType(shorty[0]), result).Decode());
 }
 
-mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) {
+ObjPtr<mirror::Object> BoxPrimitive(Primitive::Type src_class, const JValue& value) {
   if (src_class == Primitive::kPrimNot) {
     return value.GetL();
   }
@@ -750,8 +753,9 @@
   return "result";
 }
 
-static bool UnboxPrimitive(mirror::Object* o,
-                           mirror::Class* dst_class, ArtField* f,
+static bool UnboxPrimitive(ObjPtr<mirror::Object> o,
+                           ObjPtr<mirror::Class> dst_class,
+                           ArtField* f,
                            JValue* unboxed_value)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   bool unbox_for_result = (f == nullptr);
@@ -769,7 +773,7 @@
       }
       return false;
     }
-    unboxed_value->SetL(o);
+    unboxed_value->SetL(o.Decode());
     return true;
   }
   if (UNLIKELY(dst_class->GetPrimitiveType() == Primitive::kPrimVoid)) {
@@ -791,34 +795,34 @@
   }
 
   JValue boxed_value;
-  mirror::Class* klass = o->GetClass();
-  mirror::Class* src_class = nullptr;
+  ObjPtr<mirror::Class> klass = o->GetClass();
+  ObjPtr<mirror::Class> src_class = nullptr;
   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
   ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0);
   if (klass->DescriptorEquals("Ljava/lang/Boolean;")) {
     src_class = class_linker->FindPrimitiveClass('Z');
-    boxed_value.SetZ(primitive_field->GetBoolean(o));
+    boxed_value.SetZ(primitive_field->GetBoolean(o.Decode()));
   } else if (klass->DescriptorEquals("Ljava/lang/Byte;")) {
     src_class = class_linker->FindPrimitiveClass('B');
-    boxed_value.SetB(primitive_field->GetByte(o));
+    boxed_value.SetB(primitive_field->GetByte(o.Decode()));
   } else if (klass->DescriptorEquals("Ljava/lang/Character;")) {
     src_class = class_linker->FindPrimitiveClass('C');
-    boxed_value.SetC(primitive_field->GetChar(o));
+    boxed_value.SetC(primitive_field->GetChar(o.Decode()));
   } else if (klass->DescriptorEquals("Ljava/lang/Float;")) {
     src_class = class_linker->FindPrimitiveClass('F');
-    boxed_value.SetF(primitive_field->GetFloat(o));
+    boxed_value.SetF(primitive_field->GetFloat(o.Decode()));
   } else if (klass->DescriptorEquals("Ljava/lang/Double;")) {
     src_class = class_linker->FindPrimitiveClass('D');
-    boxed_value.SetD(primitive_field->GetDouble(o));
+    boxed_value.SetD(primitive_field->GetDouble(o.Decode()));
   } else if (klass->DescriptorEquals("Ljava/lang/Integer;")) {
     src_class = class_linker->FindPrimitiveClass('I');
-    boxed_value.SetI(primitive_field->GetInt(o));
+    boxed_value.SetI(primitive_field->GetInt(o.Decode()));
   } else if (klass->DescriptorEquals("Ljava/lang/Long;")) {
     src_class = class_linker->FindPrimitiveClass('J');
-    boxed_value.SetJ(primitive_field->GetLong(o));
+    boxed_value.SetJ(primitive_field->GetLong(o.Decode()));
   } else if (klass->DescriptorEquals("Ljava/lang/Short;")) {
     src_class = class_linker->FindPrimitiveClass('S');
-    boxed_value.SetS(primitive_field->GetShort(o));
+    boxed_value.SetS(primitive_field->GetShort(o.Decode()));
   } else {
     std::string temp;
     ThrowIllegalArgumentException(
@@ -833,28 +837,36 @@
                                boxed_value, unboxed_value);
 }
 
-bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, ArtField* f,
+bool UnboxPrimitiveForField(ObjPtr<mirror::Object> o,
+                            ObjPtr<mirror::Class> dst_class,
+                            ArtField* f,
                             JValue* unboxed_value) {
   DCHECK(f != nullptr);
   return UnboxPrimitive(o, dst_class, f, unboxed_value);
 }
 
-bool UnboxPrimitiveForResult(mirror::Object* o, mirror::Class* dst_class, JValue* unboxed_value) {
+bool UnboxPrimitiveForResult(ObjPtr<mirror::Object> o,
+                             ObjPtr<mirror::Class> dst_class,
+                             JValue* unboxed_value) {
   return UnboxPrimitive(o, dst_class, nullptr, unboxed_value);
 }
 
-mirror::Class* GetCallingClass(Thread* self, size_t num_frames) {
+ObjPtr<mirror::Class> GetCallingClass(Thread* self, size_t num_frames) {
   NthCallerVisitor visitor(self, num_frames);
   visitor.WalkStack();
   return visitor.caller != nullptr ? visitor.caller->GetDeclaringClass() : nullptr;
 }
 
-bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
-                  uint32_t access_flags, mirror::Class** calling_class, size_t num_frames) {
+bool VerifyAccess(Thread* self,
+                  ObjPtr<mirror::Object> obj,
+                  ObjPtr<mirror::Class> declaring_class,
+                  uint32_t access_flags,
+                  ObjPtr<mirror::Class>* calling_class,
+                  size_t num_frames) {
   if ((access_flags & kAccPublic) != 0) {
     return true;
   }
-  auto* klass = GetCallingClass(self, num_frames);
+  ObjPtr<mirror::Class> klass = GetCallingClass(self, num_frames);
   if (UNLIKELY(klass == nullptr)) {
     // The caller is an attached native thread.
     return false;
@@ -863,10 +875,10 @@
   return VerifyAccess(obj, declaring_class, access_flags, klass);
 }
 
-bool VerifyAccess(mirror::Object* obj,
-                  mirror::Class* declaring_class,
+bool VerifyAccess(ObjPtr<mirror::Object> obj,
+                  ObjPtr<mirror::Class> declaring_class,
                   uint32_t access_flags,
-                  mirror::Class* calling_class) {
+                  ObjPtr<mirror::Class> calling_class) {
   if (calling_class == declaring_class) {
     return true;
   }
@@ -876,16 +888,16 @@
   }
   if ((access_flags & kAccProtected) != 0) {
     if (obj != nullptr && !obj->InstanceOf(calling_class) &&
-        !declaring_class->IsInSamePackage(calling_class)) {
+        !declaring_class->IsInSamePackage(calling_class.Decode())) {
       return false;
-    } else if (declaring_class->IsAssignableFrom(calling_class)) {
+    } else if (declaring_class->IsAssignableFrom(calling_class.Decode())) {
       return true;
     }
   }
-  return declaring_class->IsInSamePackage(calling_class);
+  return declaring_class->IsInSamePackage(calling_class.Decode());
 }
 
-void InvalidReceiverError(mirror::Object* o, mirror::Class* c) {
+void InvalidReceiverError(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c) {
   std::string expected_class_name(PrettyDescriptor(c));
   std::string actual_class_name(PrettyTypeOf(o));
   ThrowIllegalArgumentException(StringPrintf("Expected receiver of type %s, but got %s",
@@ -895,18 +907,18 @@
 
 // This only works if there's one reference which points to the object in obj.
 // Will need to be fixed if there's cases where it's not.
-void UpdateReference(Thread* self, jobject obj, mirror::Object* result) {
+void UpdateReference(Thread* self, jobject obj, ObjPtr<mirror::Object> result) {
   IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
   IndirectRefKind kind = GetIndirectRefKind(ref);
   if (kind == kLocal) {
-    self->GetJniEnv()->locals.Update(obj, result);
+    self->GetJniEnv()->locals.Update(obj, result.Decode());
   } else if (kind == kHandleScopeOrInvalid) {
     LOG(FATAL) << "Unsupported UpdateReference for kind kHandleScopeOrInvalid";
   } else if (kind == kGlobal) {
-    self->GetJniEnv()->vm->UpdateGlobal(self, ref, result);
+    self->GetJniEnv()->vm->UpdateGlobal(self, ref, result.Decode());
   } else {
     DCHECK_EQ(kind, kWeakGlobal);
-    self->GetJniEnv()->vm->UpdateWeakGlobal(self, ref, result);
+    self->GetJniEnv()->vm->UpdateWeakGlobal(self, ref, result.Decode());
   }
 }
 
diff --git a/runtime/reflection.h b/runtime/reflection.h
index 208b533..6e5ef71 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -19,6 +19,7 @@
 
 #include "base/mutex.h"
 #include "jni.h"
+#include "obj_ptr.h"
 #include "primitive.h"
 
 namespace art {
@@ -32,62 +33,85 @@
 class ScopedObjectAccessAlreadyRunnable;
 class ShadowFrame;
 
-mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value)
+ObjPtr<mirror::Object> BoxPrimitive(Primitive::Type src_class, const JValue& value)
     REQUIRES_SHARED(Locks::mutator_lock_);
-bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, ArtField* f,
+
+bool UnboxPrimitiveForField(ObjPtr<mirror::Object> o,
+                            ObjPtr<mirror::Class> dst_class,
+                            ArtField* f,
                             JValue* unboxed_value)
     REQUIRES_SHARED(Locks::mutator_lock_);
-bool UnboxPrimitiveForResult(mirror::Object* o, mirror::Class* dst_class, JValue* unboxed_value)
+
+bool UnboxPrimitiveForResult(ObjPtr<mirror::Object> o,
+                             ObjPtr<mirror::Class> dst_class,
+                             JValue* unboxed_value)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 ALWAYS_INLINE bool ConvertPrimitiveValue(bool unbox_for_result,
-                                         Primitive::Type src_class, Primitive::Type dst_class,
-                                         const JValue& src, JValue* dst)
+                                         Primitive::Type src_class,
+                                         Primitive::Type dst_class,
+                                         const JValue& src,
+                                         JValue* dst)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid,
+JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
+                         jobject obj,
+                         jmethodID mid,
                          va_list args)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid,
+JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa,
+                         jobject obj,
+                         jmethodID mid,
                          jvalue* args)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa,
-                                           jobject obj, jmethodID mid, jvalue* args)
+                                           jobject obj,
+                                           jmethodID mid,
+                                           jvalue* args)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
-                                           jobject obj, jmethodID mid, va_list args)
+                                           jobject obj,
+                                           jmethodID mid,
+                                           va_list args)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 // num_frames is number of frames we look up for access check.
-jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject method, jobject receiver,
-                     jobject args, size_t num_frames = 1)
+jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa,
+                     jobject method,
+                     jobject receiver,
+                     jobject args,
+                     size_t num_frames = 1)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-ALWAYS_INLINE bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c)
+ALWAYS_INLINE bool VerifyObjectIsClass(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
-                  uint32_t access_flags, mirror::Class** calling_class, size_t num_frames)
+bool VerifyAccess(Thread* self,
+                  ObjPtr<mirror::Object> obj,
+                  ObjPtr<mirror::Class> declaring_class,
+                  uint32_t access_flags,
+                  ObjPtr<mirror::Class>* calling_class,
+                  size_t num_frames)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 // This version takes a known calling class.
-bool VerifyAccess(mirror::Object* obj,
-                  mirror::Class* declaring_class,
+bool VerifyAccess(ObjPtr<mirror::Object> obj,
+                  ObjPtr<mirror::Class> declaring_class,
                   uint32_t access_flags,
-                  mirror::Class* calling_class)
+                  ObjPtr<mirror::Class> calling_class)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 // Get the calling class by using a stack visitor, may return null for unattached native threads.
-mirror::Class* GetCallingClass(Thread* self, size_t num_frames)
+ObjPtr<mirror::Class> GetCallingClass(Thread* self, size_t num_frames)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-void InvalidReceiverError(mirror::Object* o, mirror::Class* c)
+void InvalidReceiverError(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
-void UpdateReference(Thread* self, jobject obj, mirror::Object* result)
+void UpdateReference(Thread* self, jobject obj, ObjPtr<mirror::Object> result)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 }  // namespace art
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index 298a974..bb6eb79 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -59,6 +59,8 @@
   if (UNLIKELY(TestAllFlags())) {
     CheckSuspend();
   }
+  // Invalidate the current thread's object pointers (ObjPtr) to catch possible moving GC bugs due
+  // to missing handles.
   PoisonObjectPointers();
 }
 
@@ -173,6 +175,9 @@
 
 inline void Thread::TransitionFromRunnableToSuspended(ThreadState new_state) {
   AssertThreadSuspensionIsAllowable();
+  if (kIsDebugBuild) {
+    PoisonObjectPointers();
+  }
   DCHECK_EQ(this, Thread::Current());
   // Change to non-runnable state, thereby appearing suspended to the system.
   TransitionToSuspendedAndRunCheckpoints(new_state);
@@ -303,6 +308,12 @@
   tlsPtr_.thread_local_alloc_stack_top = nullptr;
 }
 
+inline void Thread::PoisonObjectPointersIfDebug() {
+  if (kIsDebugBuild) {
+    Thread::Current()->PoisonObjectPointers();
+  }
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_THREAD_INL_H_
diff --git a/runtime/thread.h b/runtime/thread.h
index fb6bde6..55f1489 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -475,6 +475,8 @@
     ++poison_object_cookie_;
   }
 
+  ALWAYS_INLINE static void PoisonObjectPointersIfDebug();
+
   ALWAYS_INLINE uintptr_t GetPoisonObjectCookie() const {
     return poison_object_cookie_;
   }
diff --git a/runtime/utils.cc b/runtime/utils.cc
index b52e2f2..0803ca7 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -37,6 +37,7 @@
 #include "mirror/object_array-inl.h"
 #include "mirror/string.h"
 #include "oat_quick_method_header.h"
+#include "obj_ptr-inl.h"
 #include "os.h"
 #include "scoped_thread_state_change.h"
 #include "utf-inl.h"
@@ -270,14 +271,14 @@
   }
 }
 
-std::string PrettyDescriptor(mirror::String* java_descriptor) {
+std::string PrettyStringDescriptor(ObjPtr<mirror::String> java_descriptor) {
   if (java_descriptor == nullptr) {
     return "null";
   }
   return PrettyDescriptor(java_descriptor->ToModifiedUtf8().c_str());
 }
 
-std::string PrettyDescriptor(mirror::Class* klass) {
+std::string PrettyDescriptor(ObjPtr<mirror::Class> klass) {
   if (klass == nullptr) {
     return "null";
   }
@@ -456,7 +457,7 @@
   return result;
 }
 
-std::string PrettyTypeOf(mirror::Object* obj) {
+std::string PrettyTypeOf(ObjPtr<mirror::Object> obj) {
   if (obj == nullptr) {
     return "null";
   }
@@ -471,7 +472,7 @@
   return result;
 }
 
-std::string PrettyClass(mirror::Class* c) {
+std::string PrettyClass(ObjPtr<mirror::Class> c) {
   if (c == nullptr) {
     return "null";
   }
@@ -482,7 +483,7 @@
   return result;
 }
 
-std::string PrettyClassAndClassLoader(mirror::Class* c) {
+std::string PrettyClassAndClassLoader(ObjPtr<mirror::Class> c) {
   if (c == nullptr) {
     return "null";
   }
diff --git a/runtime/utils.h b/runtime/utils.h
index e65b947..ea9e8f7 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -33,6 +33,7 @@
 #include "base/mutex.h"
 #include "base/stringpiece.h"
 #include "globals.h"
+#include "obj_ptr.h"
 #include "primitive.h"
 
 class BacktraceMap;
@@ -135,10 +136,10 @@
 // Returns a human-readable equivalent of 'descriptor'. So "I" would be "int",
 // "[[I" would be "int[][]", "[Ljava/lang/String;" would be
 // "java.lang.String[]", and so forth.
-std::string PrettyDescriptor(mirror::String* descriptor)
+std::string PrettyStringDescriptor(ObjPtr<mirror::String> descriptor)
     REQUIRES_SHARED(Locks::mutator_lock_);
 std::string PrettyDescriptor(const char* descriptor);
-std::string PrettyDescriptor(mirror::Class* klass)
+std::string PrettyDescriptor(ObjPtr<mirror::Class> klass)
     REQUIRES_SHARED(Locks::mutator_lock_);
 std::string PrettyDescriptor(Primitive::Type type);
 
@@ -158,7 +159,7 @@
 // So given an instance of java.lang.String, the output would
 // be "java.lang.String". Given an array of int, the output would be "int[]".
 // Given String.class, the output would be "java.lang.Class<java.lang.String>".
-std::string PrettyTypeOf(mirror::Object* obj)
+std::string PrettyTypeOf(ObjPtr<mirror::Object> obj)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 // Returns a human-readable form of the type at an index in the specified dex file.
@@ -167,11 +168,11 @@
 
 // Returns a human-readable form of the name of the given class.
 // Given String.class, the output would be "java.lang.Class<java.lang.String>".
-std::string PrettyClass(mirror::Class* c)
+std::string PrettyClass(ObjPtr<mirror::Class> c)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 // Returns a human-readable form of the name of the given class with its class loader.
-std::string PrettyClassAndClassLoader(mirror::Class* c)
+std::string PrettyClassAndClassLoader(ObjPtr<mirror::Class> c)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 // Returns a human-readable version of the Java part of the access flags, e.g., "private static "