Fix and optimize verify object.

VerifyObject no longer resides in heap. You can now enable
VerifyObject for non-debug builds. VerifyStack is still slow, so it
is now guarded by its own flag.

Fixed the image writer to not use verification at places where
verification fails due to invalid reads.

Fixed RosAlloc to use SizeOf which doesn't call verify object.

Added a flag paremeter to some of the mirror getters / setters to
be able to selectively disable VerifyObject on certain calls.

Optimized the GC to not verify each object multiple times during
object scanning if verify object is enabled.

Added 3 verification options: verify reads, verify this, and verify
writes so that you can select how much verification you want for
mirror getters and setters.

Removed some useless DCHECKs which would slow debug builds without
providing any benefits.

TODO: RosAlloc verification doesn't currently work with verify
objects.

Bug: 12934910
Bug: 12879358

Change-Id: Ic61033104dfc334543f89b0fc0ad8cd4f4015d69
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index fa50324..48ec5ab 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2308,7 +2308,7 @@
       CHECK(klass == existing);
     }
   }
-  Runtime::Current()->GetHeap()->VerifyObject(klass);
+  VerifyObject(klass);
   class_table_.insert(std::make_pair(hash, klass));
   class_table_dirty_ = true;
   return NULL;
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index d148ae5..4915532 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -30,19 +30,19 @@
 
 template <typename MarkVisitor>
 inline void MarkSweep::ScanObjectVisit(mirror::Object* obj, const MarkVisitor& visitor) {
-  DCHECK(obj != NULL);
   if (kIsDebugBuild && !IsMarked(obj)) {
     heap_->DumpSpaces();
     LOG(FATAL) << "Scanning unmarked object " << obj;
   }
+  // The GetClass verifies the object, don't need to reverify after.
   mirror::Class* klass = obj->GetClass();
-  DCHECK(klass != NULL);
+  // IsArrayClass verifies klass.
   if (UNLIKELY(klass->IsArrayClass())) {
     if (kCountScannedTypes) {
       ++array_count_;
     }
-    if (klass->IsObjectArrayClass()) {
-      VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object>(), visitor);
+    if (klass->IsObjectArrayClass<kVerifyNone>()) {
+      VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object, kVerifyNone>(), visitor);
     }
   } else if (UNLIKELY(klass == mirror::Class::GetJavaLangClass())) {
     if (kCountScannedTypes) {
@@ -54,7 +54,7 @@
       ++other_count_;
     }
     VisitOtherReferences(klass, obj, visitor);
-    if (UNLIKELY(klass->IsReferenceClass())) {
+    if (UNLIKELY(klass->IsReferenceClass<kVerifyNone>())) {
       DelayReferenceReferent(klass, obj);
     }
   }
@@ -65,24 +65,19 @@
                                              bool visit_class)
     SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_,
                           Locks::mutator_lock_) {
-  DCHECK(obj != NULL);
-  DCHECK(obj->GetClass() != NULL);
   mirror::Class* klass = obj->GetClass();
-  DCHECK(klass != NULL);
-  if (klass == mirror::Class::GetJavaLangClass()) {
-    DCHECK_EQ(klass->GetClass(), mirror::Class::GetJavaLangClass());
+  if (klass->IsArrayClass()) {
+    if (visit_class) {
+      visitor(obj, klass, mirror::Object::ClassOffset(), false);
+    }
+    if (klass->IsObjectArrayClass<kVerifyNone>()) {
+      VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object, kVerifyNone>(), visitor);
+    }
+  } else if (klass == mirror::Class::GetJavaLangClass()) {
+    DCHECK_EQ(klass->GetClass<kVerifyNone>(), mirror::Class::GetJavaLangClass());
     VisitClassReferences(klass, obj, visitor);
   } else {
-    if (klass->IsArrayClass()) {
-      if (visit_class) {
-        visitor(obj, klass, mirror::Object::ClassOffset(), false);
-      }
-      if (klass->IsObjectArrayClass()) {
-        VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object>(), visitor);
-      }
-    } else {
-      VisitOtherReferences(klass, obj, visitor);
-    }
+    VisitOtherReferences(klass, obj, visitor);
   }
 }
 
@@ -90,9 +85,7 @@
 inline void MarkSweep::VisitInstanceFieldsReferences(mirror::Class* klass, mirror::Object* obj,
                                                      const Visitor& visitor)
     SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
-  DCHECK(obj != NULL);
-  DCHECK(klass != NULL);
-  VisitFieldsReferences(obj, klass->GetReferenceInstanceOffsets(), false, visitor);
+  VisitFieldsReferences(obj, klass->GetReferenceInstanceOffsets<kVerifyNone>(), false, visitor);
 }
 
 template <typename Visitor>
@@ -100,14 +93,13 @@
                                             const Visitor& visitor)
     SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
   VisitInstanceFieldsReferences(klass, obj, visitor);
-  VisitStaticFieldsReferences(obj->AsClass(), visitor);
+  VisitStaticFieldsReferences(obj->AsClass<kVerifyNone>(), visitor);
 }
 
 template <typename Visitor>
 inline void MarkSweep::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor)
     SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
-  DCHECK(klass != NULL);
-  VisitFieldsReferences(klass, klass->GetReferenceStaticOffsets(), true, visitor);
+  VisitFieldsReferences(klass, klass->GetReferenceStaticOffsets<kVerifyNone>(), true, visitor);
 }
 
 template <typename Visitor>
@@ -118,7 +110,7 @@
     while (ref_offsets != 0) {
       size_t right_shift = CLZ(ref_offsets);
       MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
-      mirror::Object* ref = obj->GetFieldObject<mirror::Object>(field_offset, false);
+      mirror::Object* ref = obj->GetFieldObject<mirror::Object, kVerifyReads>(field_offset, false);
       visitor(obj, ref, field_offset, is_static);
       ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
     }
@@ -127,7 +119,7 @@
     // walk up the class inheritance hierarchy and find reference
     // offsets the hard way. In the static case, just consider this
     // class.
-    for (mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
+    for (mirror::Class* klass = is_static ? obj->AsClass<kVerifyNone>() : obj->GetClass<kVerifyNone>();
          klass != nullptr;
          klass = is_static ? nullptr : klass->GetSuperClass()) {
       size_t num_reference_fields = (is_static
@@ -137,7 +129,7 @@
         mirror::ArtField* field = (is_static ? klass->GetStaticField(i)
                                              : klass->GetInstanceField(i));
         MemberOffset field_offset = field->GetOffset();
-        mirror::Object* ref = obj->GetFieldObject<mirror::Object>(field_offset, false);
+        mirror::Object* ref = obj->GetFieldObject<mirror::Object, kVerifyReads>(field_offset, false);
         visitor(obj, ref, field_offset, is_static);
       }
     }
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 7b9d675..fb797e0 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -533,15 +533,11 @@
 
 void MarkSweep::MarkRootParallelCallback(mirror::Object** root, void* arg, uint32_t /*thread_id*/,
                                          RootType /*root_type*/) {
-  DCHECK(root != NULL);
-  DCHECK(arg != NULL);
   reinterpret_cast<MarkSweep*>(arg)->MarkObjectNonNullParallel(*root);
 }
 
 void MarkSweep::MarkRootCallback(Object** root, void* arg, uint32_t /*thread_id*/,
                                  RootType /*root_type*/) {
-  DCHECK(root != nullptr);
-  DCHECK(arg != nullptr);
   reinterpret_cast<MarkSweep*>(arg)->MarkObjectNonNull(*root);
 }
 
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index 882867b..fe8c253 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -666,11 +666,11 @@
       // case since it does not dirty cards and use additional memory.
       // Since we do not change the actual object, we can safely use non-transactional mode. Also
       // disable check as we could run inside a transaction.
-      obj->SetFieldObjectWithoutWriteBarrier<false, false>(offset, new_address, false);
+      obj->SetFieldObjectWithoutWriteBarrier<false, false, kVerifyNone>(offset, new_address, false);
     }
   }, kMovingClasses);
-  mirror::Class* klass = obj->GetClass();
-  if (UNLIKELY(klass->IsReferenceClass())) {
+  mirror::Class* klass = obj->GetClass<kVerifyNone>();
+  if (UNLIKELY(klass->IsReferenceClass<kVerifyNone>())) {
     DelayReferenceReferent(klass, obj);
   }
 }
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index 9c91b0e..3d591f0 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -28,6 +28,7 @@
 #include "runtime.h"
 #include "thread.h"
 #include "thread-inl.h"
+#include "verify_object-inl.h"
 
 namespace art {
 namespace gc {
@@ -98,12 +99,8 @@
   if (AllocatorMayHaveConcurrentGC(allocator) && concurrent_gc_) {
     CheckConcurrentGC(self, new_num_bytes_allocated, obj);
   }
-  if (kIsDebugBuild) {
-    if (kDesiredHeapVerification > kNoHeapVerification) {
-      VerifyObject(obj);
-    }
-    self->VerifyStack();
-  }
+  VerifyObject(obj);
+  self->VerifyStack();
   return obj;
 }
 
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 8c89cdc..b970df3 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -135,7 +135,7 @@
        * searching.
        */
       max_allocation_stack_size_(kGCALotMode ? kGcAlotInterval
-          : (kDesiredHeapVerification > kVerifyAllFast) ? KB : MB),
+          : (kVerifyObjectSupport > kVerifyObjectModeFast) ? KB : MB),
       current_allocator_(kAllocatorTypeDlMalloc),
       current_non_moving_allocator_(kAllocatorTypeNonMoving),
       bump_pointer_space_(nullptr),
@@ -150,7 +150,7 @@
       target_utilization_(target_utilization),
       total_wait_time_(0),
       total_allocation_time_(0),
-      verify_object_mode_(kHeapVerificationNotPermitted),
+      verify_object_mode_(kVerifyObjectModeDisabled),
       disable_moving_gc_count_(0),
       running_on_valgrind_(RUNNING_ON_VALGRIND),
       use_tlab_(use_tlab) {
@@ -314,9 +314,7 @@
 
 bool Heap::IsCompilingBoot() const {
   for (const auto& space : continuous_spaces_) {
-    if (space->IsImageSpace()) {
-      return false;
-    } else if (space->IsZygoteSpace()) {
+    if (space->IsImageSpace() || space->IsZygoteSpace()) {
       return false;
     }
   }
@@ -823,14 +821,16 @@
     return false;
   }
   if (bump_pointer_space_ != nullptr && bump_pointer_space_->HasAddress(obj)) {
-    mirror::Class* klass = obj->GetClass();
+    mirror::Class* klass = obj->GetClass<kVerifyNone>();
     if (obj == klass) {
       // This case happens for java.lang.Class.
       return true;
     }
     return VerifyClassClass(klass) && IsLiveObjectLocked(klass);
   } else if (temp_space_ != nullptr && temp_space_->HasAddress(obj)) {
-    return false;
+    // If we are in the allocated region of the temp space, then we are probably live (e.g. during
+    // a GC). When a GC isn't running End() - Begin() is 0 which means no objects are contained.
+    return temp_space_->Contains(obj);
   }
   space::ContinuousSpace* c_space = FindContinuousSpaceFromObject(obj, true);
   space::DiscontinuousSpace* d_space = NULL;
@@ -886,25 +886,6 @@
   return false;
 }
 
-void Heap::VerifyObjectImpl(mirror::Object* obj) {
-  if (Thread::Current() == NULL ||
-      Runtime::Current()->GetThreadList()->GetLockOwner() == Thread::Current()->GetTid()) {
-    return;
-  }
-  VerifyObjectBody(obj);
-}
-
-bool Heap::VerifyClassClass(const mirror::Class* c) const {
-  // Note: we don't use the accessors here as they have internal sanity checks that we don't want
-  // to run
-  const byte* raw_addr =
-      reinterpret_cast<const byte*>(c) + mirror::Object::ClassOffset().Int32Value();
-  mirror::Class* c_c = reinterpret_cast<mirror::HeapReference<mirror::Class> const *>(raw_addr)->AsMirrorPtr();
-  raw_addr = reinterpret_cast<const byte*>(c_c) + mirror::Object::ClassOffset().Int32Value();
-  mirror::Class* c_c_c = reinterpret_cast<mirror::HeapReference<mirror::Class> const *>(raw_addr)->AsMirrorPtr();
-  return c_c == c_c_c;
-}
-
 void Heap::DumpSpaces(std::ostream& stream) {
   for (const auto& space : continuous_spaces_) {
     accounting::SpaceBitmap* live_bitmap = space->GetLiveBitmap();
@@ -923,36 +904,30 @@
 }
 
 void Heap::VerifyObjectBody(mirror::Object* obj) {
-  CHECK(IsAligned<kObjectAlignment>(obj)) << "Object isn't aligned: " << obj;
+  if (this == nullptr && verify_object_mode_ == kVerifyObjectModeDisabled) {
+    return;
+  }
   // Ignore early dawn of the universe verifications.
   if (UNLIKELY(static_cast<size_t>(num_bytes_allocated_.Load()) < 10 * KB)) {
     return;
   }
-  const byte* raw_addr = reinterpret_cast<const byte*>(obj) +
-      mirror::Object::ClassOffset().Int32Value();
-  mirror::Class* c = reinterpret_cast<mirror::HeapReference<mirror::Class> const *>(raw_addr)->AsMirrorPtr();
-  if (UNLIKELY(c == NULL)) {
-    LOG(FATAL) << "Null class in object: " << obj;
-  } else if (UNLIKELY(!IsAligned<kObjectAlignment>(c))) {
-    LOG(FATAL) << "Class isn't aligned: " << c << " in object: " << obj;
-  }
+  CHECK(IsAligned<kObjectAlignment>(obj)) << "Object isn't aligned: " << obj;
+  mirror::Class* c = obj->GetFieldObject<mirror::Class, kVerifyNone>(
+      mirror::Object::ClassOffset(), false);
+  CHECK(c != nullptr) << "Null class in object " << obj;
+  CHECK(IsAligned<kObjectAlignment>(c)) << "Class " << c << " not aligned in object " << obj;
   CHECK(VerifyClassClass(c));
 
-  if (verify_object_mode_ > kVerifyAllFast) {
-    // TODO: the bitmap tests below are racy if VerifyObjectBody is called without the
-    //       heap_bitmap_lock_.
+  if (verify_object_mode_ > kVerifyObjectModeFast) {
+    // Note: the bitmap tests below are racy since we don't hold the heap bitmap lock.
     if (!IsLiveObjectLocked(obj)) {
       DumpSpaces();
       LOG(FATAL) << "Object is dead: " << obj;
     }
-    if (!IsLiveObjectLocked(c)) {
-      LOG(FATAL) << "Class of object is dead: " << c << " in object: " << obj;
-    }
   }
 }
 
 void Heap::VerificationCallback(mirror::Object* obj, void* arg) {
-  DCHECK(obj != NULL);
   reinterpret_cast<Heap*>(arg)->VerifyObjectBody(obj);
 }
 
@@ -1790,7 +1765,7 @@
 
       if (bitmap == nullptr) {
         LOG(ERROR) << "Object " << obj << " has no bitmap";
-        if (!heap_->VerifyClassClass(obj->GetClass())) {
+        if (!VerifyClassClass(obj->GetClass())) {
           LOG(ERROR) << "Object " << obj << " failed class verification!";
         }
       } else {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 21a2365..83202a5 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -37,6 +37,7 @@
 #include "reference_queue.h"
 #include "safe_map.h"
 #include "thread_pool.h"
+#include "verify_object.h"
 
 namespace art {
 
@@ -99,15 +100,6 @@
   kAllocatorTypeLOS,  // Large object space, also doesn't have entrypoints.
 };
 
-// How we want to sanity check the heap's correctness.
-enum HeapVerificationMode {
-  kHeapVerificationNotPermitted,  // Too early in runtime start-up for heap to be verified.
-  kNoHeapVerification,  // Production default.
-  kVerifyAllFast,  // Sanity check all heap accesses with quick(er) tests.
-  kVerifyAll  // Sanity check all heap accesses.
-};
-static constexpr HeapVerificationMode kDesiredHeapVerification = kNoHeapVerification;
-
 // If true, use rosalloc/RosAllocSpace instead of dlmalloc/DlMallocSpace
 static constexpr bool kUseRosAlloc = true;
 
@@ -208,14 +200,9 @@
   void ChangeCollector(CollectorType collector_type);
 
   // The given reference is believed to be to an object in the Java heap, check the soundness of it.
-  void VerifyObjectImpl(mirror::Object* o);
-  void VerifyObject(mirror::Object* o) {
-    if (o != nullptr && this != nullptr && verify_object_mode_ > kNoHeapVerification) {
-      VerifyObjectImpl(o);
-    }
-  }
-  // Check that c.getClass() == c.getClass().getClass().
-  bool VerifyClassClass(const mirror::Class* c) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  // TODO: NO_THREAD_SAFETY_ANALYSIS since we call this everywhere and it is impossible to find a
+  // proper lock ordering for it.
+  void VerifyObjectBody(mirror::Object* o) NO_THREAD_SAFETY_ANALYSIS;
 
   // Check sanity of all live references.
   void VerifyHeap() LOCKS_EXCLUDED(Locks::heap_bitmap_lock_);
@@ -347,21 +334,20 @@
 
   // Enable verification of object references when the runtime is sufficiently initialized.
   void EnableObjectValidation() {
-    verify_object_mode_ = kDesiredHeapVerification;
-    if (verify_object_mode_ > kNoHeapVerification) {
+    verify_object_mode_ = kVerifyObjectSupport;
+    if (verify_object_mode_ > kVerifyObjectModeDisabled) {
       VerifyHeap();
     }
   }
 
   // Disable object reference verification for image writing.
   void DisableObjectValidation() {
-    verify_object_mode_ = kHeapVerificationNotPermitted;
+    verify_object_mode_ = kVerifyObjectModeDisabled;
   }
 
   // Other checks may be performed if we know the heap should be in a sane state.
   bool IsObjectValidationEnabled() const {
-    return kDesiredHeapVerification > kNoHeapVerification &&
-        verify_object_mode_ > kHeapVerificationNotPermitted;
+    return verify_object_mode_ > kVerifyObjectModeDisabled;
   }
 
   // Returns true if low memory mode is enabled.
@@ -665,10 +651,6 @@
       LOCKS_EXCLUDED(Locks::heap_bitmap_lock_);
   void RemoveSpace(space::Space* space) LOCKS_EXCLUDED(Locks::heap_bitmap_lock_);
 
-  // No thread saftey analysis since we call this everywhere and it is impossible to find a proper
-  // lock ordering for it.
-  void VerifyObjectBody(mirror::Object *obj) NO_THREAD_SAFETY_ANALYSIS;
-
   static void VerificationCallback(mirror::Object* obj, void* arg)
       SHARED_LOCKS_REQUIRED(GlobalSychronization::heap_bitmap_lock_);
 
@@ -916,7 +898,7 @@
   AtomicInteger total_allocation_time_;
 
   // The current state of heap verification, may be enabled or disabled.
-  HeapVerificationMode verify_object_mode_;
+  VerifyObjectMode verify_object_mode_;
 
   // Compacting GC disable count, prevents compacting GC from running iff > 0.
   size_t disable_moving_gc_count_ GUARDED_BY(gc_complete_lock_);
diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc
index f90e6c7..ee31112 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -111,7 +111,8 @@
 }
 
 void MallocSpace::RegisterRecentFree(mirror::Object* ptr) {
-  recent_freed_objects_[recent_free_pos_] = std::make_pair(ptr, ptr->GetClass());
+  // No verification since the object is dead.
+  recent_freed_objects_[recent_free_pos_] = std::make_pair(ptr, ptr->GetClass<kVerifyNone>());
   recent_free_pos_ = (recent_free_pos_ + 1) & kRecentFreeMask;
 }
 
diff --git a/runtime/gc/space/rosalloc_space.h b/runtime/gc/space/rosalloc_space.h
index 2377423..72e84f6 100644
--- a/runtime/gc/space/rosalloc_space.h
+++ b/runtime/gc/space/rosalloc_space.h
@@ -60,7 +60,8 @@
     // TODO: NO_THREAD_SAFETY_ANALYSIS because SizeOf() requires that mutator_lock is held.
     void* obj_ptr = const_cast<void*>(reinterpret_cast<const void*>(obj));
     // obj is a valid object. Use its class in the header to get the size.
-    size_t size = obj->SizeOf();
+    // Don't use verification since the object may be dead if we are sweeping.
+    size_t size = obj->SizeOf<kVerifyNone>();
     size_t size_by_size = rosalloc_->UsableSize(size);
     if (kIsDebugBuild) {
       size_t size_by_ptr = rosalloc_->UsableSize(obj_ptr);
diff --git a/runtime/gc/space/space_test.cc b/runtime/gc/space/space_test.cc
index 6d07a60..0b9f7ad 100644
--- a/runtime/gc/space/space_test.cc
+++ b/runtime/gc/space/space_test.cc
@@ -38,18 +38,20 @@
     Runtime::Current()->GetHeap()->RevokeAllThreadLocalBuffers();
     Runtime::Current()->GetHeap()->AddSpace(space);
   }
-  void InstallClass(mirror::Object* o, size_t size) NO_THREAD_SAFETY_ANALYSIS {
+  void InstallClass(SirtRef<mirror::Object>& o, size_t size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // Note the minimum size, which is the size of a zero-length byte array.
     EXPECT_GE(size, SizeOfZeroLengthByteArray());
-    SirtRef<mirror::ClassLoader> null_loader(Thread::Current(), NULL);
-    mirror::Class* byte_array_class = Runtime::Current()->GetClassLinker()->FindClass("[B", null_loader);
-    EXPECT_TRUE(byte_array_class != NULL);
+    SirtRef<mirror::ClassLoader> null_loader(Thread::Current(), nullptr);
+    mirror::Class* byte_array_class = Runtime::Current()->GetClassLinker()->FindClass("[B",
+                                                                                      null_loader);
+    EXPECT_TRUE(byte_array_class != nullptr);
     o->SetClass(byte_array_class);
-    mirror::Array* arr = o->AsArray();
+    mirror::Array* arr = o->AsArray<kVerifyNone>();
     size_t header_size = SizeOfZeroLengthByteArray();
     int32_t length = size - header_size;
     arr->SetLength(length);
-    EXPECT_EQ(arr->SizeOf(), size);
+    EXPECT_EQ(arr->SizeOf<kVerifyNone>(), size);
   }
 
   static size_t SizeOfZeroLengthByteArray() {
@@ -86,38 +88,38 @@
 void SpaceTest::InitTestBody(CreateSpaceFn create_space) {
   {
     // Init < max == growth
-    UniquePtr<Space> space(create_space("test", 16 * MB, 32 * MB, 32 * MB, NULL));
-    EXPECT_TRUE(space.get() != NULL);
+    UniquePtr<Space> space(create_space("test", 16 * MB, 32 * MB, 32 * MB, nullptr));
+    EXPECT_TRUE(space.get() != nullptr);
   }
   {
     // Init == max == growth
-    UniquePtr<Space> space(create_space("test", 16 * MB, 16 * MB, 16 * MB, NULL));
-    EXPECT_TRUE(space.get() != NULL);
+    UniquePtr<Space> space(create_space("test", 16 * MB, 16 * MB, 16 * MB, nullptr));
+    EXPECT_TRUE(space.get() != nullptr);
   }
   {
     // Init > max == growth
-    UniquePtr<Space> space(create_space("test", 32 * MB, 16 * MB, 16 * MB, NULL));
-    EXPECT_TRUE(space.get() == NULL);
+    UniquePtr<Space> space(create_space("test", 32 * MB, 16 * MB, 16 * MB, nullptr));
+    EXPECT_TRUE(space.get() == nullptr);
   }
   {
     // Growth == init < max
-    UniquePtr<Space> space(create_space("test", 16 * MB, 16 * MB, 32 * MB, NULL));
-    EXPECT_TRUE(space.get() != NULL);
+    UniquePtr<Space> space(create_space("test", 16 * MB, 16 * MB, 32 * MB, nullptr));
+    EXPECT_TRUE(space.get() != nullptr);
   }
   {
     // Growth < init < max
-    UniquePtr<Space> space(create_space("test", 16 * MB, 8 * MB, 32 * MB, NULL));
-    EXPECT_TRUE(space.get() == NULL);
+    UniquePtr<Space> space(create_space("test", 16 * MB, 8 * MB, 32 * MB, nullptr));
+    EXPECT_TRUE(space.get() == nullptr);
   }
   {
     // Init < growth < max
-    UniquePtr<Space> space(create_space("test", 8 * MB, 16 * MB, 32 * MB, NULL));
-    EXPECT_TRUE(space.get() != NULL);
+    UniquePtr<Space> space(create_space("test", 8 * MB, 16 * MB, 32 * MB, nullptr));
+    EXPECT_TRUE(space.get() != nullptr);
   }
   {
     // Init < max < growth
-    UniquePtr<Space> space(create_space("test", 8 * MB, 32 * MB, 16 * MB, NULL));
-    EXPECT_TRUE(space.get() == NULL);
+    UniquePtr<Space> space(create_space("test", 8 * MB, 32 * MB, 16 * MB, nullptr));
+    EXPECT_TRUE(space.get() == nullptr);
   }
 }
 
@@ -134,52 +136,52 @@
 // the GC works with the ZygoteSpace.
 void SpaceTest::ZygoteSpaceTestBody(CreateSpaceFn create_space) {
   size_t dummy = 0;
-  MallocSpace* space(create_space("test", 4 * MB, 16 * MB, 16 * MB, NULL));
-  ASSERT_TRUE(space != NULL);
+  MallocSpace* space(create_space("test", 4 * MB, 16 * MB, 16 * MB, nullptr));
+  ASSERT_TRUE(space != nullptr);
 
   // Make space findable to the heap, will also delete space when runtime is cleaned up
   AddSpace(space);
   Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
 
   // Succeeds, fits without adjusting the footprint limit.
-  mirror::Object* ptr1 = space->Alloc(self, 1 * MB, &dummy);
-  EXPECT_TRUE(ptr1 != NULL);
+  SirtRef<mirror::Object> ptr1(self, space->Alloc(self, 1 * MB, &dummy));
+  EXPECT_TRUE(ptr1.get() != nullptr);
   InstallClass(ptr1, 1 * MB);
 
   // Fails, requires a higher footprint limit.
   mirror::Object* ptr2 = space->Alloc(self, 8 * MB, &dummy);
-  EXPECT_TRUE(ptr2 == NULL);
+  EXPECT_TRUE(ptr2 == nullptr);
 
   // Succeeds, adjusts the footprint.
   size_t ptr3_bytes_allocated;
-  mirror::Object* ptr3 = space->AllocWithGrowth(self, 8 * MB, &ptr3_bytes_allocated);
-  EXPECT_TRUE(ptr3 != NULL);
+  SirtRef<mirror::Object> ptr3(self, space->AllocWithGrowth(self, 8 * MB, &ptr3_bytes_allocated));
+  EXPECT_TRUE(ptr3.get() != nullptr);
   EXPECT_LE(8U * MB, ptr3_bytes_allocated);
   InstallClass(ptr3, 8 * MB);
 
   // Fails, requires a higher footprint limit.
   mirror::Object* ptr4 = space->Alloc(self, 8 * MB, &dummy);
-  EXPECT_TRUE(ptr4 == NULL);
+  EXPECT_TRUE(ptr4 == nullptr);
 
   // Also fails, requires a higher allowed footprint.
   mirror::Object* ptr5 = space->AllocWithGrowth(self, 8 * MB, &dummy);
-  EXPECT_TRUE(ptr5 == NULL);
+  EXPECT_TRUE(ptr5 == nullptr);
 
   // Release some memory.
-  ScopedObjectAccess soa(self);
-  size_t free3 = space->AllocationSize(ptr3);
+  size_t free3 = space->AllocationSize(ptr3.get());
   EXPECT_EQ(free3, ptr3_bytes_allocated);
-  EXPECT_EQ(free3, space->Free(self, ptr3));
+  EXPECT_EQ(free3, space->Free(self, ptr3.reset(nullptr)));
   EXPECT_LE(8U * MB, free3);
 
   // Succeeds, now that memory has been freed.
-  mirror::Object* ptr6 = space->AllocWithGrowth(self, 9 * MB, &dummy);
-  EXPECT_TRUE(ptr6 != NULL);
+  SirtRef<mirror::Object> ptr6(self, space->AllocWithGrowth(self, 9 * MB, &dummy));
+  EXPECT_TRUE(ptr6.get() != nullptr);
   InstallClass(ptr6, 9 * MB);
 
   // Final clean up.
-  size_t free1 = space->AllocationSize(ptr1);
-  space->Free(self, ptr1);
+  size_t free1 = space->AllocationSize(ptr1.get());
+  space->Free(self, ptr1.reset(nullptr));
   EXPECT_LE(1U * MB, free1);
 
   // Make sure that the zygote space isn't directly at the start of the space.
@@ -199,23 +201,23 @@
   AddSpace(space);
 
   // Succeeds, fits without adjusting the footprint limit.
-  ptr1 = space->Alloc(self, 1 * MB, &dummy);
-  EXPECT_TRUE(ptr1 != NULL);
+  ptr1.reset(space->Alloc(self, 1 * MB, &dummy));
+  EXPECT_TRUE(ptr1.get() != nullptr);
   InstallClass(ptr1, 1 * MB);
 
   // Fails, requires a higher footprint limit.
   ptr2 = space->Alloc(self, 8 * MB, &dummy);
-  EXPECT_TRUE(ptr2 == NULL);
+  EXPECT_TRUE(ptr2 == nullptr);
 
   // Succeeds, adjusts the footprint.
-  ptr3 = space->AllocWithGrowth(self, 2 * MB, &dummy);
-  EXPECT_TRUE(ptr3 != NULL);
+  ptr3.reset(space->AllocWithGrowth(self, 2 * MB, &dummy));
+  EXPECT_TRUE(ptr3.get() != nullptr);
   InstallClass(ptr3, 2 * MB);
-  space->Free(self, ptr3);
+  space->Free(self, ptr3.reset(nullptr));
 
   // Final clean up.
-  free1 = space->AllocationSize(ptr1);
-  space->Free(self, ptr1);
+  free1 = space->AllocationSize(ptr1.get());
+  space->Free(self, ptr1.reset(nullptr));
   EXPECT_LE(1U * MB, free1);
 }
 
@@ -229,52 +231,52 @@
 
 void SpaceTest::AllocAndFreeTestBody(CreateSpaceFn create_space) {
   size_t dummy = 0;
-  MallocSpace* space(create_space("test", 4 * MB, 16 * MB, 16 * MB, NULL));
-  ASSERT_TRUE(space != NULL);
+  MallocSpace* space(create_space("test", 4 * MB, 16 * MB, 16 * MB, nullptr));
+  ASSERT_TRUE(space != nullptr);
   Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
 
   // Make space findable to the heap, will also delete space when runtime is cleaned up
   AddSpace(space);
 
   // Succeeds, fits without adjusting the footprint limit.
-  mirror::Object* ptr1 = space->Alloc(self, 1 * MB, &dummy);
-  EXPECT_TRUE(ptr1 != NULL);
+  SirtRef<mirror::Object> ptr1(self, space->Alloc(self, 1 * MB, &dummy));
+  EXPECT_TRUE(ptr1.get() != nullptr);
   InstallClass(ptr1, 1 * MB);
 
   // Fails, requires a higher footprint limit.
   mirror::Object* ptr2 = space->Alloc(self, 8 * MB, &dummy);
-  EXPECT_TRUE(ptr2 == NULL);
+  EXPECT_TRUE(ptr2 == nullptr);
 
   // Succeeds, adjusts the footprint.
   size_t ptr3_bytes_allocated;
-  mirror::Object* ptr3 = space->AllocWithGrowth(self, 8 * MB, &ptr3_bytes_allocated);
-  EXPECT_TRUE(ptr3 != NULL);
+  SirtRef<mirror::Object> ptr3(self, space->AllocWithGrowth(self, 8 * MB, &ptr3_bytes_allocated));
+  EXPECT_TRUE(ptr3.get() != nullptr);
   EXPECT_LE(8U * MB, ptr3_bytes_allocated);
   InstallClass(ptr3, 8 * MB);
 
   // Fails, requires a higher footprint limit.
   mirror::Object* ptr4 = space->Alloc(self, 8 * MB, &dummy);
-  EXPECT_TRUE(ptr4 == NULL);
+  EXPECT_TRUE(ptr4 == nullptr);
 
   // Also fails, requires a higher allowed footprint.
   mirror::Object* ptr5 = space->AllocWithGrowth(self, 8 * MB, &dummy);
-  EXPECT_TRUE(ptr5 == NULL);
+  EXPECT_TRUE(ptr5 == nullptr);
 
   // Release some memory.
-  ScopedObjectAccess soa(self);
-  size_t free3 = space->AllocationSize(ptr3);
+  size_t free3 = space->AllocationSize(ptr3.get());
   EXPECT_EQ(free3, ptr3_bytes_allocated);
-  space->Free(self, ptr3);
+  space->Free(self, ptr3.reset(nullptr));
   EXPECT_LE(8U * MB, free3);
 
   // Succeeds, now that memory has been freed.
-  mirror::Object* ptr6 = space->AllocWithGrowth(self, 9 * MB, &dummy);
-  EXPECT_TRUE(ptr6 != NULL);
+  SirtRef<mirror::Object> ptr6(self, space->AllocWithGrowth(self, 9 * MB, &dummy));
+  EXPECT_TRUE(ptr6.get() != nullptr);
   InstallClass(ptr6, 9 * MB);
 
   // Final clean up.
-  size_t free1 = space->AllocationSize(ptr1);
-  space->Free(self, ptr1);
+  size_t free1 = space->AllocationSize(ptr1.get());
+  space->Free(self, ptr1.reset(nullptr));
   EXPECT_LE(1U * MB, free1);
 }
 
@@ -288,11 +290,11 @@
 TEST_F(SpaceTest, LargeObjectTest) {
   size_t rand_seed = 0;
   for (size_t i = 0; i < 2; ++i) {
-    LargeObjectSpace* los = NULL;
+    LargeObjectSpace* los = nullptr;
     if (i == 0) {
       los = space::LargeObjectMapSpace::Create("large object space");
     } else {
-      los = space::FreeListSpace::Create("large object space", NULL, 128 * MB);
+      los = space::FreeListSpace::Create("large object space", nullptr, 128 * MB);
     }
 
     static const size_t num_allocations = 64;
@@ -304,7 +306,7 @@
         size_t request_size = test_rand(&rand_seed) % max_allocation_size;
         size_t allocation_size = 0;
         mirror::Object* obj = los->Alloc(Thread::Current(), request_size, &allocation_size);
-        ASSERT_TRUE(obj != NULL);
+        ASSERT_TRUE(obj != nullptr);
         ASSERT_EQ(allocation_size, los->AllocationSize(obj));
         ASSERT_GE(allocation_size, request_size);
         // Fill in our magic value.
@@ -337,7 +339,7 @@
     size_t bytes_allocated = 0;
     // Checks that the coalescing works.
     mirror::Object* obj = los->Alloc(Thread::Current(), 100 * MB, &bytes_allocated);
-    EXPECT_TRUE(obj != NULL);
+    EXPECT_TRUE(obj != nullptr);
     los->Free(Thread::Current(), obj);
 
     EXPECT_EQ(0U, los->GetBytesAllocated());
@@ -347,12 +349,13 @@
 }
 
 void SpaceTest::AllocAndFreeListTestBody(CreateSpaceFn create_space) {
-  MallocSpace* space(create_space("test", 4 * MB, 16 * MB, 16 * MB, NULL));
-  ASSERT_TRUE(space != NULL);
+  MallocSpace* space(create_space("test", 4 * MB, 16 * MB, 16 * MB, nullptr));
+  ASSERT_TRUE(space != nullptr);
 
   // Make space findable to the heap, will also delete space when runtime is cleaned up
   AddSpace(space);
   Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
 
   // Succeeds, fits without adjusting the max allowed footprint.
   mirror::Object* lots_of_objects[1024];
@@ -361,17 +364,16 @@
     size_t size_of_zero_length_byte_array = SizeOfZeroLengthByteArray();
     lots_of_objects[i] = space->Alloc(self, size_of_zero_length_byte_array, &allocation_size);
     EXPECT_TRUE(lots_of_objects[i] != nullptr);
-    InstallClass(lots_of_objects[i], size_of_zero_length_byte_array);
+    SirtRef<mirror::Object> obj(self, lots_of_objects[i]);
+    InstallClass(obj, size_of_zero_length_byte_array);
+    lots_of_objects[i] = obj.get();
     EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i]));
   }
 
-  // Release memory and check pointers are NULL.
-  {
-    ScopedObjectAccess soa(self);
-    space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
-    for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
-      EXPECT_TRUE(lots_of_objects[i] == nullptr);
-    }
+  // Release memory and check pointers are nullptr.
+  space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
+  for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
+    EXPECT_TRUE(lots_of_objects[i] == nullptr);
   }
 
   // Succeeds, fits by adjusting the max allowed footprint.
@@ -379,17 +381,17 @@
     size_t allocation_size = 0;
     lots_of_objects[i] = space->AllocWithGrowth(self, 1024, &allocation_size);
     EXPECT_TRUE(lots_of_objects[i] != nullptr);
-    InstallClass(lots_of_objects[i], 1024);
+    SirtRef<mirror::Object> obj(self, lots_of_objects[i]);
+    InstallClass(obj, 1024);
+    lots_of_objects[i] = obj.get();
     EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i]));
   }
 
-  // Release memory and check pointers are NULL
-  {
-    ScopedObjectAccess soa(self);
-    space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
-    for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
-      EXPECT_TRUE(lots_of_objects[i] == nullptr);
-    }
+  // Release memory and check pointers are nullptr
+  // TODO: This isn't compaction safe, fix.
+  space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
+  for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
+    EXPECT_TRUE(lots_of_objects[i] == nullptr);
   }
 }
 
@@ -430,6 +432,7 @@
   size_t last_object = 0;  // last object for which allocation succeeded
   size_t amount_allocated = 0;  // amount of space allocated
   Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
   size_t rand_seed = 123456789;
   for (size_t i = 0; i < max_objects; i++) {
     size_t alloc_fails = 0;  // number of failed allocations
@@ -446,19 +449,19 @@
           alloc_size = size_of_zero_length_byte_array;
         }
       }
-      mirror::Object* object;
+      SirtRef<mirror::Object> object(self, nullptr);
       size_t bytes_allocated = 0;
       if (round <= 1) {
-        object = space->Alloc(self, alloc_size, &bytes_allocated);
+        object.reset(space->Alloc(self, alloc_size, &bytes_allocated));
       } else {
-        object = space->AllocWithGrowth(self, alloc_size, &bytes_allocated);
+        object.reset(space->AllocWithGrowth(self, alloc_size, &bytes_allocated));
       }
       footprint = space->GetFootprint();
       EXPECT_GE(space->Size(), footprint);  // invariant
-      if (object != NULL) {  // allocation succeeded
+      if (object.get() != nullptr) {  // allocation succeeded
         InstallClass(object, alloc_size);
-        lots_of_objects.get()[i] = object;
-        size_t allocation_size = space->AllocationSize(object);
+        lots_of_objects[i] = object.get();
+        size_t allocation_size = space->AllocationSize(object.get());
         EXPECT_EQ(bytes_allocated, allocation_size);
         if (object_size > 0) {
           EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
@@ -489,8 +492,11 @@
   // Release storage in a semi-adhoc manner
   size_t free_increment = 96;
   while (true) {
-    // Give the space a haircut
-    space->Trim();
+    {
+      ScopedThreadStateChange tsc(self, kNative);
+      // Give the space a haircut.
+      space->Trim();
+    }
 
     // Bounds sanity
     footprint = space->GetFootprint();
@@ -504,30 +510,28 @@
       break;
     }
 
-    {
-      // Free some objects
-      ScopedObjectAccess soa(self);
-      for (size_t i = 0; i < last_object; i += free_increment) {
-        mirror::Object* object = lots_of_objects.get()[i];
-        if (object == NULL) {
-          continue;
-        }
-        size_t allocation_size = space->AllocationSize(object);
-        if (object_size > 0) {
-          EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
-        } else {
-          EXPECT_GE(allocation_size, 8u);
-        }
-        space->Free(self, object);
-        lots_of_objects.get()[i] = NULL;
-        amount_allocated -= allocation_size;
-        footprint = space->GetFootprint();
-        EXPECT_GE(space->Size(), footprint);  // invariant
+    // Free some objects
+    for (size_t i = 0; i < last_object; i += free_increment) {
+      mirror::Object* object = lots_of_objects.get()[i];
+      if (object == nullptr) {
+        continue;
       }
-
-      free_increment >>= 1;
+      size_t allocation_size = space->AllocationSize(object);
+      if (object_size > 0) {
+        EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
+      } else {
+        EXPECT_GE(allocation_size, 8u);
+      }
+      space->Free(self, object);
+      lots_of_objects.get()[i] = nullptr;
+      amount_allocated -= allocation_size;
+      footprint = space->GetFootprint();
+      EXPECT_GE(space->Size(), footprint);  // invariant
     }
+
+    free_increment >>= 1;
   }
+
   // The space has become empty here before allocating a large object
   // below. For RosAlloc, revoke thread-local runs, which are kept
   // even when empty for a performance reason, so that they won't
@@ -537,15 +541,15 @@
   space->RevokeAllThreadLocalBuffers();
 
   // All memory was released, try a large allocation to check freed memory is being coalesced
-  mirror::Object* large_object;
+  SirtRef<mirror::Object> large_object(self, nullptr);
   size_t three_quarters_space = (growth_limit / 2) + (growth_limit / 4);
   size_t bytes_allocated = 0;
   if (round <= 1) {
-    large_object = space->Alloc(self, three_quarters_space, &bytes_allocated);
+    large_object.reset(space->Alloc(self, three_quarters_space, &bytes_allocated));
   } else {
-    large_object = space->AllocWithGrowth(self, three_quarters_space, &bytes_allocated);
+    large_object.reset(space->AllocWithGrowth(self, three_quarters_space, &bytes_allocated));
   }
-  EXPECT_TRUE(large_object != NULL);
+  EXPECT_TRUE(large_object.get() != nullptr);
   InstallClass(large_object, three_quarters_space);
 
   // Sanity check footprint
@@ -555,10 +559,8 @@
   EXPECT_LE(space->Size(), growth_limit);
 
   // Clean up
-  {
-    ScopedObjectAccess soa(self);
-    space->Free(self, large_object);
-  }
+  space->Free(self, large_object.reset(nullptr));
+
   // Sanity check footprint
   footprint = space->GetFootprint();
   EXPECT_LE(footprint, growth_limit);
@@ -574,8 +576,8 @@
   size_t initial_size = 4 * MB;
   size_t growth_limit = 8 * MB;
   size_t capacity = 16 * MB;
-  MallocSpace* space(create_space("test", initial_size, growth_limit, capacity, NULL));
-  ASSERT_TRUE(space != NULL);
+  MallocSpace* space(create_space("test", initial_size, growth_limit, capacity, nullptr));
+  ASSERT_TRUE(space != nullptr);
 
   // Basic sanity
   EXPECT_EQ(space->Capacity(), growth_limit);
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index e37fb61..9e1d915 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -31,7 +31,7 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // If both register locations contains the same value, the register probably holds a reference.
   int32_t src_value = shadow_frame.GetVReg(src_reg);
-  mirror::Object* o = shadow_frame.GetVRegReference<false>(src_reg);
+  mirror::Object* o = shadow_frame.GetVRegReference<kVerifyNone>(src_reg);
   if (src_value == reinterpret_cast<intptr_t>(o)) {
     new_shadow_frame->SetVRegReference(dest_reg, o);
   } else {
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 7c5de5e..90aaccd 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -27,10 +27,13 @@
 namespace art {
 namespace mirror {
 
+template<VerifyObjectFlags kVerifyFlags>
 inline size_t Array::SizeOf() {
   // This is safe from overflow because the array was already allocated, so we know it's sane.
-  size_t component_size = GetClass()->GetComponentSize();
-  int32_t component_count = GetLength();
+  size_t component_size = GetClass<kVerifyFlags>()->GetComponentSize();
+  // Don't need to check this since we already check this in GetClass.
+  int32_t component_count =
+      GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>();
   size_t header_size = sizeof(Object) + (component_size == sizeof(int64_t) ? 8 : 4);
   size_t data_size = component_count * component_size;
   return header_size + data_size;
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 7555975..c4f9a75 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -53,17 +53,18 @@
                                  const SirtRef<IntArray>& dimensions)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   int32_t GetLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), false);
+    return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Array, length_), false);
   }
 
   void SetLength(int32_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     CHECK_GE(length, 0);
     // We use non transactional version since we can't undo this write. We also disable checking
     // since it would fail during a transaction.
-    SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false, false);
+    SetField32<false, false, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false);
   }
 
   static MemberOffset LengthOffset() {
@@ -94,8 +95,10 @@
 
   // Returns true if the index is valid. If not, throws an ArrayIndexOutOfBoundsException and
   // returns false.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool CheckIsValidIndex(int32_t index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    if (UNLIKELY(static_cast<uint32_t>(index) >= static_cast<uint32_t>(GetLength()))) {
+    if (UNLIKELY(static_cast<uint32_t>(index) >=
+                 static_cast<uint32_t>(GetLength<kVerifyFlags>()))) {
       ThrowArrayIndexOutOfBoundsException(index);
       return false;
     }
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index d347724..d5eccaf 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -215,6 +215,13 @@
   DCHECK(!result || IsRuntimeMethod());
   return result;
 }
+
+template<VerifyObjectFlags kVerifyFlags>
+inline void ArtMethod::SetNativeMethod(const void* native_method) {
+  SetFieldPtr<false, true, kVerifyFlags>(
+      OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_), native_method, false);
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 20d2b18..fe27992 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -360,10 +360,5 @@
   RegisterNative(self, GetJniDlsymLookupStub(), false);
 }
 
-void ArtMethod::SetNativeMethod(const void* native_method) {
-  SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_),
-                     native_method, false);
-}
-
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 86f5348..e17dc5f 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -214,40 +214,48 @@
   void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
               const char* shorty) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   EntryPointFromInterpreter* GetEntryPointFromInterpreter() {
-    return GetFieldPtr<EntryPointFromInterpreter*>(
+    return GetFieldPtr<EntryPointFromInterpreter*, kVerifyFlags>(
                OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_), false);
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetEntryPointFromInterpreter(EntryPointFromInterpreter* entry_point_from_interpreter) {
-    SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_),
-                       entry_point_from_interpreter, false);
+    SetFieldPtr<false, true, kVerifyFlags>(
+        OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_),
+        entry_point_from_interpreter, false);
   }
 
   static MemberOffset EntryPointFromPortableCompiledCodeOffset() {
     return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_portable_compiled_code_));
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   const void* GetEntryPointFromPortableCompiledCode() {
-    return GetFieldPtr<const void*>(EntryPointFromPortableCompiledCodeOffset(), false);
+    return GetFieldPtr<const void*, kVerifyFlags>(
+        EntryPointFromPortableCompiledCodeOffset(), false);
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetEntryPointFromPortableCompiledCode(const void* entry_point_from_portable_compiled_code) {
-    SetFieldPtr<false>(EntryPointFromPortableCompiledCodeOffset(),
-                       entry_point_from_portable_compiled_code, false);
+    SetFieldPtr<false, true, kVerifyFlags>(
+        EntryPointFromPortableCompiledCodeOffset(), entry_point_from_portable_compiled_code, false);
   }
 
   static MemberOffset EntryPointFromQuickCompiledCodeOffset() {
     return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_quick_compiled_code_));
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   const void* GetEntryPointFromQuickCompiledCode() {
-    return GetFieldPtr<const void*>(EntryPointFromQuickCompiledCodeOffset(), false);
+    return GetFieldPtr<const void*, kVerifyFlags>(EntryPointFromQuickCompiledCodeOffset(), false);
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code) {
-    SetFieldPtr<false>(EntryPointFromQuickCompiledCodeOffset(),
-                       entry_point_from_quick_compiled_code, false);
+    SetFieldPtr<false, true, kVerifyFlags>(
+        EntryPointFromQuickCompiledCodeOffset(), entry_point_from_quick_compiled_code, false);
   }
 
 
@@ -279,9 +287,10 @@
         false);
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetMappingTable(const uint8_t* mapping_table) {
-    SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_),
-                       mapping_table, false);
+    SetFieldPtr<false, true, kVerifyFlags>(
+        OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_), mapping_table, false);
   }
 
   uint32_t GetOatMappingTableOffset();
@@ -294,8 +303,10 @@
         false);
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetVmapTable(const uint8_t* vmap_table) {
-    SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_), vmap_table, false);
+    SetFieldPtr<false, true, kVerifyFlags>(
+        OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_), vmap_table, false);
   }
 
   uint32_t GetOatVmapTableOffset();
@@ -305,8 +316,10 @@
   const uint8_t* GetNativeGcMap() {
     return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), false);
   }
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetNativeGcMap(const uint8_t* data) {
-    SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), data, false);
+    SetFieldPtr<false, true, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), data,
+                                           false);
   }
 
   // When building the oat need a convenient place to stuff the offset of the native GC map.
@@ -350,6 +363,7 @@
     return reinterpret_cast<const void*>(GetField32(NativeMethodOffset(), false));
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetNativeMethod(const void*);
 
   static MemberOffset GetMethodIndexOffset() {
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index cba221d..e82c393 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -85,6 +85,7 @@
   return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0;
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline ObjectArray<ArtMethod>* Class::GetVirtualMethods() {
   DCHECK(IsLoaded() || IsErroneous());
   return GetFieldObject<ObjectArray<ArtMethod> >(
@@ -103,8 +104,9 @@
   return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0;
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline ArtMethod* Class::GetVirtualMethod(uint32_t i) {
-  DCHECK(IsResolved() || IsErroneous());
+  DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
   return GetVirtualMethods()->Get(i);
 }
 
@@ -415,14 +417,16 @@
   }
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline uint32_t Class::GetAccessFlags() {
   // Check class is loaded or this is java.lang.String that has a
   // circularity issue during loading the names of its members
-  DCHECK(IsLoaded() || IsErroneous() ||
+  DCHECK(IsLoaded<kVerifyFlags>() ||
+         IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ||
          this == String::GetJavaLangString() ||
          this == ArtField::GetJavaLangReflectArtField() ||
          this == ArtMethod::GetJavaLangReflectArtMethod());
-  return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
+  return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
 }
 
 inline String* Class::GetName() {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index cd8504b..43db996 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -120,9 +120,11 @@
     kStatusMax = 10,
   };
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   Status GetStatus() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK_EQ(sizeof(Status), sizeof(uint32_t));
-    return static_cast<Status>(GetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), true));
+    COMPILE_ASSERT(sizeof(Status) == sizeof(uint32_t), size_of_status_not_uint32);
+    return static_cast<Status>(GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, status_),
+                                                       true));
   }
 
   void SetStatus(Status new_status, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -132,45 +134,54 @@
   }
 
   // Returns true if the class has failed to link.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsErroneous() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetStatus() == kStatusError;
+    return GetStatus<kVerifyFlags>() == kStatusError;
   }
 
   // Returns true if the class has been loaded.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsIdxLoaded() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetStatus() >= kStatusIdx;
+    return GetStatus<kVerifyFlags>() >= kStatusIdx;
   }
 
   // Returns true if the class has been loaded.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsLoaded() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetStatus() >= kStatusLoaded;
+    return GetStatus<kVerifyFlags>() >= kStatusLoaded;
   }
 
   // Returns true if the class has been linked.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsResolved() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetStatus() >= kStatusResolved;
+    return GetStatus<kVerifyFlags>() >= kStatusResolved;
   }
 
   // Returns true if the class was compile-time verified.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsCompileTimeVerified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetStatus() >= kStatusRetryVerificationAtRuntime;
+    return GetStatus<kVerifyFlags>() >= kStatusRetryVerificationAtRuntime;
   }
 
   // Returns true if the class has been verified.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsVerified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetStatus() >= kStatusVerified;
+    return GetStatus<kVerifyFlags>() >= kStatusVerified;
   }
 
   // Returns true if the class is initializing.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsInitializing() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetStatus() >= kStatusInitializing;
+    return GetStatus<kVerifyFlags>() >= kStatusInitializing;
   }
 
   // Returns true if the class is initialized.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsInitialized() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetStatus() == kStatusInitialized;
+    return GetStatus<kVerifyFlags>() == kStatusInitialized;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -217,24 +228,29 @@
     return (GetAccessFlags() & kAccSynthetic) != 0;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return (GetAccessFlags() & kAccClassIsReference) != 0;
+    return (GetAccessFlags<kVerifyFlags>() & kAccClassIsReference) != 0;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsWeakReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return (GetAccessFlags() & kAccClassIsWeakReference) != 0;
+    return (GetAccessFlags<kVerifyFlags>() & kAccClassIsWeakReference) != 0;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsSoftReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return (GetAccessFlags() & kAccReferenceFlagsMask) == kAccClassIsReference;
+    return (GetAccessFlags<kVerifyFlags>() & kAccReferenceFlagsMask) == kAccClassIsReference;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsFinalizerReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return (GetAccessFlags() & kAccClassIsFinalizerReference) != 0;
+    return (GetAccessFlags<kVerifyFlags>() & kAccClassIsFinalizerReference) != 0;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPhantomReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return (GetAccessFlags() & kAccClassIsPhantomReference) != 0;
+    return (GetAccessFlags<kVerifyFlags>() & kAccClassIsPhantomReference) != 0;
   }
 
   // Can references of this type be assigned to by things of another type? For non-array types
@@ -260,7 +276,7 @@
   // Computes the name, then sets the cached value.
   String* ComputeName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool IsProxyClass() {
+  bool IsProxyClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // Read access flags without using getter as whether something is a proxy can be check in
     // any loaded state
     // TODO: switch to a check if the super class is java.lang.reflect.Proxy?
@@ -268,10 +284,11 @@
     return (access_flags & kAccClassIsProxy) != 0;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   Primitive::Type GetPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
     return static_cast<Primitive::Type>(
-        GetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false));
+        GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false));
   }
 
   void SetPrimitiveType(Primitive::Type new_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -280,48 +297,61 @@
   }
 
   // Returns true if the class is a primitive type.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitive() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetPrimitiveType() != Primitive::kPrimNot;
+    return GetPrimitiveType<kVerifyFlags>() != Primitive::kPrimNot;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitiveBoolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetPrimitiveType() == Primitive::kPrimBoolean;
+    return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimBoolean;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitiveByte() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetPrimitiveType() == Primitive::kPrimByte;
+    return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimByte;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitiveChar() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetPrimitiveType() == Primitive::kPrimChar;
+    return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimChar;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitiveShort() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetPrimitiveType() == Primitive::kPrimShort;
+    return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimShort;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitiveInt() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return GetPrimitiveType() == Primitive::kPrimInt;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitiveLong() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetPrimitiveType() == Primitive::kPrimLong;
+    return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimLong;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitiveFloat() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetPrimitiveType() == Primitive::kPrimFloat;
+    return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimFloat;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitiveDouble() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetPrimitiveType() == Primitive::kPrimDouble;
+    return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimDouble;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitiveVoid() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetPrimitiveType() == Primitive::kPrimVoid;
+    return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimVoid;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPrimitiveArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return IsArrayClass() && GetComponentType()->IsPrimitive();
+    return IsArrayClass<kVerifyFlags>() &&
+        GetComponentType<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>()->
+        IsPrimitive();
   }
 
   // Depth of class from java.lang.Object
@@ -333,8 +363,9 @@
     return depth;
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetComponentType() != NULL;
+    return GetComponentType<kVerifyFlags>() != NULL;
   }
 
   bool IsClassClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -351,8 +382,9 @@
     return OFFSET_OF_OBJECT_MEMBER(Class, component_type_);
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   Class* GetComponentType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetFieldObject<Class>(ComponentTypeOffset(), false);
+    return GetFieldObject<Class, kVerifyFlags>(ComponentTypeOffset(), false);
   }
 
   void SetComponentType(Class* new_component_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -376,8 +408,9 @@
     return (!IsPrimitive() && !IsInterface() && !IsAbstract()) || ((IsAbstract()) && IsArrayClass());
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsObjectArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetComponentType() != NULL && !GetComponentType()->IsPrimitive();
+    return GetComponentType<kVerifyFlags>() != nullptr && !GetComponentType<kVerifyFlags>()->IsPrimitive();
   }
 
   // Creates a raw object instance but does not invoke the default constructor.
@@ -396,12 +429,14 @@
     return IsClassClass() || IsArrayClass();
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   uint32_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
+    return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   uint32_t GetClassSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
+    return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
   }
 
   void SetClassSize(uint32_t new_class_size)
@@ -549,6 +584,7 @@
   // Returns the number of static, private, and constructor methods.
   uint32_t NumDirectMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ObjectArray<ArtMethod>* GetVirtualMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void SetVirtualMethods(ObjectArray<ArtMethod>* new_virtual_methods)
@@ -557,6 +593,7 @@
   // Returns the number of non-inherited virtual methods.
   uint32_t NumVirtualMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ArtMethod* GetVirtualMethod(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   ArtMethod* GetVirtualMethodDuringLinking(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -683,9 +720,11 @@
                       false);
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   uint32_t GetReferenceInstanceOffsets() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(IsResolved() || IsErroneous());
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false);
+    DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
+    return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_),
+                                   false);
   }
 
   void SetReferenceInstanceOffsets(uint32_t new_reference_offsets)
@@ -725,8 +764,10 @@
   // TODO: uint16_t
   void SetStaticField(uint32_t i, ArtField* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   uint32_t GetReferenceStaticOffsets() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_), false);
+    return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_),
+                                   false);
   }
 
   void SetReferenceStaticOffsets(uint32_t new_reference_offsets)
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 70291c1..df8104d 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -32,18 +32,21 @@
 namespace art {
 namespace mirror {
 
+template<VerifyObjectFlags kVerifyFlags>
 inline Class* Object::GetClass() {
-  return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
+  return GetFieldObject<Class, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline void Object::SetClass(Class* new_klass) {
   // new_klass may be NULL prior to class linker initialization.
   // We don't mark the card as this occurs as part of object allocation. Not all objects have
   // backing cards, such as large objects.
   // We use non transactional version since we can't undo this write. We also disable checking as
   // we may run in transaction mode here.
-  SetFieldObjectWithoutWriteBarrier<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, klass_),
-                                                  new_klass, false, false);
+  SetFieldObjectWithoutWriteBarrier<false, false,
+      static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(
+      OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false);
 }
 
 inline LockWord Object::GetLockWord() {
@@ -89,176 +92,222 @@
   Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::VerifierInstanceOf(Class* klass) {
   DCHECK(klass != NULL);
-  DCHECK(GetClass() != NULL);
+  DCHECK(GetClass<kVerifyFlags>() != NULL);
   return klass->IsInterface() || InstanceOf(klass);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::InstanceOf(Class* klass) {
   DCHECK(klass != NULL);
-  DCHECK(GetClass() != NULL);
-  return klass->IsAssignableFrom(GetClass());
+  DCHECK(GetClass<kVerifyNone>() != NULL);
+  return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsClass() {
-  Class* java_lang_Class = GetClass()->GetClass();
-  return GetClass() == java_lang_Class;
+  Class* java_lang_Class = GetClass<kVerifyFlags>()->GetClass();
+  return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ==
+      java_lang_Class;
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline Class* Object::AsClass() {
-  DCHECK(IsClass());
+  DCHECK(IsClass<kVerifyFlags>());
   return down_cast<Class*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsObjectArray() {
-  return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive();
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  return IsArrayInstance<kVerifyFlags>() &&
+      !GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitive();
 }
 
-template<class T>
+template<class T, VerifyObjectFlags kVerifyFlags>
 inline ObjectArray<T>* Object::AsObjectArray() {
-  DCHECK(IsObjectArray());
+  DCHECK(IsObjectArray<kVerifyFlags>());
   return down_cast<ObjectArray<T>*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsArrayInstance() {
-  return GetClass()->IsArrayClass();
+  return GetClass<kVerifyFlags>()->IsArrayClass();
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsArtField() {
-  return GetClass()->IsArtFieldClass();
+  return GetClass<kVerifyFlags>()->IsArtFieldClass();
 }
 
-inline ArtField* Object::AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  DCHECK(IsArtField());
+template<VerifyObjectFlags kVerifyFlags>
+inline ArtField* Object::AsArtField() {
+  DCHECK(IsArtField<kVerifyFlags>());
   return down_cast<ArtField*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsArtMethod() {
-  return GetClass()->IsArtMethodClass();
+  return GetClass<kVerifyFlags>()->IsArtMethodClass();
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline ArtMethod* Object::AsArtMethod() {
-  DCHECK(IsArtMethod());
+  DCHECK(IsArtMethod<kVerifyFlags>());
   return down_cast<ArtMethod*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsReferenceInstance() {
-  return GetClass()->IsReferenceClass();
+  return GetClass<kVerifyFlags>()->IsReferenceClass();
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline Array* Object::AsArray() {
-  DCHECK(IsArrayInstance());
+  DCHECK(IsArrayInstance<kVerifyFlags>());
   return down_cast<Array*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline BooleanArray* Object::AsBooleanArray() {
-  DCHECK(GetClass()->IsArrayClass());
-  DCHECK(GetClass()->GetComponentType()->IsPrimitiveBoolean());
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean());
   return down_cast<BooleanArray*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline ByteArray* Object::AsByteArray() {
-  DCHECK(GetClass()->IsArrayClass());
-  DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte());
+  static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
   return down_cast<ByteArray*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline ByteArray* Object::AsByteSizedArray() {
-  DCHECK(GetClass()->IsArrayClass());
-  DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte() ||
-         GetClass()->GetComponentType()->IsPrimitiveBoolean());
+  constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
+         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
   return down_cast<ByteArray*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline CharArray* Object::AsCharArray() {
-  DCHECK(GetClass()->IsArrayClass());
-  DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar());
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
   return down_cast<CharArray*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline ShortArray* Object::AsShortArray() {
-  DCHECK(GetClass()->IsArrayClass());
-  DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort());
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort());
   return down_cast<ShortArray*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline ShortArray* Object::AsShortSizedArray() {
-  DCHECK(GetClass()->IsArrayClass());
-  DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort() ||
-         GetClass()->GetComponentType()->IsPrimitiveChar());
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() ||
+         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
   return down_cast<ShortArray*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline IntArray* Object::AsIntArray() {
-  DCHECK(GetClass()->IsArrayClass());
-  DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt() ||
-         GetClass()->GetComponentType()->IsPrimitiveFloat());
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() ||
+         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
   return down_cast<IntArray*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline LongArray* Object::AsLongArray() {
-  DCHECK(GetClass()->IsArrayClass());
-  DCHECK(GetClass()->GetComponentType()->IsPrimitiveLong() ||
-         GetClass()->GetComponentType()->IsPrimitiveDouble());
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() ||
+         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
   return down_cast<LongArray*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline FloatArray* Object::AsFloatArray() {
-  DCHECK(GetClass()->IsArrayClass());
-  DCHECK(GetClass()->GetComponentType()->IsPrimitiveFloat());
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
   return down_cast<FloatArray*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline DoubleArray* Object::AsDoubleArray() {
-  DCHECK(GetClass()->IsArrayClass());
-  DCHECK(GetClass()->GetComponentType()->IsPrimitiveDouble());
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
   return down_cast<DoubleArray*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline String* Object::AsString() {
-  DCHECK(GetClass()->IsStringClass());
+  DCHECK(GetClass<kVerifyFlags>()->IsStringClass());
   return down_cast<String*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline Throwable* Object::AsThrowable() {
-  DCHECK(GetClass()->IsThrowableClass());
+  DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
   return down_cast<Throwable*>(this);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsWeakReferenceInstance() {
-  return GetClass()->IsWeakReferenceClass();
+  return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsSoftReferenceInstance() {
-  return GetClass()->IsSoftReferenceClass();
+  return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsFinalizerReferenceInstance() {
-  return GetClass()->IsFinalizerReferenceClass();
+  return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsPhantomReferenceInstance() {
-  return GetClass()->IsPhantomReferenceClass();
+  return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline size_t Object::SizeOf() {
   size_t result;
-  if (IsArrayInstance()) {
-    result = AsArray()->SizeOf();
-  } else if (IsClass()) {
-    result = AsClass()->SizeOf();
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  if (IsArrayInstance<kVerifyFlags>()) {
+    result = AsArray<kNewFlags>()->SizeOf<>();
+  } else if (IsClass<kNewFlags>()) {
+    result = AsClass<kNewFlags>()->SizeOf<kNewFlags>();
   } else {
-    result = GetClass()->GetObjectSize();
+    result = GetClass<kNewFlags>()->GetObjectSize();
   }
-  DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(GetClass());
-  DCHECK(!IsArtField()  || result == sizeof(ArtField));
-  DCHECK(!IsArtMethod() || result == sizeof(ArtMethod));
+  DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(GetClass<kNewFlags>());
+  DCHECK(!IsArtField<kNewFlags>()  || result == sizeof(ArtField));
+  DCHECK(!IsArtMethod<kNewFlags>() || result == sizeof(ArtMethod));
   return result;
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline int32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) {
-  VerifyObject(this);
+  if (kVerifyFlags & kVerifyThis) {
+    VerifyObject(this);
+  }
   const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
   const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
   if (UNLIKELY(is_volatile)) {
@@ -270,9 +319,8 @@
   }
 }
 
-template<bool kTransactionActive, bool kCheckTransaction>
-inline void Object::SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile,
-                               bool this_is_valid) {
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile) {
   if (kCheckTransaction) {
     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
   }
@@ -280,7 +328,7 @@
     Runtime::Current()->RecordWriteField32(this, field_offset, GetField32(field_offset, is_volatile),
                                            is_volatile);
   }
-  if (this_is_valid) {
+  if (kVerifyFlags & kVerifyThis) {
     VerifyObject(this);
   }
   byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
@@ -294,7 +342,7 @@
   }
 }
 
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
 inline bool Object::CasField32(MemberOffset field_offset, int32_t old_value, int32_t new_value) {
   if (kCheckTransaction) {
     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
@@ -302,14 +350,19 @@
   if (kTransactionActive) {
     Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
   }
-  VerifyObject(this);
+  if (kVerifyFlags & kVerifyThis) {
+    VerifyObject(this);
+  }
   byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
   volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr);
   return __sync_bool_compare_and_swap(addr, old_value, new_value);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline int64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) {
-  VerifyObject(this);
+  if (kVerifyFlags & kVerifyThis) {
+    VerifyObject(this);
+  }
   const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
   const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
   if (UNLIKELY(is_volatile)) {
@@ -321,9 +374,8 @@
   }
 }
 
-template<bool kTransactionActive, bool kCheckTransaction>
-inline void Object::SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile,
-                               bool this_is_valid) {
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile) {
   if (kCheckTransaction) {
     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
   }
@@ -331,7 +383,7 @@
     Runtime::Current()->RecordWriteField64(this, field_offset, GetField64(field_offset, is_volatile),
                                            is_volatile);
   }
-  if (this_is_valid) {
+  if (kVerifyFlags & kVerifyThis) {
     VerifyObject(this);
   }
   byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
@@ -349,7 +401,7 @@
   }
 }
 
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
 inline bool Object::CasField64(MemberOffset field_offset, int64_t old_value, int64_t new_value) {
   if (kCheckTransaction) {
     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
@@ -357,15 +409,19 @@
   if (kTransactionActive) {
     Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
   }
-  VerifyObject(this);
+  if (kVerifyFlags & kVerifyThis) {
+    VerifyObject(this);
+  }
   byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
   volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(raw_addr);
   return QuasiAtomic::Cas64(old_value, new_value, addr);
 }
 
-template<class T>
+template<class T, VerifyObjectFlags kVerifyFlags>
 inline T* Object::GetFieldObject(MemberOffset field_offset, bool is_volatile) {
-  VerifyObject(this);
+  if (kVerifyFlags & kVerifyThis) {
+    VerifyObject(this);
+  }
   byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
   HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
   HeapReference<T> objref = *objref_addr;
@@ -374,13 +430,15 @@
     QuasiAtomic::MembarLoadLoad();  // Ensure loads don't re-order.
   }
   T* result = objref.AsMirrorPtr();
-  VerifyObject(result);
+  if (kVerifyFlags & kVerifyReads) {
+    VerifyObject(result);
+  }
   return result;
 }
 
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
 inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
-                                                      bool is_volatile, bool this_is_valid) {
+                                                      bool is_volatile) {
   if (kCheckTransaction) {
     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
   }
@@ -389,10 +447,12 @@
                                                   GetFieldObject<Object>(field_offset, is_volatile),
                                                   true);
   }
-  if (this_is_valid) {
+  if (kVerifyFlags & kVerifyThis) {
     VerifyObject(this);
   }
-  VerifyObject(new_value);
+  if (kVerifyFlags & kVerifyWrites) {
+    VerifyObject(new_value);
+  }
   HeapReference<Object> objref(HeapReference<Object>::FromMirrorPtr(new_value));
   byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
   HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
@@ -405,27 +465,43 @@
   }
 }
 
-template<bool kTransactionActive, bool kCheckTransaction>
-inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile,
-                                   bool this_is_valid) {
-  SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction>(field_offset, new_value,
-                                                                           is_volatile,
-                                                                           this_is_valid);
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile) {
+  SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>(
+      field_offset, new_value, is_volatile);
   if (new_value != nullptr) {
     CheckFieldAssignment(field_offset, new_value);
     Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
   }
 }
 
-template<bool kTransactionActive, bool kCheckTransaction>
-inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value, Object* new_value) {
+template <VerifyObjectFlags kVerifyFlags>
+inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
+  if (kVerifyFlags & kVerifyThis) {
+    VerifyObject(this);
+  }
+  return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) +
+      field_offset.Int32Value());
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value,
+                                   Object* new_value) {
   if (kCheckTransaction) {
     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
   }
+  if (kVerifyFlags & kVerifyThis) {
+    VerifyObject(this);
+  }
+  if (kVerifyFlags & kVerifyWrites) {
+    VerifyObject(new_value);
+  }
+  if (kVerifyFlags & kVerifyReads) {
+    VerifyObject(old_value);
+  }
   if (kTransactionActive) {
     Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
   }
-  VerifyObject(this);
   byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
   volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr);
   HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
@@ -437,12 +513,6 @@
   return success;
 }
 
-inline void Object::VerifyObject(Object* obj) {
-  if (kIsDebugBuild) {
-    Runtime::Current()->GetHeap()->VerifyObject(obj);
-  }
-}
-
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 1251852..f1485e5 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -141,10 +141,9 @@
 
 void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_value) {
   Class* c = GetClass();
-  if (Runtime::Current()->GetClassLinker() == NULL ||
-      !Runtime::Current()->IsStarted() ||
-      !Runtime::Current()->GetHeap()->IsObjectValidationEnabled() ||
-      !c->IsResolved()) {
+  Runtime* runtime = Runtime::Current();
+  if (runtime->GetClassLinker() == nullptr || !runtime->IsStarted() ||
+      !runtime->GetHeap()->IsObjectValidationEnabled() || !c->IsResolved()) {
     return;
   }
   for (Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index eb118c7..7487dd2 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -24,6 +24,7 @@
 #include "object_reference.h"
 #include "offsets.h"
 #include "runtime.h"
+#include "verify_object.h"
 
 namespace art {
 
@@ -59,7 +60,8 @@
 #define OFFSET_OF_OBJECT_MEMBER(type, field) \
     MemberOffset(OFFSETOF_MEMBER(type, field))
 
-constexpr bool kCheckFieldAssignments = false;
+// Checks that we don't do field assignments which violate the typing system.
+static constexpr bool kCheckFieldAssignments = false;
 
 // C++ mirror of java.lang.Object
 class MANAGED Object {
@@ -68,16 +70,20 @@
     return OFFSET_OF_OBJECT_MEMBER(Object, klass_);
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   Class* GetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetClass(Class* new_klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // The verifier treats all interfaces as java.lang.Object and relies on runtime checks in
   // invoke-interface to detect incompatible interface types.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool VerifierInstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool InstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -95,135 +101,147 @@
 
   mirror::Object* MonitorEnter(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       EXCLUSIVE_LOCK_FUNCTION(monitor_lock_);
-
   bool MonitorExit(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       UNLOCK_FUNCTION(monitor_lock_);
-
   void Notify(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   void NotifyAll(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   void Wait(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   void Wait(Thread* self, int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   Class* AsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsObjectArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  template<class T>
+  template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ObjectArray<T>* AsObjectArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsArrayInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   Array* AsArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   BooleanArray* AsBooleanArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ByteArray* AsByteArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ByteArray* AsByteSizedArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   CharArray* AsCharArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ShortArray* AsShortArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ShortArray* AsShortSizedArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   IntArray* AsIntArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   LongArray* AsLongArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   FloatArray* AsFloatArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   DoubleArray* AsDoubleArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   String* AsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   Throwable* AsThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ArtMethod* AsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ArtField* AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsWeakReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsSoftReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsFinalizerReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPhantomReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Accessor for Java type fields.
-  template<class T> T* GetFieldObject(MemberOffset field_offset, bool is_volatile)
+  template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  T* GetFieldObject(MemberOffset field_offset, bool is_volatile)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive, bool kCheckTransaction = true>
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
-                                         bool is_volatile, bool this_is_valid = true)
+                                         bool is_volatile)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive, bool kCheckTransaction = true>
-  void SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile,
-                      bool this_is_valid = true)
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  void SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive, bool kCheckTransaction = true>
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool CasFieldObject(MemberOffset field_offset, Object* old_value, Object* new_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  HeapReference<Object>* GetFieldObjectReferenceAddr(MemberOffset field_offset) ALWAYS_INLINE {
-    VerifyObject(this);
-    return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) +
-        field_offset.Int32Value());
-  }
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  HeapReference<Object>* GetFieldObjectReferenceAddr(MemberOffset field_offset);
 
-  int32_t GetField32(MemberOffset field_offset, bool is_volatile);
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  int32_t GetField32(MemberOffset field_offset, bool is_volatile)
+      NO_THREAD_SAFETY_ANALYSIS;
 
-  template<bool kTransactionActive, bool kCheckTransaction = true>
-  void SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile,
-                  bool this_is_valid = true);
-
-  template<bool kTransactionActive, bool kCheckTransaction = true>
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  void SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile);
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool CasField32(MemberOffset field_offset, int32_t old_value, int32_t new_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   int64_t GetField64(MemberOffset field_offset, bool is_volatile);
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  void SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile);
 
-  template<bool kTransactionActive, bool kCheckTransaction = true>
-  void SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile,
-                  bool this_is_valid = true);
-
-  template<bool kTransactionActive, bool kCheckTransaction = true>
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool CasField64(MemberOffset field_offset, int64_t old_value, int64_t new_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<bool kTransactionActive, bool kCheckTransaction = true, typename T>
-  void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile,
-                   bool this_is_valid = true) {
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, typename T>
+  void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile) {
 #ifndef __LP64__
-    SetField32<kTransactionActive, kCheckTransaction>(field_offset,
-                                                      reinterpret_cast<int32_t>(new_value),
-                                                      is_volatile, this_is_valid);
+    SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags>(
+        field_offset, reinterpret_cast<int32_t>(new_value), is_volatile);
 #else
-    SetField64<kTransactionActive, kCheckTransaction>(field_offset,
-                                                      reinterpret_cast<int64_t>(new_value),
-                                                      is_volatile, this_is_valid);
+    SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags>(
+        field_offset, reinterpret_cast<int64_t>(new_value), is_volatile);
 #endif
   }
 
  protected:
   // Accessors for non-Java type fields
-  template<class T>
-  T GetFieldPtr(MemberOffset field_offset, bool is_volatile) {
+  template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  T GetFieldPtr(MemberOffset field_offset, bool is_volatile) NO_THREAD_SAFETY_ANALYSIS {
 #ifndef __LP64__
-    return reinterpret_cast<T>(GetField32(field_offset, is_volatile));
+    return reinterpret_cast<T>(GetField32<kVerifyFlags>(field_offset, is_volatile));
 #else
-    return reinterpret_cast<T>(GetField64(field_offset, is_volatile));
+    return reinterpret_cast<T>(GetField64<kVerifyFlags>(field_offset, is_volatile));
 #endif
   }
 
  private:
-  static void VerifyObject(Object* obj) ALWAYS_INLINE;
   // Verify the type correctness of stores to fields.
   void CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 521b6ce..a427957 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -58,10 +58,10 @@
   return GetFieldObject<T>(OffsetOfElement(i), false);
 }
 
-template<class T>
+template<class T> template<VerifyObjectFlags kVerifyFlags>
 inline bool ObjectArray<T>::CheckAssignable(T* object) {
   if (object != NULL) {
-    Class* element_class = GetClass()->GetComponentType();
+    Class* element_class = GetClass<kVerifyFlags>()->GetComponentType();
     if (UNLIKELY(!object->InstanceOf(element_class))) {
       ThrowArrayStoreException(object);
       return false;
@@ -80,31 +80,33 @@
 }
 
 template<class T>
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
 inline void ObjectArray<T>::Set(int32_t i, T* object) {
-  if (LIKELY(CheckIsValidIndex(i) && CheckAssignable(object))) {
-    SetFieldObject<kTransactionActive, kCheckTransaction>(OffsetOfElement(i), object, false);
+  if (LIKELY(CheckIsValidIndex(i) && CheckAssignable<kVerifyFlags>(object))) {
+    SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object,
+                                                                        false);
   } else {
     DCHECK(Thread::Current()->IsExceptionPending());
   }
 }
 
 template<class T>
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
 inline void ObjectArray<T>::SetWithoutChecks(int32_t i, T* object) {
-  DCHECK(CheckIsValidIndex(i));
-  DCHECK(CheckAssignable(object));
-  SetFieldObject<kTransactionActive, kCheckTransaction>(OffsetOfElement(i), object, false);
+  DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
+  DCHECK(CheckAssignable<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(object));
+  SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object,
+                                                                      false);
 }
 
 template<class T>
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
 inline void ObjectArray<T>::SetWithoutChecksAndWriteBarrier(int32_t i, T* object) {
-  DCHECK(CheckIsValidIndex(i));
+  DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
   // TODO:  enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
   // DCHECK(CheckAssignable(object));
-  SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction>(OffsetOfElement(i),
-                                                                           object, false);
+  SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>(
+      OffsetOfElement(i), object, false);
 }
 
 template<class T>
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index 668b276..7f9e716 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -37,22 +37,27 @@
 
   // Returns true if the object can be stored into the array. If not, throws
   // an ArrayStoreException and returns false.
-  bool CheckAssignable(T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  // TODO fix thread safety analysis: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  bool CheckAssignable(T* object) NO_THREAD_SAFETY_ANALYSIS;
 
   void Set(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   // TODO fix thread safety analysis: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
-  template<bool kTransactionActive, bool kCheckTransaction = true>
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void Set(int32_t i, 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.
   // TODO fix thread safety analysis broken by the use of template. This should be
   // SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
-  template<bool kTransactionActive, bool kCheckTransaction = true>
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetWithoutChecks(int32_t i, T* object) NO_THREAD_SAFETY_ANALYSIS;
   // TODO fix thread safety analysis broken by the use of template. This should be
   // SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
-  template<bool kTransactionActive, bool kCheckTransaction = true>
+  template<bool kTransactionActive, bool kCheckTransaction = true,
+      VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetWithoutChecksAndWriteBarrier(int32_t i, T* object) NO_THREAD_SAFETY_ANALYSIS;
 
   T* GetWithoutChecks(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/native/java_lang_String.cc b/runtime/native/java_lang_String.cc
index c401d50..f95664b 100644
--- a/runtime/native/java_lang_String.cc
+++ b/runtime/native/java_lang_String.cc
@@ -20,6 +20,7 @@
 #include "scoped_fast_native_object_access.h"
 #include "scoped_thread_state_change.h"
 #include "ScopedLocalRef.h"
+#include "verify_object-inl.h"
 
 namespace art {
 
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index 011e165..2665a08 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -24,6 +24,7 @@
 #include "ScopedUtfChars.h"
 #include "thread.h"
 #include "thread_list.h"
+#include "verify_object-inl.h"
 
 namespace art {
 
diff --git a/runtime/native/java_lang_reflect_Proxy.cc b/runtime/native/java_lang_reflect_Proxy.cc
index 809369a..1266c41 100644
--- a/runtime/native/java_lang_reflect_Proxy.cc
+++ b/runtime/native/java_lang_reflect_Proxy.cc
@@ -20,6 +20,7 @@
 #include "mirror/object_array.h"
 #include "mirror/string.h"
 #include "scoped_thread_state_change.h"
+#include "verify_object-inl.h"
 
 namespace art {
 
diff --git a/runtime/native/scoped_fast_native_object_access.h b/runtime/native/scoped_fast_native_object_access.h
index 1658d96..b5ee748 100644
--- a/runtime/native/scoped_fast_native_object_access.h
+++ b/runtime/native/scoped_fast_native_object_access.h
@@ -21,6 +21,7 @@
 #include "jni_internal.h"
 #include "thread-inl.h"
 #include "mirror/art_method.h"
+#include "verify_object.h"
 
 namespace art {
 
@@ -79,9 +80,7 @@
       return NULL;
     }
 
-    if (kIsDebugBuild) {
-      Runtime::Current()->GetHeap()->VerifyObject(obj);
-    }
+    VerifyObject(obj);
 
     DCHECK_NE((reinterpret_cast<uintptr_t>(obj) & 0xffff0000), 0xebad0000);
 
diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h
index 1ca6c4e..2f959db 100644
--- a/runtime/scoped_thread_state_change.h
+++ b/runtime/scoped_thread_state_change.h
@@ -19,6 +19,7 @@
 
 #include "base/casts.h"
 #include "thread-inl.h"
+#include "verify_object.h"
 
 namespace art {
 
@@ -165,9 +166,7 @@
       return NULL;
     }
 
-    if (kIsDebugBuild) {
-      Runtime::Current()->GetHeap()->VerifyObject(obj);
-    }
+    VerifyObject(obj);
 
     DCHECK_NE((reinterpret_cast<uintptr_t>(obj) & 0xffff0000), 0xebad0000);
 
diff --git a/runtime/sirt_ref.h b/runtime/sirt_ref.h
index 3c5e4f8..b22e816 100644
--- a/runtime/sirt_ref.h
+++ b/runtime/sirt_ref.h
@@ -45,8 +45,11 @@
     return down_cast<T*>(sirt_.GetReference(0));
   }
 
-  void reset(T* object = nullptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  // Returns the old reference.
+  T* reset(T* object = nullptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    T* old_ref = get();
     sirt_.SetReference(0, object);
+    return old_ref;
   }
 
  private:
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 864b86a..a6a0b29 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -25,14 +25,11 @@
 #include "runtime.h"
 #include "thread_list.h"
 #include "throw_location.h"
+#include "verify_object-inl.h"
 #include "vmap_table.h"
 
 namespace art {
 
-bool ShadowFrame::VerifyReference(const mirror::Object* val) const {
-  return !Runtime::Current()->GetHeap()->IsInTempSpace(val);
-}
-
 mirror::Object* ShadowFrame::GetThisObject() const {
   mirror::ArtMethod* m = GetMethod();
   if (m->IsStatic()) {
diff --git a/runtime/stack.h b/runtime/stack.h
index 7e9889e..6a62922 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -22,7 +22,9 @@
 #include "base/casts.h"
 #include "base/macros.h"
 #include "arch/context.h"
+#include "mirror/object.h"
 #include "mirror/object_reference.h"
+#include "verify_object.h"
 
 #include <stdint.h>
 #include <string>
@@ -213,26 +215,20 @@
     return *reinterpret_cast<unaligned_double*>(vreg);
   }
 
-  template <bool kChecked = false>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   mirror::Object* GetVRegReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK_LT(i, NumberOfVRegs());
+    mirror::Object* ref;
     if (HasReferenceArray()) {
-      mirror::Object* ref = References()[i].AsMirrorPtr();
-      if (kChecked) {
-        CHECK(VerifyReference(ref)) << "VReg " << i << "(" << ref
-                                    << ") is in protected space, reference array " << true;
-      }
-      return ref;
+      ref = References()[i].AsMirrorPtr();
     } else {
       const uint32_t* vreg_ptr = &vregs_[i];
-      mirror::Object* ref =
-          reinterpret_cast<const StackReference<mirror::Object>*>(vreg_ptr)->AsMirrorPtr();
-      if (kChecked) {
-        CHECK(VerifyReference(ref)) << "VReg " << i
-            << "(" << ref << ") is in protected space, reference array " << false;
-      }
-      return ref;
+      ref = reinterpret_cast<const StackReference<mirror::Object>*>(vreg_ptr)->AsMirrorPtr();
     }
+    if (kVerifyFlags & kVerifyReads) {
+      VerifyObject(ref);
+    }
+    return ref;
   }
 
   // Get view of vregs as range of consecutive arguments starting at i.
@@ -290,10 +286,12 @@
     }
   }
 
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetVRegReference(size_t i, mirror::Object* val) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK_LT(i, NumberOfVRegs());
-    DCHECK(!kMovingCollector || VerifyReference(val))
-        << "VReg " << i << "(" << val << ") is in protected space";
+    if (kVerifyFlags & kVerifyWrites) {
+      VerifyObject(val);
+    }
     uint32_t* vreg = &vregs_[i];
     reinterpret_cast<StackReference<mirror::Object>*>(vreg)->Assign(val);
     if (HasReferenceArray()) {
@@ -374,8 +372,6 @@
     return reinterpret_cast<const StackReference<mirror::Object>*>(vreg_end);
   }
 
-  bool VerifyReference(const mirror::Object* val) const;
-
   StackReference<mirror::Object>* References() {
     return const_cast<StackReference<mirror::Object>*>(const_cast<const ShadowFrame*>(this)->References());
   }
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index c0bf377..f7e88cc 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -152,9 +152,10 @@
 }
 
 inline void Thread::VerifyStack() {
-  gc::Heap* heap = Runtime::Current()->GetHeap();
-  if (heap->IsObjectValidationEnabled()) {
-    VerifyStackImpl();
+  if (kVerifyStack) {
+    if (Runtime::Current()->GetHeap()->IsObjectValidationEnabled()) {
+      VerifyStackImpl();
+    }
   }
 }
 
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 16655fb..8949a5b 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -66,6 +66,7 @@
 #include "thread_list.h"
 #include "utils.h"
 #include "verifier/dex_gc_map.h"
+#include "verify_object-inl.h"
 #include "vmap_table.h"
 #include "well_known_classes.h"
 
@@ -1217,8 +1218,8 @@
   if (UNLIKELY(result == nullptr)) {
     JniAbortF(nullptr, "use of deleted %s %p", ToStr<IndirectRefKind>(kind).c_str(), obj);
   } else {
-    if (kIsDebugBuild && (result != kInvalidIndirectRefObject)) {
-      Runtime::Current()->GetHeap()->VerifyObject(result);
+    if (result != kInvalidIndirectRefObject) {
+      VerifyObject(result);
     }
   }
   return result;
@@ -2000,9 +2001,7 @@
 };
 
 void Thread::SetClassLoaderOverride(mirror::ClassLoader* class_loader_override) {
-  if (kIsDebugBuild) {
-    Runtime::Current()->GetHeap()->VerifyObject(class_loader_override);
-  }
+  VerifyObject(class_loader_override);
   class_loader_override_ = class_loader_override;
 }
 
@@ -2037,11 +2036,9 @@
   }
 }
 
-static void VerifyRoot(mirror::Object** root, void* arg, uint32_t /*thread_id*/,
-                       RootType /*root_type*/) {
-  DCHECK(root != nullptr);
-  DCHECK(arg != nullptr);
-  reinterpret_cast<gc::Heap*>(arg)->VerifyObject(*root);
+static void VerifyRoot(mirror::Object** root, void* /*arg*/, uint32_t /*thread_id*/,
+                       RootType /*root_type*/) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  VerifyObject(*root);
 }
 
 void Thread::VerifyStackImpl() {
diff --git a/runtime/thread.h b/runtime/thread.h
index 48912d1..9813130 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -375,7 +375,8 @@
     return class_loader_override_;
   }
 
-  void SetClassLoaderOverride(mirror::ClassLoader* class_loader_override);
+  void SetClassLoaderOverride(mirror::ClassLoader* class_loader_override)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Create the internal representation of a stack trace, that is more time
   // and space efficient to compute than the StackTraceElement[]
@@ -391,7 +392,7 @@
 
   void VisitRoots(RootCallback* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void VerifyStack() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE void VerifyStack() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   //
   // Offsets of various members of native Thread class, used by compiled code.
diff --git a/runtime/verify_object-inl.h b/runtime/verify_object-inl.h
new file mode 100644
index 0000000..e211c83
--- /dev/null
+++ b/runtime/verify_object-inl.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_VERIFY_OBJECT_INL_H_
+#define ART_RUNTIME_VERIFY_OBJECT_INL_H_
+
+#include "verify_object.h"
+
+#include "gc/heap.h"
+#include "mirror/class-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+inline void VerifyObject(mirror::Object* obj) {
+  if (kVerifyObjectSupport > kVerifyObjectModeDisabled && obj != nullptr) {
+    if (kVerifyObjectSupport > kVerifyObjectModeFast) {
+      // Slow object verification, try the heap right away.
+      Runtime::Current()->GetHeap()->VerifyObjectBody(obj);
+    } else {
+      // Fast object verification, only call the heap if our quick sanity tests fail. The heap will
+      // print the diagnostic message.
+      bool failed = !IsAligned<kObjectAlignment>(obj);
+      if (!failed) {
+        mirror::Class* c = obj->GetClass<kVerifyNone>();
+        failed = failed || c == nullptr;
+        failed = failed ||!IsAligned<kObjectAlignment>(c);
+        failed = failed ||!VerifyClassClass(c);
+      }
+      if (UNLIKELY(failed)) {
+        Runtime::Current()->GetHeap()->VerifyObjectBody(obj);
+      }
+    }
+  }
+}
+
+inline bool VerifyClassClass(mirror::Class* c) {
+  if (UNLIKELY(c == nullptr)) {
+    return false;
+  }
+  // Note: We pass in flags to ensure that the accessors don't call VerifyObject.
+  mirror::Class* c_c = c->GetClass<kVerifyNone>();
+  return c_c != nullptr && c_c == c_c->GetClass<kVerifyNone>();
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_VERIFY_OBJECT_INL_H_
diff --git a/runtime/verify_object.h b/runtime/verify_object.h
new file mode 100644
index 0000000..b39df4a
--- /dev/null
+++ b/runtime/verify_object.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_VERIFY_OBJECT_H_
+#define ART_RUNTIME_VERIFY_OBJECT_H_
+
+#include "locks.h"
+
+#include <stdint.h>
+
+namespace art {
+
+namespace mirror {
+  class Class;
+  class Object;
+}  // namespace mirror
+
+// How we want to sanity check the heap's correctness.
+enum VerifyObjectMode {
+  kVerifyObjectModeDisabled,  // Heap verification is disabled.
+  kVerifyObjectModeFast,  // Sanity heap accesses quickly by using VerifyClassClass.
+  kVerifyObjectModeAll  // Sanity heap accesses thoroughly.
+};
+
+enum VerifyObjectFlags {
+  kVerifyNone = 0x0,
+  // Verify self when we are doing an operation.
+  kVerifyThis = 0x1,
+  // Verify reads from objects.
+  kVerifyReads = 0x2,
+  // Verify writes to objects.
+  kVerifyWrites = 0x4,
+  // Verify all things.
+  kVerifyAll = kVerifyThis | kVerifyReads | kVerifyWrites,
+};
+
+static constexpr bool kVerifyStack = kIsDebugBuild;
+static constexpr VerifyObjectFlags kDefaultVerifyFlags = kVerifyNone;
+static constexpr VerifyObjectMode kVerifyObjectSupport =
+    kDefaultVerifyFlags != 0 ? kVerifyObjectModeFast : kVerifyObjectModeDisabled;
+
+ALWAYS_INLINE inline void VerifyObject(mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS;
+
+// Check that c.getClass() == c.getClass().getClass().
+ALWAYS_INLINE inline bool VerifyClassClass(mirror::Class* c) NO_THREAD_SAFETY_ANALYSIS;
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_VERIFY_OBJECT_H_