Enable moving classes.

Slight reduction in Zygote size, memory savings are in the noise.
Before: Zygote size: 8739224
After: Zygote size: 8733568

Fixed a bug where we didn't set the concurrent start bytes after
switching the allocator from bump pointer to ROSAlloc in the
zygote. This caused excessive memory usage.

Added the method verifiers as roots to fix an issue caused by
RegTypes holding a Class*.

Added logic to clear card table in the SemiSpace collector, this
reduces DalvikOther from ~2400k -> ~1760k when using the SemiSpace
collector.

Added a missing lock to the timing loggers which caused a rare
one time crash in std::set.

Bug: 11771255
Bug: 8499494
Bug: 10802951

Change-Id: I99d2b528cd51c1c5ed7012e3220b3aefded680ae
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 7b42879..8e666dd 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1596,7 +1596,8 @@
   ClassLinker* class_linker = manager->GetClassLinker();
   const DexFile& dex_file = *manager->GetDexFile();
   SirtRef<mirror::DexCache> dex_cache(soa.Self(), class_linker->FindDexCache(dex_file));
-  SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()));
+  SirtRef<mirror::ClassLoader> class_loader(
+      soa.Self(), soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()));
   mirror::Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
 
   if (klass == NULL) {
@@ -1651,8 +1652,8 @@
   jobject jclass_loader = manager->GetClassLoader();
   SirtRef<mirror::ClassLoader> class_loader(
       soa.Self(), soa.Decode<mirror::ClassLoader*>(jclass_loader));
-  mirror::Class* klass = class_linker->FindClass(descriptor, class_loader);
-  if (klass == NULL) {
+  SirtRef<mirror::Class> klass(soa.Self(), class_linker->FindClass(descriptor, class_loader));
+  if (klass.get() == nullptr) {
     CHECK(soa.Self()->IsExceptionPending());
     soa.Self()->ClearException();
 
@@ -1669,8 +1670,8 @@
       LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
                  << " because: " << error_msg;
     }
-  } else if (!SkipClass(jclass_loader, dex_file, klass)) {
-    CHECK(klass->IsResolved()) << PrettyClass(klass);
+  } else if (!SkipClass(jclass_loader, dex_file, klass.get())) {
+    CHECK(klass->IsResolved()) << PrettyClass(klass.get());
     class_linker->VerifyClass(klass);
 
     if (klass->IsErroneous()) {
@@ -1680,7 +1681,7 @@
     }
 
     CHECK(klass->IsCompileTimeVerified() || klass->IsErroneous())
-        << PrettyDescriptor(klass) << ": state=" << klass->GetStatus();
+        << PrettyDescriptor(klass.get()) << ": state=" << klass->GetStatus();
   }
   soa.Self()->AssertNoPendingException();
 }
@@ -2123,9 +2124,10 @@
   ScopedObjectAccess soa(Thread::Current());
   SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
                                             soa.Decode<mirror::ClassLoader*>(jclass_loader));
-  mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor, class_loader);
+  SirtRef<mirror::Class> klass(soa.Self(),
+                               manager->GetClassLinker()->FindClass(descriptor, class_loader));
 
-  if (klass != NULL && !SkipClass(jclass_loader, dex_file, klass)) {
+  if (klass.get() != nullptr && !SkipClass(jclass_loader, dex_file, klass.get())) {
     // Only try to initialize classes that were successfully verified.
     if (klass->IsVerified()) {
       // Attempt to initialize the class but bail if we either need to initialize the super-class
@@ -2140,7 +2142,8 @@
         // parent-to-child and a child-to-parent lock ordering and consequent potential deadlock.
         // We need to use an ObjectLock due to potential suspension in the interpreting code. Rather
         // than use a special Object for the purpose we use the Class of java.lang.Class.
-        ObjectLock lock(soa.Self(), klass->GetClass());
+        SirtRef<mirror::Class> sirt_klass(soa.Self(), klass->GetClass());
+        ObjectLock<mirror::Class> lock(soa.Self(), &sirt_klass);
         // Attempt to initialize allowing initialization of parent classes but still not static
         // fields.
         manager->GetClassLinker()->EnsureInitialized(klass, false, true);
@@ -2164,10 +2167,11 @@
               VLOG(compiler) << "Initializing: " << descriptor;
               if (strcmp("Ljava/lang/Void;", descriptor) == 0) {
                 // Hand initialize j.l.Void to avoid Dex file operations in un-started runtime.
-                ObjectLock lock(soa.Self(), klass);
+                ObjectLock<mirror::Class> lock(soa.Self(), &klass);
                 mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields();
                 CHECK_EQ(fields->GetLength(), 1);
-                fields->Get(0)->SetObj(klass, manager->GetClassLinker()->FindPrimitiveClass('V'));
+                fields->Get(0)->SetObj(klass.get(),
+                                       manager->GetClassLinker()->FindPrimitiveClass('V'));
                 klass->SetStatus(mirror::Class::kStatusInitialized, soa.Self());
               } else {
                 manager->GetClassLinker()->EnsureInitialized(klass, true, true);
@@ -2180,7 +2184,7 @@
       // If successfully initialized place in SSB array.
       if (klass->IsInitialized()) {
         int32_t ssb_index = klass->GetDexTypeIndex();
-        klass->GetDexCache()->GetInitializedStaticStorage()->Set(ssb_index, klass);
+        klass->GetDexCache()->GetInitializedStaticStorage()->Set(ssb_index, klass.get());
       }
     }
     // Record the final class status if necessary.
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index c71cc97..3406fe6 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -152,14 +152,14 @@
     const DexFile::ClassDef& class_def = dex->GetClassDef(i);
     const char* descriptor = dex->GetClassDescriptor(class_def);
     mirror::Class* klass = class_linker_->FindSystemClass(descriptor);
-    EXPECT_TRUE(klass != NULL) << descriptor;
-    EXPECT_LT(image_begin, reinterpret_cast<byte*>(klass)) << descriptor;
+    EXPECT_TRUE(klass != nullptr) << descriptor;
     if (image_classes.find(descriptor) != image_classes.end()) {
-      // image classes should be located before the end of the image.
+      // Image classes should be located inside the image.
+      EXPECT_LT(image_begin, reinterpret_cast<byte*>(klass)) << descriptor;
       EXPECT_LT(reinterpret_cast<byte*>(klass), image_end) << descriptor;
     } else {
-      // non image classes should be in a space after the image.
-      EXPECT_GT(reinterpret_cast<byte*>(klass), image_end) << descriptor;
+      EXPECT_TRUE(reinterpret_cast<byte*>(klass) >= image_end ||
+                  reinterpret_cast<byte*>(klass) < image_begin) << descriptor;
     }
     EXPECT_TRUE(Monitor::IsValidLockWord(klass->GetLockWord()));
   }
diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc
index c8dee6d..bb32b2d 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -43,6 +43,7 @@
 }
 
 void CumulativeLogger::SetName(const std::string& name) {
+  MutexLock mu(Thread::Current(), lock_);
   name_.assign(name);
 }
 
@@ -61,6 +62,7 @@
 }
 
 uint64_t CumulativeLogger::GetTotalNs() const {
+  MutexLock mu(Thread::Current(), lock_);
   return GetTotalTime() * kAdjust;
 }
 
diff --git a/runtime/base/timing_logger.h b/runtime/base/timing_logger.h
index c1ff0a3..b0bcf10 100644
--- a/runtime/base/timing_logger.h
+++ b/runtime/base/timing_logger.h
@@ -31,16 +31,15 @@
 class CumulativeLogger {
  public:
   explicit CumulativeLogger(const std::string& name);
-  void prepare_stats();
   ~CumulativeLogger();
   void Start();
-  void End();
-  void Reset();
+  void End() LOCKS_EXCLUDED(lock_);
+  void Reset() LOCKS_EXCLUDED(lock_);
   void Dump(std::ostream& os) LOCKS_EXCLUDED(lock_);
   uint64_t GetTotalNs() const;
   // Allow the name to be modified, particularly when the cumulative logger is a field within a
   // parent class that is unable to determine the "name" of a sub-class.
-  void SetName(const std::string& name);
+  void SetName(const std::string& name) LOCKS_EXCLUDED(lock_);
   void AddLogger(const TimingLogger& logger) LOCKS_EXCLUDED(lock_);
   size_t GetIterations() const;
 
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 500cb59..3e5d90d 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -530,7 +530,8 @@
   for (size_t i = 0; i < ClassLinker::kClassRootsMax; ++i) {
     mirror::Class* c = GetClassRoot(ClassRoot(i));
     if (!c->IsArrayClass() && !c->IsPrimitive()) {
-      EnsureInitialized(GetClassRoot(ClassRoot(i)), true, true);
+      SirtRef<mirror::Class> sirt_class(self, GetClassRoot(ClassRoot(i)));
+      EnsureInitialized(sirt_class, true, true);
       self->AssertNoPendingException();
     }
   }
@@ -1133,7 +1134,7 @@
   }
 
   {
-    ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
+    WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
     if (!only_dirty || class_table_dirty_) {
       for (std::pair<const size_t, mirror::Class*>& it : class_table_) {
         it.second = down_cast<mirror::Class*>(visitor(it.second, arg));
@@ -1156,7 +1157,7 @@
   if (dex_cache_image_class_lookup_required_) {
     MoveImageClassesToClassTable();
   }
-  ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+  WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
   for (const std::pair<size_t, mirror::Class*>& it : class_table_) {
     if (!visitor(it.second, arg)) {
       return;
@@ -1249,7 +1250,10 @@
                                        size_t class_size) {
   DCHECK_GE(class_size, sizeof(mirror::Class));
   gc::Heap* heap = Runtime::Current()->GetHeap();
-  mirror::Object* k = heap->AllocNonMovableObject<true>(self, java_lang_Class, class_size);
+  mirror::Object* k =
+      kMovingClasses ?
+          heap->AllocObject<true>(self, java_lang_Class, class_size) :
+          heap->AllocNonMovableObject<true>(self, java_lang_Class, class_size);
   if (UNLIKELY(k == NULL)) {
     CHECK(self->IsExceptionPending());  // OOME.
     return NULL;
@@ -1287,21 +1291,23 @@
   DCHECK(klass != NULL);
   // Wait for the class if it has not already been linked.
   if (!klass->IsResolved() && !klass->IsErroneous()) {
-    ObjectLock lock(self, klass);
+    SirtRef<mirror::Class> sirt_class(self, klass);
+    ObjectLock<mirror::Class> lock(self, &sirt_class);
     // Check for circular dependencies between classes.
-    if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) {
-      ThrowClassCircularityError(klass);
-      klass->SetStatus(mirror::Class::kStatusError, self);
-      return NULL;
+    if (!sirt_class->IsResolved() && sirt_class->GetClinitThreadId() == self->GetTid()) {
+      ThrowClassCircularityError(sirt_class.get());
+      sirt_class->SetStatus(mirror::Class::kStatusError, self);
+      return nullptr;
     }
     // Wait for the pending initialization to complete.
-    while (!klass->IsResolved() && !klass->IsErroneous()) {
+    while (!sirt_class->IsResolved() && !sirt_class->IsErroneous()) {
       lock.WaitIgnoringInterrupts();
     }
+    klass = sirt_class.get();
   }
   if (klass->IsErroneous()) {
     ThrowEarlierClassFailure(klass);
-    return NULL;
+    return nullptr;
   }
   // Return the loaded class.  No exceptions should be pending.
   CHECK(klass->IsResolved()) << PrettyClass(klass);
@@ -1320,7 +1326,7 @@
 }
 
 mirror::Class* ClassLinker::FindClass(const char* descriptor,
-                                      SirtRef<mirror::ClassLoader>& class_loader) {
+                                      const SirtRef<mirror::ClassLoader>& class_loader) {
   DCHECK_NE(*descriptor, '\0') << "descriptor is empty string";
   Thread* self = Thread::Current();
   DCHECK(self != NULL);
@@ -1403,7 +1409,7 @@
 }
 
 mirror::Class* ClassLinker::DefineClass(const char* descriptor,
-                                        SirtRef<mirror::ClassLoader>& class_loader,
+                                        const SirtRef<mirror::ClassLoader>& class_loader,
                                         const DexFile& dex_file,
                                         const DexFile::ClassDef& dex_class_def) {
   Thread* self = Thread::Current();
@@ -1440,7 +1446,7 @@
     klass->SetStatus(mirror::Class::kStatusError, self);
     return NULL;
   }
-  ObjectLock lock(self, klass.get());
+  ObjectLock<mirror::Class> lock(self, &klass);
   klass->SetClinitThreadId(self->GetTid());
   // Add the newly loaded class to the loaded classes table.
   mirror::Class* existing = InsertClass(descriptor, klass.get(), Hash(descriptor));
@@ -1695,7 +1701,7 @@
   // Ignore virtual methods on the iterator.
 }
 
-static void LinkCode(SirtRef<mirror::ArtMethod>& method, const OatFile::OatClass* oat_class,
+static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::OatClass* oat_class,
                      uint32_t method_index)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Method shouldn't have already been linked.
@@ -1741,7 +1747,7 @@
 
 void ClassLinker::LoadClass(const DexFile& dex_file,
                             const DexFile::ClassDef& dex_class_def,
-                            SirtRef<mirror::Class>& klass,
+                            const SirtRef<mirror::Class>& klass,
                             mirror::ClassLoader* class_loader) {
   CHECK(klass.get() != NULL);
   CHECK(klass->GetDexCache() != NULL);
@@ -1861,7 +1867,8 @@
 }
 
 void ClassLinker::LoadField(const DexFile& /*dex_file*/, const ClassDataItemIterator& it,
-                            SirtRef<mirror::Class>& klass, SirtRef<mirror::ArtField>& dst) {
+                            const SirtRef<mirror::Class>& klass,
+                            const SirtRef<mirror::ArtField>& dst) {
   uint32_t field_idx = it.GetMemberIndex();
   dst->SetDexFieldIndex(field_idx);
   dst->SetDeclaringClass(klass.get());
@@ -1870,7 +1877,7 @@
 
 mirror::ArtMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file,
                                            const ClassDataItemIterator& it,
-                                           SirtRef<mirror::Class>& klass) {
+                                           const SirtRef<mirror::Class>& klass) {
   uint32_t dex_method_idx = it.GetMemberIndex();
   const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
   const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
@@ -1941,7 +1948,8 @@
   AppendToBootClassPath(dex_file, dex_cache);
 }
 
-void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
+void ClassLinker::AppendToBootClassPath(const DexFile& dex_file,
+                                        const SirtRef<mirror::DexCache>& dex_cache) {
   CHECK(dex_cache.get() != NULL) << dex_file.GetLocation();
   boot_class_path_.push_back(&dex_file);
   RegisterDexFile(dex_file, dex_cache);
@@ -1962,7 +1970,8 @@
   return IsDexFileRegisteredLocked(dex_file);
 }
 
-void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
+void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file,
+                                        const SirtRef<mirror::DexCache>& dex_cache) {
   dex_lock_.AssertExclusiveHeld(Thread::Current());
   CHECK(dex_cache.get() != NULL) << dex_file.GetLocation();
   CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation()))
@@ -1994,7 +2003,8 @@
   }
 }
 
-void ClassLinker::RegisterDexFile(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
+void ClassLinker::RegisterDexFile(const DexFile& dex_file,
+                                  const SirtRef<mirror::DexCache>& dex_cache) {
   WriterMutexLock mu(Thread::Current(), dex_lock_);
   RegisterDexFileLocked(dex_file, dex_cache);
 }
@@ -2040,11 +2050,13 @@
   return InitializePrimitiveClass(klass, type);
 }
 
-mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_class, Primitive::Type type) {
+mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_class,
+                                                     Primitive::Type type) {
   CHECK(primitive_class != NULL);
   // Must hold lock on object when initializing.
   Thread* self = Thread::Current();
-  ObjectLock lock(self, primitive_class);
+  SirtRef<mirror::Class> sirt_class(self, primitive_class);
+  ObjectLock<mirror::Class> lock(self, &sirt_class);
   primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
   primitive_class->SetPrimitiveType(type);
   primitive_class->SetStatus(mirror::Class::kStatusInitialized, self);
@@ -2068,7 +2080,7 @@
 //
 // Returns NULL with an exception raised on failure.
 mirror::Class* ClassLinker::CreateArrayClass(const char* descriptor,
-                                             SirtRef<mirror::ClassLoader>& class_loader) {
+                                             const SirtRef<mirror::ClassLoader>& class_loader) {
   // Identify the underlying component type
   CHECK_EQ('[', descriptor[0]);
   mirror::Class* component_type = FindClass(descriptor + 1, class_loader);
@@ -2138,7 +2150,7 @@
     }
     new_class->SetComponentType(component_type);
   }
-  ObjectLock lock(self, new_class.get());  // Must hold lock on object when initializing.
+  ObjectLock<mirror::Class> lock(self, &new_class);  // Must hold lock on object when initializing.
   DCHECK(new_class->GetComponentType() != NULL);
   mirror::Class* java_lang_Object = GetClassRoot(kJavaLangObject);
   new_class->SetSuperClass(java_lang_Object);
@@ -2421,10 +2433,10 @@
   }
 }
 
-void ClassLinker::VerifyClass(mirror::Class* klass) {
+void ClassLinker::VerifyClass(const SirtRef<mirror::Class>& klass) {
   // TODO: assert that the monitor on the Class is held
   Thread* self = Thread::Current();
-  ObjectLock lock(self, klass);
+  ObjectLock<mirror::Class> lock(self, &klass);
 
   // Don't attempt to re-verify if already sufficiently verified.
   if (klass->IsVerified() ||
@@ -2435,7 +2447,7 @@
   // The class might already be erroneous, for example at compile time if we attempted to verify
   // this class as a parent to another.
   if (klass->IsErroneous()) {
-    ThrowEarlierClassFailure(klass);
+    ThrowEarlierClassFailure(klass.get());
     return;
   }
 
@@ -2443,7 +2455,7 @@
     klass->SetStatus(mirror::Class::kStatusVerifying, self);
   } else {
     CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime)
-        << PrettyClass(klass);
+        << PrettyClass(klass.get());
     CHECK(!Runtime::Current()->IsCompiler());
     klass->SetStatus(mirror::Class::kStatusVerifyingAtRuntime, self);
   }
@@ -2452,23 +2464,23 @@
   SirtRef<mirror::Class> super(self, klass->GetSuperClass());
   if (super.get() != NULL) {
     // Acquire lock to prevent races on verifying the super class.
-    ObjectLock lock(self, super.get());
+    ObjectLock<mirror::Class> lock(self, &super);
 
     if (!super->IsVerified() && !super->IsErroneous()) {
-      VerifyClass(super.get());
+      VerifyClass(super);
     }
     if (!super->IsCompileTimeVerified()) {
       std::string error_msg(StringPrintf("Rejecting class %s that attempts to sub-class erroneous class %s",
-                                         PrettyDescriptor(klass).c_str(),
+                                         PrettyDescriptor(klass.get()).c_str(),
                                          PrettyDescriptor(super.get()).c_str()));
       LOG(ERROR) << error_msg  << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
       SirtRef<mirror::Throwable> cause(self, self->GetException(NULL));
-      if (cause.get() != NULL) {
+      if (cause.get() != nullptr) {
         self->ClearException();
       }
-      ThrowVerifyError(klass, "%s", error_msg.c_str());
-      if (cause.get() != NULL) {
-        self->GetException(NULL)->SetCause(cause.get());
+      ThrowVerifyError(klass.get(), "%s", error_msg.c_str());
+      if (cause.get() != nullptr) {
+        self->GetException(nullptr)->SetCause(cause.get());
       }
       klass->SetStatus(mirror::Class::kStatusError, self);
       return;
@@ -2478,26 +2490,26 @@
   // Try to use verification information from the oat file, otherwise do runtime verification.
   const DexFile& dex_file = *klass->GetDexCache()->GetDexFile();
   mirror::Class::Status oat_file_class_status(mirror::Class::kStatusNotReady);
-  bool preverified = VerifyClassUsingOatFile(dex_file, klass, oat_file_class_status);
+  bool preverified = VerifyClassUsingOatFile(dex_file, klass.get(), oat_file_class_status);
   if (oat_file_class_status == mirror::Class::kStatusError) {
     VLOG(class_linker) << "Skipping runtime verification of erroneous class "
-        << PrettyDescriptor(klass) << " in "
+        << PrettyDescriptor(klass.get()) << " in "
         << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
-    ThrowVerifyError(klass, "Rejecting class %s because it failed compile-time verification",
-                     PrettyDescriptor(klass).c_str());
+    ThrowVerifyError(klass.get(), "Rejecting class %s because it failed compile-time verification",
+                     PrettyDescriptor(klass.get()).c_str());
     klass->SetStatus(mirror::Class::kStatusError, self);
     return;
   }
   verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
   std::string error_msg;
   if (!preverified) {
-    verifier_failure = verifier::MethodVerifier::VerifyClass(klass,
+    verifier_failure = verifier::MethodVerifier::VerifyClass(klass.get(),
                                                              Runtime::Current()->IsCompiler(),
                                                              &error_msg);
   }
   if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) {
     if (!preverified && verifier_failure != verifier::MethodVerifier::kNoFailure) {
-      VLOG(class_linker) << "Soft verification failure in class " << PrettyDescriptor(klass)
+      VLOG(class_linker) << "Soft verification failure in class " << PrettyDescriptor(klass.get())
           << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
           << " because: " << error_msg;
     }
@@ -2527,11 +2539,11 @@
       }
     }
   } else {
-    LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(klass)
+    LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(klass.get())
         << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
         << " because: " << error_msg;
     self->AssertNoPendingException();
-    ThrowVerifyError(klass, "%s", error_msg.c_str());
+    ThrowVerifyError(klass.get(), "%s", error_msg.c_str());
     klass->SetStatus(mirror::Class::kStatusError, self);
   }
   if (preverified || verifier_failure == verifier::MethodVerifier::kNoFailure) {
@@ -2625,7 +2637,8 @@
   return false;
 }
 
-void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file, mirror::Class* klass) {
+void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file,
+                                                    const SirtRef<mirror::Class>& klass) {
   for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
     ResolveMethodExceptionHandlerTypes(dex_file, klass->GetDirectMethod(i));
   }
@@ -2763,13 +2776,13 @@
   self->AssertNoPendingException();
 
   {
-    ObjectLock lock(self, klass.get());  // Must hold lock on object when resolved.
+    ObjectLock<mirror::Class> lock(self, &klass);  // Must hold lock on object when resolved.
     // Link the fields and virtual methods, creating vtable and iftables
     SirtRef<mirror::ObjectArray<mirror::Class> > sirt_interfaces(
         self, soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
     if (!LinkClass(self, klass, sirt_interfaces)) {
       klass->SetStatus(mirror::Class::kStatusError, self);
-      return NULL;
+      return nullptr;
     }
 
     interfaces_sfield->SetObject(klass.get(), soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
@@ -2840,7 +2853,7 @@
 
 
 mirror::ArtMethod* ClassLinker::CreateProxyConstructor(Thread* self,
-                                                       SirtRef<mirror::Class>& klass,
+                                                       const SirtRef<mirror::Class>& klass,
                                                        mirror::Class* proxy_class) {
   // Create constructor for Proxy that must initialize h
   mirror::ObjectArray<mirror::ArtMethod>* proxy_direct_methods =
@@ -2870,8 +2883,9 @@
   DCHECK(constructor->IsPublic());
 }
 
-mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<mirror::Class>& klass,
-                                                  SirtRef<mirror::ArtMethod>& prototype) {
+mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self,
+                                                  const SirtRef<mirror::Class>& klass,
+                                                  const SirtRef<mirror::ArtMethod>& prototype) {
   // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
   // prototype method
   prototype->GetDeclaringClass()->GetDexCache()->SetResolvedMethod(prototype->GetDexMethodIndex(),
@@ -2966,7 +2980,7 @@
   return init_done_;
 }
 
-bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
+bool ClassLinker::InitializeClass(const SirtRef<mirror::Class>& klass, bool can_init_statics,
                                   bool can_init_parents) {
   // see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol
 
@@ -2978,14 +2992,14 @@
   }
 
   // Fast fail if initialization requires a full runtime. Not part of the JLS.
-  if (!CanWeInitializeClass(klass, can_init_statics, can_init_parents)) {
+  if (!CanWeInitializeClass(klass.get(), can_init_statics, can_init_parents)) {
     return false;
   }
 
   Thread* self = Thread::Current();
   uint64_t t0;
   {
-    ObjectLock lock(self, klass);
+    ObjectLock<mirror::Class> lock(self, &klass);
 
     // Re-check under the lock in case another thread initialized ahead of us.
     if (klass->IsInitialized()) {
@@ -2994,11 +3008,11 @@
 
     // Was the class already found to be erroneous? Done under the lock to match the JLS.
     if (klass->IsErroneous()) {
-      ThrowEarlierClassFailure(klass);
+      ThrowEarlierClassFailure(klass.get());
       return false;
     }
 
-    CHECK(klass->IsResolved()) << PrettyClass(klass) << ": state=" << klass->GetStatus();
+    CHECK(klass->IsResolved()) << PrettyClass(klass.get()) << ": state=" << klass->GetStatus();
 
     if (!klass->IsVerified()) {
       VerifyClass(klass);
@@ -3035,7 +3049,7 @@
       return false;
     }
 
-    CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << PrettyClass(klass);
+    CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << PrettyClass(klass.get());
 
     // From here out other threads may observe that we're initializing and so changes of state
     // require the a notification.
@@ -3051,16 +3065,17 @@
     if (!super_class->IsInitialized()) {
       CHECK(!super_class->IsInterface());
       CHECK(can_init_parents);
-      bool super_initialized = InitializeClass(super_class, can_init_statics, true);
+      SirtRef<mirror::Class> sirt_super(self, super_class);
+      bool super_initialized = InitializeClass(sirt_super, can_init_statics, true);
       if (!super_initialized) {
         // The super class was verified ahead of entering initializing, we should only be here if
         // the super class became erroneous due to initialization.
-        CHECK(super_class->IsErroneous() && self->IsExceptionPending())
-            << "Super class initialization failed for " << PrettyDescriptor(super_class)
-            << " that has unexpected status " << super_class->GetStatus()
+        CHECK(sirt_super->IsErroneous() && self->IsExceptionPending())
+            << "Super class initialization failed for " << PrettyDescriptor(sirt_super.get())
+            << " that has unexpected status " << sirt_super->GetStatus()
             << "\nPending exception:\n"
             << (self->GetException(NULL) != NULL ? self->GetException(NULL)->Dump() : "");
-        ObjectLock lock(self, klass);
+        ObjectLock<mirror::Class> lock(self, &klass);
         // Initialization failed because the super-class is erroneous.
         klass->SetStatus(mirror::Class::kStatusError, self);
         return false;
@@ -3069,7 +3084,7 @@
   }
 
   if (klass->NumStaticFields() > 0) {
-    ClassHelper kh(klass);
+    ClassHelper kh(klass.get());
     const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
     CHECK(dex_class_def != NULL);
     const DexFile& dex_file = kh.GetDexFile();
@@ -3081,7 +3096,7 @@
       CHECK(can_init_statics);
       // We reordered the fields, so we need to be able to map the field indexes to the right fields.
       SafeMap<uint32_t, mirror::ArtField*> field_map;
-      ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
+      ConstructFieldMap(dex_file, *dex_class_def, klass.get(), field_map);
       for (size_t i = 0; it.HasNext(); i++, it.Next()) {
         it.ReadValueToField(field_map.Get(i));
       }
@@ -3100,13 +3115,13 @@
   }
 
   // Opportunistically set static method trampolines to their destination.
-  FixupStaticTrampolines(klass);
+  FixupStaticTrampolines(klass.get());
 
   uint64_t t1 = NanoTime();
 
   bool success = true;
   {
-    ObjectLock lock(self, klass);
+    ObjectLock<mirror::Class> lock(self, &klass);
 
     if (self->IsExceptionPending()) {
       WrapExceptionInInitializer();
@@ -3122,7 +3137,7 @@
       // Set the class as initialized except if failed to initialize static fields.
       klass->SetStatus(mirror::Class::kStatusInitialized, self);
       if (VLOG_IS_ON(class_linker)) {
-        ClassHelper kh(klass);
+        ClassHelper kh(klass.get());
         LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
       }
     }
@@ -3130,7 +3145,8 @@
   return success;
 }
 
-bool ClassLinker::WaitForInitializeClass(mirror::Class* klass, Thread* self, ObjectLock& lock)
+bool ClassLinker::WaitForInitializeClass(const SirtRef<mirror::Class>& klass, Thread* self,
+                                         ObjectLock<mirror::Class>& lock)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   while (true) {
     self->AssertNoPendingException();
@@ -3157,47 +3173,49 @@
       // The caller wants an exception, but it was thrown in a
       // different thread.  Synthesize one here.
       ThrowNoClassDefFoundError("<clinit> failed for class %s; see exception in other thread",
-                                PrettyDescriptor(klass).c_str());
+                                PrettyDescriptor(klass.get()).c_str());
       return false;
     }
     if (klass->IsInitialized()) {
       return true;
     }
-    LOG(FATAL) << "Unexpected class status. " << PrettyClass(klass) << " is " << klass->GetStatus();
+    LOG(FATAL) << "Unexpected class status. " << PrettyClass(klass.get()) << " is "
+        << klass->GetStatus();
   }
-  LOG(FATAL) << "Not Reached" << PrettyClass(klass);
+  LOG(FATAL) << "Not Reached" << PrettyClass(klass.get());
 }
 
-bool ClassLinker::ValidateSuperClassDescriptors(const mirror::Class* klass) {
+bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& klass) {
   if (klass->IsInterface()) {
     return true;
   }
+  Thread* self = Thread::Current();
   // begin with the methods local to the superclass
   if (klass->HasSuperClass() &&
       klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
-    const mirror::Class* super = klass->GetSuperClass();
+    SirtRef<mirror::Class> super(self, klass->GetSuperClass());
     for (int i = super->GetVTable()->GetLength() - 1; i >= 0; --i) {
       const mirror::ArtMethod* method = klass->GetVTable()->Get(i);
       if (method != super->GetVTable()->Get(i) &&
-          !IsSameMethodSignatureInDifferentClassContexts(method, super, klass)) {
-        ThrowLinkageError(klass, "Class %s method %s resolves differently in superclass %s",
-                          PrettyDescriptor(klass).c_str(), PrettyMethod(method).c_str(),
-                          PrettyDescriptor(super).c_str());
+          !IsSameMethodSignatureInDifferentClassContexts(method, super.get(), klass.get())) {
+        ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in superclass %s",
+                          PrettyDescriptor(klass.get()).c_str(), PrettyMethod(method).c_str(),
+                          PrettyDescriptor(super.get()).c_str());
         return false;
       }
     }
   }
   for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
-    mirror::Class* interface = klass->GetIfTable()->GetInterface(i);
+    SirtRef<mirror::Class> interface(self, klass->GetIfTable()->GetInterface(i));
     if (klass->GetClassLoader() != interface->GetClassLoader()) {
       for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
         const mirror::ArtMethod* method = klass->GetIfTable()->GetMethodArray(i)->Get(j);
-        if (!IsSameMethodSignatureInDifferentClassContexts(method, interface,
+        if (!IsSameMethodSignatureInDifferentClassContexts(method, interface.get(),
                                                            method->GetDeclaringClass())) {
-          ThrowLinkageError(klass, "Class %s method %s resolves differently in interface %s",
+          ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in interface %s",
                             PrettyDescriptor(method->GetDeclaringClass()).c_str(),
                             PrettyMethod(method).c_str(),
-                            PrettyDescriptor(interface).c_str());
+                            PrettyDescriptor(interface.get()).c_str());
           return false;
         }
       }
@@ -3214,17 +3232,22 @@
   if (klass1 == klass2) {
     return true;
   }
+  Thread* self = Thread::Current();
+  CHECK(klass1 != nullptr);
+  CHECK(klass2 != nullptr);
+  SirtRef<mirror::ClassLoader> loader1(self, klass1->GetClassLoader());
+  SirtRef<mirror::ClassLoader> loader2(self, klass2->GetClassLoader());
   const DexFile& dex_file = *method->GetDeclaringClass()->GetDexCache()->GetDexFile();
   const DexFile::ProtoId& proto_id =
       dex_file.GetMethodPrototype(dex_file.GetMethodId(method->GetDexMethodIndex()));
   for (DexFileParameterIterator it(dex_file, proto_id); it.HasNext(); it.Next()) {
     const char* descriptor = it.GetDescriptor();
-    if (descriptor == NULL) {
+    if (descriptor == nullptr) {
       break;
     }
     if (descriptor[0] == 'L' || descriptor[0] == '[') {
       // Found a non-primitive type.
-      if (!IsSameDescriptorInDifferentClassContexts(descriptor, klass1, klass2)) {
+      if (!IsSameDescriptorInDifferentClassContexts(descriptor, loader1, loader2)) {
         return false;
       }
     }
@@ -3232,47 +3255,42 @@
   // Check the return type
   const char* descriptor = dex_file.GetReturnTypeDescriptor(proto_id);
   if (descriptor[0] == 'L' || descriptor[0] == '[') {
-    if (!IsSameDescriptorInDifferentClassContexts(descriptor, klass1, klass2)) {
+    if (!IsSameDescriptorInDifferentClassContexts(descriptor, loader1, loader2)) {
       return false;
     }
   }
   return true;
 }
 
-// Returns true if the descriptor resolves to the same class in the context of klass1 and klass2.
+// Returns true if the descriptor resolves to the same class in the context of loader1 and loader2.
 bool ClassLinker::IsSameDescriptorInDifferentClassContexts(const char* descriptor,
-                                                           const mirror::Class* klass1,
-                                                           const mirror::Class* klass2) {
-  CHECK(descriptor != NULL);
-  CHECK(klass1 != NULL);
-  CHECK(klass2 != NULL);
-  if (klass1 == klass2) {
-    return true;
-  }
+                                                           SirtRef<mirror::ClassLoader>& loader1,
+                                                           SirtRef<mirror::ClassLoader>& loader2) {
+  CHECK(descriptor != nullptr);
   Thread* self = Thread::Current();
-  SirtRef<mirror::ClassLoader> class_loader1(self, klass1->GetClassLoader());
-  mirror::Class* found1 = FindClass(descriptor, class_loader1);
-  if (found1 == NULL) {
-    Thread::Current()->ClearException();
+  SirtRef<mirror::Class> found1(self, FindClass(descriptor, loader1));
+  if (found1.get() == nullptr) {
+    self->ClearException();
   }
-  SirtRef<mirror::ClassLoader> class_loader2(self, klass2->GetClassLoader());
-  mirror::Class* found2 = FindClass(descriptor, class_loader2);
-  if (found2 == NULL) {
-    Thread::Current()->ClearException();
+  mirror::Class* found2 = FindClass(descriptor, loader2);
+  if (found2 == nullptr) {
+    self->ClearException();
   }
-  return found1 == found2;
+  return found1.get() == found2;
 }
 
-bool ClassLinker::EnsureInitialized(mirror::Class* c, bool can_init_fields, bool can_init_parents) {
-  DCHECK(c != NULL);
+bool ClassLinker::EnsureInitialized(const SirtRef<mirror::Class>& c, bool can_init_fields,
+                                    bool can_init_parents) {
+  DCHECK(c.get() != NULL);
   if (c->IsInitialized()) {
     return true;
   }
 
   bool success = InitializeClass(c, can_init_fields, can_init_parents);
   if (!success) {
-    Thread* self = Thread::Current();
-    CHECK(self->IsExceptionPending() || !can_init_fields || !can_init_parents) << PrettyClass(c);
+    if (can_init_fields && can_init_parents) {
+      CHECK(Thread::Current()->IsExceptionPending()) << PrettyClass(c.get());
+    }
   }
   return success;
 }
@@ -3285,13 +3303,14 @@
   Thread* self = Thread::Current();
   SirtRef<mirror::DexCache> dex_cache(self, c->GetDexCache());
   SirtRef<mirror::ClassLoader> class_loader(self, c->GetClassLoader());
+  CHECK(!kMovingFields);
   for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
     field_map.Put(i, ResolveField(dex_file, it.GetMemberIndex(), dex_cache, class_loader, true));
   }
 }
 
-bool ClassLinker::LinkClass(Thread* self, SirtRef<mirror::Class>& klass,
-                            SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
+bool ClassLinker::LinkClass(Thread* self, const SirtRef<mirror::Class>& klass,
+                            const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
   CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());
   if (!LinkSuperClass(klass)) {
     return false;
@@ -3312,7 +3331,8 @@
   return true;
 }
 
-bool ClassLinker::LoadSuperAndInterfaces(SirtRef<mirror::Class>& klass, const DexFile& dex_file) {
+bool ClassLinker::LoadSuperAndInterfaces(const SirtRef<mirror::Class>& klass,
+                                         const DexFile& dex_file) {
   CHECK_EQ(mirror::Class::kStatusIdx, klass->GetStatus());
   const DexFile::ClassDef& class_def = dex_file.GetClassDef(klass->GetDexClassDefIndex());
   uint16_t super_class_idx = class_def.superclass_idx_;
@@ -3355,7 +3375,7 @@
   return true;
 }
 
-bool ClassLinker::LinkSuperClass(SirtRef<mirror::Class>& klass) {
+bool ClassLinker::LinkSuperClass(const SirtRef<mirror::Class>& klass) {
   CHECK(!klass->IsPrimitive());
   mirror::Class* super = klass->GetSuperClass();
   if (klass.get() == GetClassRoot(kJavaLangObject)) {
@@ -3414,8 +3434,8 @@
 }
 
 // Populate the class vtable and itable. Compute return type indices.
-bool ClassLinker::LinkMethods(SirtRef<mirror::Class>& klass,
-                              SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
+bool ClassLinker::LinkMethods(const SirtRef<mirror::Class>& klass,
+                              const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
   if (klass->IsInterface()) {
     // No vtable.
     size_t count = klass->NumVirtualMethods();
@@ -3435,7 +3455,7 @@
   return true;
 }
 
-bool ClassLinker::LinkVirtualMethods(SirtRef<mirror::Class>& klass) {
+bool ClassLinker::LinkVirtualMethods(const SirtRef<mirror::Class>& klass) {
   Thread* self = Thread::Current();
   if (klass->HasSuperClass()) {
     uint32_t max_count = klass->NumVirtualMethods() + klass->GetSuperClass()->GetVTable()->GetLength();
@@ -3518,8 +3538,8 @@
   return true;
 }
 
-bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
-                                       SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
+bool ClassLinker::LinkInterfaceMethods(const SirtRef<mirror::Class>& klass,
+                                       const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
   // Set the imt table to be all conflicts by default.
   klass->SetImTable(Runtime::Current()->GetDefaultImt());
   size_t super_ifcount;
@@ -3529,14 +3549,17 @@
     super_ifcount = 0;
   }
   size_t ifcount = super_ifcount;
-  ClassHelper kh(klass.get());
-  uint32_t num_interfaces =
-      interfaces.get() == nullptr ? kh.NumDirectInterfaces() : interfaces->GetLength();
-  ifcount += num_interfaces;
-  for (size_t i = 0; i < num_interfaces; i++) {
-    mirror::Class* interface =
-        interfaces.get() == nullptr ? kh.GetDirectInterface(i) : interfaces->Get(i);
-    ifcount += interface->GetIfTableCount();
+  uint32_t num_interfaces;
+  {
+    ClassHelper kh(klass.get());
+    num_interfaces =
+        interfaces.get() == nullptr ? kh.NumDirectInterfaces() : interfaces->GetLength();
+    ifcount += num_interfaces;
+    for (size_t i = 0; i < num_interfaces; i++) {
+      mirror::Class* interface =
+          interfaces.get() == nullptr ? kh.GetDirectInterface(i) : interfaces->Get(i);
+      ifcount += interface->GetIfTableCount();
+    }
   }
   if (ifcount == 0) {
     // Class implements no interfaces.
@@ -3576,6 +3599,7 @@
   // Flatten the interface inheritance hierarchy.
   size_t idx = super_ifcount;
   for (size_t i = 0; i < num_interfaces; i++) {
+    ClassHelper kh(klass.get());
     mirror::Class* interface =
         interfaces.get() == nullptr ? kh.GetDirectInterface(i) : interfaces->Get(i);
     DCHECK(interface != NULL);
@@ -3640,11 +3664,8 @@
     return false;
   }
   std::vector<mirror::ArtMethod*> miranda_list;
-  MethodHelper vtable_mh(NULL);
-  MethodHelper interface_mh(NULL);
   for (size_t i = 0; i < ifcount; ++i) {
-    mirror::Class* interface = iftable->GetInterface(i);
-    size_t num_methods = interface->NumVirtualMethods();
+    size_t num_methods = iftable->GetInterface(i)->NumVirtualMethods();
     if (num_methods > 0) {
       SirtRef<mirror::ObjectArray<mirror::ArtMethod> >
           method_array(self, AllocArtMethodArray(self, num_methods));
@@ -3656,8 +3677,8 @@
       SirtRef<mirror::ObjectArray<mirror::ArtMethod> > vtable(self,
                                                               klass->GetVTableDuringLinking());
       for (size_t j = 0; j < num_methods; ++j) {
-        mirror::ArtMethod* interface_method = interface->GetVirtualMethod(j);
-        interface_mh.ChangeMethod(interface_method);
+        mirror::ArtMethod* interface_method = iftable->GetInterface(i)->GetVirtualMethod(j);
+        MethodHelper interface_mh(interface_method);
         int32_t k;
         // For each method listed in the interface's method list, find the
         // matching method in our class's method list.  We want to favor the
@@ -3669,7 +3690,7 @@
         // matter which direction we go.  We walk it backward anyway.)
         for (k = vtable->GetLength() - 1; k >= 0; --k) {
           mirror::ArtMethod* vtable_method = vtable->Get(k);
-          vtable_mh.ChangeMethod(vtable_method);
+          MethodHelper vtable_mh(vtable_method);
           if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
             if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) {
               ThrowIllegalAccessError(klass.get(),
@@ -3694,7 +3715,7 @@
           SirtRef<mirror::ArtMethod> miranda_method(self, NULL);
           for (size_t mir = 0; mir < miranda_list.size(); mir++) {
             mirror::ArtMethod* mir_method = miranda_list[mir];
-            vtable_mh.ChangeMethod(mir_method);
+            MethodHelper vtable_mh(mir_method);
             if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
               miranda_method.reset(miranda_list[mir]);
               break;
@@ -3772,12 +3793,12 @@
   return true;
 }
 
-bool ClassLinker::LinkInstanceFields(SirtRef<mirror::Class>& klass) {
+bool ClassLinker::LinkInstanceFields(const SirtRef<mirror::Class>& klass) {
   CHECK(klass.get() != NULL);
   return LinkFields(klass, false);
 }
 
-bool ClassLinker::LinkStaticFields(SirtRef<mirror::Class>& klass) {
+bool ClassLinker::LinkStaticFields(const SirtRef<mirror::Class>& klass) {
   CHECK(klass.get() != NULL);
   size_t allocated_class_size = klass->GetClassSize();
   bool success = LinkFields(klass, true);
@@ -3813,7 +3834,7 @@
   }
 };
 
-bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) {
+bool ClassLinker::LinkFields(const SirtRef<mirror::Class>& klass, bool is_static) {
   size_t num_fields =
       is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
 
@@ -3972,7 +3993,7 @@
 
 //  Set the bitmap of reference offsets, refOffsets, from the ifields
 //  list.
-void ClassLinker::CreateReferenceInstanceOffsets(SirtRef<mirror::Class>& klass) {
+void ClassLinker::CreateReferenceInstanceOffsets(const SirtRef<mirror::Class>& klass) {
   uint32_t reference_offsets = 0;
   mirror::Class* super_class = klass->GetSuperClass();
   if (super_class != NULL) {
@@ -3986,11 +4007,11 @@
   CreateReferenceOffsets(klass, false, reference_offsets);
 }
 
-void ClassLinker::CreateReferenceStaticOffsets(SirtRef<mirror::Class>& klass) {
+void ClassLinker::CreateReferenceStaticOffsets(const SirtRef<mirror::Class>& klass) {
   CreateReferenceOffsets(klass, true, 0);
 }
 
-void ClassLinker::CreateReferenceOffsets(SirtRef<mirror::Class>& klass, bool is_static,
+void ClassLinker::CreateReferenceOffsets(const SirtRef<mirror::Class>& klass, bool is_static,
                                          uint32_t reference_offsets) {
   size_t num_reference_fields =
       is_static ? klass->NumReferenceStaticFieldsDuringLinking()
@@ -4023,7 +4044,7 @@
 }
 
 mirror::String* ClassLinker::ResolveString(const DexFile& dex_file, uint32_t string_idx,
-                                           SirtRef<mirror::DexCache>& dex_cache) {
+                                           const SirtRef<mirror::DexCache>& dex_cache) {
   DCHECK(dex_cache.get() != nullptr);
   mirror::String* resolved = dex_cache->GetResolvedString(string_idx);
   if (resolved != NULL) {
@@ -4045,8 +4066,8 @@
 }
 
 mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_idx,
-                                        SirtRef<mirror::DexCache>& dex_cache,
-                                        SirtRef<mirror::ClassLoader>& class_loader) {
+                                        const SirtRef<mirror::DexCache>& dex_cache,
+                                        const SirtRef<mirror::ClassLoader>& class_loader) {
   DCHECK(dex_cache.get() != NULL);
   mirror::Class* resolved = dex_cache->GetResolvedType(type_idx);
   if (resolved == NULL) {
@@ -4064,9 +4085,11 @@
       // Convert a ClassNotFoundException to a NoClassDefFoundError.
       SirtRef<mirror::Throwable> cause(self, self->GetException(NULL));
       if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) {
+        SirtRef<mirror::Class> sirt_resolved(self, resolved);
         Thread::Current()->ClearException();
         ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor);
         self->GetException(NULL)->SetCause(cause.get());
+        resolved = sirt_resolved.get();
       }
     }
   }
@@ -4077,8 +4100,8 @@
 
 mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file,
                                               uint32_t method_idx,
-                                              SirtRef<mirror::DexCache>& dex_cache,
-                                              SirtRef<mirror::ClassLoader>& class_loader,
+                                              const SirtRef<mirror::DexCache>& dex_cache,
+                                              const SirtRef<mirror::ClassLoader>& class_loader,
                                               const mirror::ArtMethod* referrer,
                                               InvokeType type) {
   DCHECK(dex_cache.get() != NULL);
@@ -4223,8 +4246,8 @@
 }
 
 mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t field_idx,
-                                            SirtRef<mirror::DexCache>& dex_cache,
-                                            SirtRef<mirror::ClassLoader>& class_loader,
+                                            const SirtRef<mirror::DexCache>& dex_cache,
+                                            const SirtRef<mirror::ClassLoader>& class_loader,
                                             bool is_static) {
   DCHECK(dex_cache.get() != nullptr);
   mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
@@ -4263,8 +4286,8 @@
 
 mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file,
                                                uint32_t field_idx,
-                                               SirtRef<mirror::DexCache>& dex_cache,
-                                               SirtRef<mirror::ClassLoader>& class_loader) {
+                                               const SirtRef<mirror::DexCache>& dex_cache,
+                                               const SirtRef<mirror::ClassLoader>& class_loader) {
   DCHECK(dex_cache.get() != nullptr);
   mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
   if (resolved != NULL) {
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 4e2cc06..c0b5e81 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -45,7 +45,7 @@
 }  // namespace mirror
 
 class InternTable;
-class ObjectLock;
+template<class T> class ObjectLock;
 class ScopedObjectAccess;
 template<class T> class SirtRef;
 
@@ -72,7 +72,7 @@
 
   // Finds a class by its descriptor, loading it if necessary.
   // If class_loader is null, searches boot_class_path_.
-  mirror::Class* FindClass(const char* descriptor, SirtRef<mirror::ClassLoader>& class_loader)
+  mirror::Class* FindClass(const char* descriptor, const SirtRef<mirror::ClassLoader>& class_loader)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::Class* FindSystemClass(const char* descriptor)
@@ -82,7 +82,8 @@
   bool IsInitialized() const;
 
   // Define a new a class based on a ClassDef from a DexFile
-  mirror::Class* DefineClass(const char* descriptor, SirtRef<mirror::ClassLoader>& class_loader,
+  mirror::Class* DefineClass(const char* descriptor,
+                             const SirtRef<mirror::ClassLoader>& class_loader,
                              const DexFile& dex_file, const DexFile::ClassDef& dex_class_def)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -126,7 +127,7 @@
   // Resolve a String with the given index from the DexFile, storing the
   // result in the DexCache.
   mirror::String* ResolveString(const DexFile& dex_file, uint32_t string_idx,
-                                SirtRef<mirror::DexCache>& dex_cache)
+                                const SirtRef<mirror::DexCache>& dex_cache)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Resolve a Type with the given index from the DexFile, storing the
@@ -150,8 +151,8 @@
   // type, since it may be referenced from but not contained within
   // the given DexFile.
   mirror::Class* ResolveType(const DexFile& dex_file, uint16_t type_idx,
-                             SirtRef<mirror::DexCache>& dex_cache,
-                             SirtRef<mirror::ClassLoader>& class_loader)
+                             const SirtRef<mirror::DexCache>& dex_cache,
+                             const SirtRef<mirror::ClassLoader>& class_loader)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Resolve a method with a given ID from the DexFile, storing the
@@ -161,8 +162,8 @@
   // virtual method.
   mirror::ArtMethod* ResolveMethod(const DexFile& dex_file,
                                    uint32_t method_idx,
-                                   SirtRef<mirror::DexCache>& dex_cache,
-                                   SirtRef<mirror::ClassLoader>& class_loader,
+                                   const SirtRef<mirror::DexCache>& dex_cache,
+                                   const SirtRef<mirror::ClassLoader>& class_loader,
                                    const mirror::ArtMethod* referrer,
                                    InvokeType type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -182,8 +183,8 @@
   // field.
   mirror::ArtField* ResolveField(const DexFile& dex_file,
                                  uint32_t field_idx,
-                                 SirtRef<mirror::DexCache>& dex_cache,
-                                 SirtRef<mirror::ClassLoader>& class_loader,
+                                 const SirtRef<mirror::DexCache>& dex_cache,
+                                 const SirtRef<mirror::ClassLoader>& class_loader,
                                  bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -193,8 +194,8 @@
   // field resolution semantics are followed.
   mirror::ArtField* ResolveFieldJLS(const DexFile& dex_file,
                                     uint32_t field_idx,
-                                    SirtRef<mirror::DexCache>& dex_cache,
-                                    SirtRef<mirror::ClassLoader>& class_loader)
+                                    const SirtRef<mirror::DexCache>& dex_cache,
+                                    const SirtRef<mirror::ClassLoader>& class_loader)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get shorty from method index without resolution. Used to do handlerization.
@@ -204,7 +205,8 @@
   // Returns true on success, false if there's an exception pending.
   // can_run_clinit=false allows the compiler to attempt to init a class,
   // given the restriction that no <clinit> execution is possible.
-  bool EnsureInitialized(mirror::Class* c, bool can_run_clinit, bool can_init_fields)
+  bool EnsureInitialized(const SirtRef<mirror::Class>& c,
+                         bool can_init_fields, bool can_init_parents)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Initializes classes that have instances in the image but that have
@@ -214,7 +216,7 @@
   void RegisterDexFile(const DexFile& dex_file)
       LOCKS_EXCLUDED(dex_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void RegisterDexFile(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache)
+  void RegisterDexFile(const DexFile& dex_file, const SirtRef<mirror::DexCache>& dex_cache)
       LOCKS_EXCLUDED(dex_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -303,11 +305,12 @@
                                                                               size_t length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void VerifyClass(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void VerifyClass(const SirtRef<mirror::Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class* klass,
                                mirror::Class::Status& oat_file_class_status)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void ResolveClassExceptionHandlerTypes(const DexFile& dex_file, mirror::Class* klass)
+  void ResolveClassExceptionHandlerTypes(const DexFile& dex_file,
+                                         const SirtRef<mirror::Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, mirror::ArtMethod* klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -380,7 +383,8 @@
   // Alloc* convenience functions to avoid needing to pass in mirror::Class*
   // values that are known to the ClassLinker such as
   // kObjectArrayClass and kJavaLangString etc.
-  mirror::Class* AllocClass(Thread* self, size_t class_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  mirror::Class* AllocClass(Thread* self, size_t class_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::DexCache* AllocDexCache(Thread* self, const DexFile& dex_file)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::ArtField* AllocArtField(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -392,12 +396,12 @@
 
 
   mirror::Class* CreateArrayClass(const char* descriptor,
-                                  SirtRef<mirror::ClassLoader>& class_loader)
+                                  const SirtRef<mirror::ClassLoader>& class_loader)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void AppendToBootClassPath(const DexFile& dex_file)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void AppendToBootClassPath(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache)
+  void AppendToBootClassPath(const DexFile& dex_file, const SirtRef<mirror::DexCache>& dex_cache)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
@@ -409,17 +413,17 @@
 
   void LoadClass(const DexFile& dex_file,
                  const DexFile::ClassDef& dex_class_def,
-                 SirtRef<mirror::Class>& klass,
+                 const SirtRef<mirror::Class>& klass,
                  mirror::ClassLoader* class_loader)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it,
-                 SirtRef<mirror::Class>& klass, SirtRef<mirror::ArtField>& dst)
+                 const SirtRef<mirror::Class>& klass, const SirtRef<mirror::ArtField>& dst)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::ArtMethod* LoadMethod(Thread* self, const DexFile& dex_file,
                                 const ClassDataItemIterator& dex_method,
-                                SirtRef<mirror::Class>& klass)
+                                const SirtRef<mirror::Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void FixupStaticTrampolines(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -428,20 +432,22 @@
   const OatFile::OatClass* GetOatClass(const DexFile& dex_file, uint16_t class_def_idx)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void RegisterDexFileLocked(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache)
+  void RegisterDexFileLocked(const DexFile& dex_file, const SirtRef<mirror::DexCache>& dex_cache)
       EXCLUSIVE_LOCKS_REQUIRED(dex_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool IsDexFileRegisteredLocked(const DexFile& dex_file) const SHARED_LOCKS_REQUIRED(dex_lock_);
 
-  bool InitializeClass(mirror::Class* klass, bool can_run_clinit, bool can_init_parents)
+  bool InitializeClass(const SirtRef<mirror::Class>& klass, bool can_run_clinit,
+                       bool can_init_parents)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool WaitForInitializeClass(mirror::Class* klass, Thread* self, ObjectLock& lock);
-  bool ValidateSuperClassDescriptors(const mirror::Class* klass)
+  bool WaitForInitializeClass(const SirtRef<mirror::Class>& klass, Thread* self,
+                              ObjectLock<mirror::Class>& lock);
+  bool ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsSameDescriptorInDifferentClassContexts(const char* descriptor,
-                                                const mirror::Class* klass1,
-                                                const mirror::Class* klass2)
+                                                SirtRef<mirror::ClassLoader>& class_loader1,
+                                                SirtRef<mirror::ClassLoader>& class_loader2)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsSameMethodSignatureInDifferentClassContexts(const mirror::ArtMethod* method,
@@ -449,40 +455,40 @@
                                                      const mirror::Class* klass2)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool LinkClass(Thread* self, SirtRef<mirror::Class>& klass,
-                 SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
+  bool LinkClass(Thread* self, const SirtRef<mirror::Class>& klass,
+                 const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool LinkSuperClass(SirtRef<mirror::Class>& klass)
+  bool LinkSuperClass(const SirtRef<mirror::Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool LoadSuperAndInterfaces(SirtRef<mirror::Class>& klass, const DexFile& dex_file)
+  bool LoadSuperAndInterfaces(const SirtRef<mirror::Class>& klass, const DexFile& dex_file)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool LinkMethods(SirtRef<mirror::Class>& klass,
-                   SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
+  bool LinkMethods(const SirtRef<mirror::Class>& klass,
+                   const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool LinkVirtualMethods(SirtRef<mirror::Class>& klass)
+  bool LinkVirtualMethods(const SirtRef<mirror::Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
-                            SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
+  bool LinkInterfaceMethods(const SirtRef<mirror::Class>& klass,
+                            const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool LinkStaticFields(SirtRef<mirror::Class>& klass)
+  bool LinkStaticFields(const SirtRef<mirror::Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool LinkInstanceFields(SirtRef<mirror::Class>& klass)
+  bool LinkInstanceFields(const SirtRef<mirror::Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool LinkFields(SirtRef<mirror::Class>& klass, bool is_static)
+  bool LinkFields(const SirtRef<mirror::Class>& klass, bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 
-  void CreateReferenceInstanceOffsets(SirtRef<mirror::Class>& klass)
+  void CreateReferenceInstanceOffsets(const SirtRef<mirror::Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void CreateReferenceStaticOffsets(SirtRef<mirror::Class>& klass)
+  void CreateReferenceStaticOffsets(const SirtRef<mirror::Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void CreateReferenceOffsets(SirtRef<mirror::Class>& klass, bool is_static,
+  void CreateReferenceOffsets(const SirtRef<mirror::Class>& klass, bool is_static,
                               uint32_t reference_offsets)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -511,11 +517,11 @@
                                                  bool* open_failed)
       LOCKS_EXCLUDED(dex_lock_);
 
-  mirror::ArtMethod* CreateProxyConstructor(Thread* self, SirtRef<mirror::Class>& klass,
+  mirror::ArtMethod* CreateProxyConstructor(Thread* self, const SirtRef<mirror::Class>& klass,
                                             mirror::Class* proxy_class)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  mirror::ArtMethod* CreateProxyMethod(Thread* self, SirtRef<mirror::Class>& klass,
-                                       SirtRef<mirror::ArtMethod>& prototype)
+  mirror::ArtMethod* CreateProxyMethod(Thread* self, const SirtRef<mirror::Class>& klass,
+                                       const SirtRef<mirror::ArtMethod>& prototype)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   std::vector<const DexFile*> boot_class_path_;
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index b8bc474..34134fa 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -95,8 +95,10 @@
                         const std::string& component_type,
                         mirror::ClassLoader* class_loader)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    SirtRef<mirror::ClassLoader> loader(Thread::Current(), class_loader);
-    mirror::Class* array = class_linker_->FindClass(array_descriptor.c_str(), loader);
+    Thread* self = Thread::Current();
+    SirtRef<mirror::ClassLoader> loader(self, class_loader);
+    SirtRef<mirror::Class> array(self,
+                                 class_linker_->FindClass(array_descriptor.c_str(), loader));
     ClassHelper array_component_ch(array->GetComponentType());
     EXPECT_STREQ(component_type.c_str(), array_component_ch.GetDescriptor());
     EXPECT_EQ(class_loader, array->GetClassLoader());
@@ -104,10 +106,10 @@
     AssertArrayClass(array_descriptor, array);
   }
 
-  void AssertArrayClass(const std::string& array_descriptor, mirror::Class* array)
+  void AssertArrayClass(const std::string& array_descriptor, const SirtRef<mirror::Class>& array)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    ClassHelper kh(array);
-    ASSERT_TRUE(array != NULL);
+    ClassHelper kh(array.get());
+    ASSERT_TRUE(array.get() != NULL);
     ASSERT_TRUE(array->GetClass() != NULL);
     ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass());
     EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL);
@@ -135,15 +137,14 @@
     EXPECT_EQ(0U, array->NumVirtualMethods());
     EXPECT_EQ(0U, array->NumInstanceFields());
     EXPECT_EQ(0U, array->NumStaticFields());
-    kh.ChangeClass(array);
+    kh.ChangeClass(array.get());
     EXPECT_EQ(2U, kh.NumDirectInterfaces());
     EXPECT_TRUE(array->GetVTable() != NULL);
     EXPECT_EQ(2, array->GetIfTableCount());
-    mirror::IfTable* iftable = array->GetIfTable();
-    ASSERT_TRUE(iftable != NULL);
+    ASSERT_TRUE(array->GetIfTable() != NULL);
     kh.ChangeClass(kh.GetDirectInterface(0));
     EXPECT_STREQ(kh.GetDescriptor(), "Ljava/lang/Cloneable;");
-    kh.ChangeClass(array);
+    kh.ChangeClass(array.get());
     kh.ChangeClass(kh.GetDirectInterface(1));
     EXPECT_STREQ(kh.GetDescriptor(), "Ljava/io/Serializable;");
   }
@@ -179,9 +180,9 @@
     EXPECT_TRUE(fh.GetType() != NULL);
   }
 
-  void AssertClass(const std::string& descriptor, mirror::Class* klass)
+  void AssertClass(const std::string& descriptor, const SirtRef<mirror::Class>& klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    ClassHelper kh(klass);
+    ClassHelper kh(klass.get());
     EXPECT_STREQ(descriptor.c_str(), kh.GetDescriptor());
     if (descriptor == "Ljava/lang/Object;") {
       EXPECT_FALSE(klass->HasSuperClass());
@@ -197,7 +198,7 @@
     EXPECT_FALSE(klass->IsErroneous());
     EXPECT_FALSE(klass->IsArrayClass());
     EXPECT_TRUE(klass->GetComponentType() == NULL);
-    EXPECT_TRUE(klass->IsInSamePackage(klass));
+    EXPECT_TRUE(klass->IsInSamePackage(klass.get()));
     EXPECT_TRUE(mirror::Class::IsInSamePackage(kh.GetDescriptor(), kh.GetDescriptor()));
     if (klass->IsInterface()) {
       EXPECT_TRUE(klass->IsAbstract());
@@ -239,31 +240,31 @@
     }
 
     EXPECT_FALSE(klass->IsPrimitive());
-    EXPECT_TRUE(klass->CanAccess(klass));
+    EXPECT_TRUE(klass->CanAccess(klass.get()));
 
     for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
       mirror::ArtMethod* method = klass->GetDirectMethod(i);
       AssertMethod(method);
       EXPECT_TRUE(method->IsDirect());
-      EXPECT_EQ(klass, method->GetDeclaringClass());
+      EXPECT_EQ(klass.get(), method->GetDeclaringClass());
     }
 
     for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
       mirror::ArtMethod* method = klass->GetVirtualMethod(i);
       AssertMethod(method);
       EXPECT_FALSE(method->IsDirect());
-      EXPECT_TRUE(method->GetDeclaringClass()->IsAssignableFrom(klass));
+      EXPECT_TRUE(method->GetDeclaringClass()->IsAssignableFrom(klass.get()));
     }
 
     for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
       mirror::ArtField* field = klass->GetInstanceField(i);
-      AssertField(klass, field);
+      AssertField(klass.get(), field);
       EXPECT_FALSE(field->IsStatic());
     }
 
     for (size_t i = 0; i < klass->NumStaticFields(); i++) {
       mirror::ArtField* field = klass->GetStaticField(i);
-      AssertField(klass, field);
+      AssertField(klass.get(), field);
       EXPECT_TRUE(field->IsStatic());
     }
 
@@ -291,24 +292,24 @@
     }
 
     size_t total_num_reference_instance_fields = 0;
-    mirror::Class* k = klass;
+    mirror::Class* k = klass.get();
     while (k != NULL) {
       total_num_reference_instance_fields += k->NumReferenceInstanceFields();
       k = k->GetSuperClass();
     }
-    EXPECT_EQ(klass->GetReferenceInstanceOffsets() == 0,
-              total_num_reference_instance_fields == 0);
+    EXPECT_EQ(klass->GetReferenceInstanceOffsets() == 0, total_num_reference_instance_fields == 0);
   }
 
   void AssertDexFileClass(mirror::ClassLoader* class_loader, const std::string& descriptor)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     ASSERT_TRUE(descriptor != NULL);
-    mirror::Class* klass = class_linker_->FindSystemClass(descriptor.c_str());
-    ASSERT_TRUE(klass != NULL);
-    EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass).GetDescriptor());
+    SirtRef<mirror::Class> klass(Thread::Current(),
+                                 class_linker_->FindSystemClass(descriptor.c_str()));
+    ASSERT_TRUE(klass.get() != nullptr);
+    EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass.get()).GetDescriptor());
     EXPECT_EQ(class_loader, klass->GetClassLoader());
     if (klass->IsPrimitive()) {
-      AssertPrimitiveClass(descriptor, klass);
+      AssertPrimitiveClass(descriptor, klass.get());
     } else if (klass->IsArrayClass()) {
       AssertArrayClass(descriptor, klass);
     } else {
@@ -852,7 +853,7 @@
 TEST_F(ClassLinkerTest, StaticFields) {
   ScopedObjectAccess soa(Thread::Current());
   SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Statics")));
-  mirror::Class* statics = class_linker_->FindClass("LStatics;", class_loader);
+  SirtRef<mirror::Class> statics(soa.Self(), class_linker_->FindClass("LStatics;", class_loader));
   class_linker_->EnsureInitialized(statics, true, true);
 
   // Static final primitives that are initialized by a compile-time constant
@@ -867,68 +868,68 @@
   FieldHelper fh(s0);
   EXPECT_STREQ(ClassHelper(s0->GetClass()).GetDescriptor(), "Ljava/lang/reflect/ArtField;");
   EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimBoolean);
-  EXPECT_EQ(true, s0->GetBoolean(statics));
-  s0->SetBoolean(statics, false);
+  EXPECT_EQ(true, s0->GetBoolean(statics.get()));
+  s0->SetBoolean(statics.get(), false);
 
   mirror::ArtField* s1 = statics->FindStaticField("s1", "B");
   fh.ChangeField(s1);
   EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimByte);
-  EXPECT_EQ(5, s1->GetByte(statics));
-  s1->SetByte(statics, 6);
+  EXPECT_EQ(5, s1->GetByte(statics.get()));
+  s1->SetByte(statics.get(), 6);
 
   mirror::ArtField* s2 = statics->FindStaticField("s2", "C");
   fh.ChangeField(s2);
   EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimChar);
-  EXPECT_EQ('a', s2->GetChar(statics));
-  s2->SetChar(statics, 'b');
+  EXPECT_EQ('a', s2->GetChar(statics.get()));
+  s2->SetChar(statics.get(), 'b');
 
   mirror::ArtField* s3 = statics->FindStaticField("s3", "S");
   fh.ChangeField(s3);
   EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimShort);
-  EXPECT_EQ(-536, s3->GetShort(statics));
-  s3->SetShort(statics, -535);
+  EXPECT_EQ(-536, s3->GetShort(statics.get()));
+  s3->SetShort(statics.get(), -535);
 
   mirror::ArtField* s4 = statics->FindStaticField("s4", "I");
   fh.ChangeField(s4);
   EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimInt);
-  EXPECT_EQ(2000000000, s4->GetInt(statics));
-  s4->SetInt(statics, 2000000001);
+  EXPECT_EQ(2000000000, s4->GetInt(statics.get()));
+  s4->SetInt(statics.get(), 2000000001);
 
   mirror::ArtField* s5 = statics->FindStaticField("s5", "J");
   fh.ChangeField(s5);
   EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimLong);
-  EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(statics));
-  s5->SetLong(statics, 0x34567890abcdef12LL);
+  EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(statics.get()));
+  s5->SetLong(statics.get(), 0x34567890abcdef12LL);
 
   mirror::ArtField* s6 = statics->FindStaticField("s6", "F");
   fh.ChangeField(s6);
   EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimFloat);
-  EXPECT_EQ(0.5, s6->GetFloat(statics));
-  s6->SetFloat(statics, 0.75);
+  EXPECT_EQ(0.5, s6->GetFloat(statics.get()));
+  s6->SetFloat(statics.get(), 0.75);
 
   mirror::ArtField* s7 = statics->FindStaticField("s7", "D");
   fh.ChangeField(s7);
   EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimDouble);
-  EXPECT_EQ(16777217, s7->GetDouble(statics));
-  s7->SetDouble(statics, 16777219);
+  EXPECT_EQ(16777217, s7->GetDouble(statics.get()));
+  s7->SetDouble(statics.get(), 16777219);
 
   mirror::ArtField* s8 = statics->FindStaticField("s8", "Ljava/lang/String;");
   fh.ChangeField(s8);
   EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimNot);
-  EXPECT_TRUE(s8->GetObject(statics)->AsString()->Equals("android"));
+  EXPECT_TRUE(s8->GetObject(statics.get())->AsString()->Equals("android"));
   s8->SetObject(s8->GetDeclaringClass(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "robot"));
 
   // TODO: Remove EXPECT_FALSE when GCC can handle EXPECT_EQ
   // http://code.google.com/p/googletest/issues/detail?id=322
-  EXPECT_FALSE(s0->GetBoolean(statics));
-  EXPECT_EQ(6, s1->GetByte(statics));
-  EXPECT_EQ('b', s2->GetChar(statics));
-  EXPECT_EQ(-535, s3->GetShort(statics));
-  EXPECT_EQ(2000000001, s4->GetInt(statics));
-  EXPECT_EQ(0x34567890abcdef12LL, s5->GetLong(statics));
-  EXPECT_EQ(0.75, s6->GetFloat(statics));
-  EXPECT_EQ(16777219, s7->GetDouble(statics));
-  EXPECT_TRUE(s8->GetObject(statics)->AsString()->Equals("robot"));
+  EXPECT_FALSE(s0->GetBoolean(statics.get()));
+  EXPECT_EQ(6, s1->GetByte(statics.get()));
+  EXPECT_EQ('b', s2->GetChar(statics.get()));
+  EXPECT_EQ(-535, s3->GetShort(statics.get()));
+  EXPECT_EQ(2000000001, s4->GetInt(statics.get()));
+  EXPECT_EQ(0x34567890abcdef12LL, s5->GetLong(statics.get()));
+  EXPECT_EQ(0.75, s6->GetFloat(statics.get()));
+  EXPECT_EQ(16777219, s7->GetDouble(statics.get()));
+  EXPECT_TRUE(s8->GetObject(statics.get())->AsString()->Equals("robot"));
 }
 
 TEST_F(ClassLinkerTest, Interfaces) {
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 52a2141..0b572b0 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -2816,30 +2816,30 @@
   }
 
   // Translate the method through the vtable, unless the debugger wants to suppress it.
-  mirror::ArtMethod* m = pReq->method;
+  SirtRef<mirror::ArtMethod> m(soa.Self(), pReq->method);
   if ((pReq->options & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver != NULL) {
     mirror::ArtMethod* actual_method = pReq->klass->FindVirtualMethodForVirtualOrInterface(pReq->method);
-    if (actual_method != m) {
-      VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m) << " to " << PrettyMethod(actual_method);
-      m = actual_method;
+    if (actual_method != m.get()) {
+      VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m.get()) << " to " << PrettyMethod(actual_method);
+      m.reset(actual_method);
     }
   }
-  VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m)
+  VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m.get())
              << " receiver=" << pReq->receiver
              << " arg_count=" << pReq->arg_count;
-  CHECK(m != NULL);
+  CHECK(m.get() != nullptr);
 
   CHECK_EQ(sizeof(jvalue), sizeof(uint64_t));
 
-  MethodHelper mh(m);
+  MethodHelper mh(m.get());
   ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
   arg_array.BuildArgArray(soa, pReq->receiver, reinterpret_cast<jvalue*>(pReq->arg_values));
-  InvokeWithArgArray(soa, m, &arg_array, &pReq->result_value, mh.GetShorty()[0]);
+  InvokeWithArgArray(soa, m.get(), &arg_array, &pReq->result_value, mh.GetShorty()[0]);
 
   mirror::Throwable* exception = soa.Self()->GetException(NULL);
   soa.Self()->ClearException();
   pReq->exception = gRegistry->Add(exception);
-  pReq->result_tag = BasicTagFromDescriptor(MethodHelper(m).GetShorty());
+  pReq->result_tag = BasicTagFromDescriptor(MethodHelper(m.get()).GetShorty());
   if (pReq->exception != 0) {
     VLOG(jdwp) << "  JDWP invocation returning with exception=" << exception
         << " " << exception->Dump();
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 747dd56..bfdbd74 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -72,7 +72,7 @@
   if (UNLIKELY(!klass->IsInitialized())) {
     SirtRef<mirror::Class> sirt_klass(self, klass);
     // The class initializer might cause a GC.
-    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(klass, true, true)) {
+    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) {
       DCHECK(self->IsExceptionPending());
       return nullptr;  // Failure
     }
@@ -246,12 +246,15 @@
     // If the class is initialized we're done.
     if (LIKELY(fields_class->IsInitialized())) {
       return resolved_field;
-    } else if (LIKELY(class_linker->EnsureInitialized(fields_class, true, true))) {
-      // Otherwise let's ensure the class is initialized before resolving the field.
-      return resolved_field;
     } else {
-      DCHECK(self->IsExceptionPending());  // Throw exception and unwind
-      return nullptr;  // failure
+      SirtRef<mirror::Class> sirt_class(self, fields_class);
+      if (LIKELY(class_linker->EnsureInitialized(sirt_class, true, true))) {
+        // Otherwise let's ensure the class is initialized before resolving the field.
+        return resolved_field;
+      } else {
+        DCHECK(self->IsExceptionPending());  // Throw exception and unwind
+        return nullptr;  // failure
+      }
     }
   }
 }
@@ -535,12 +538,13 @@
   if (klass == referring_class && referrer->IsConstructor() && referrer->IsStatic()) {
     return klass;
   }
-  if (!class_linker->EnsureInitialized(klass, true, true)) {
+  SirtRef<mirror::Class> sirt_class(self, klass);
+  if (!class_linker->EnsureInitialized(sirt_class, true, true)) {
     CHECK(self->IsExceptionPending());
     return NULL;  // Failure - Indicate to caller to deliver exception
   }
-  referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
-  return klass;
+  referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, sirt_class.get());
+  return sirt_class.get();
 }
 
 extern void ThrowStackOverflowError(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index df4ec3a..0df00c2 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -34,14 +34,14 @@
     mirror::Class* declaringClass = method->GetDeclaringClass();
     if (UNLIKELY(!declaringClass->IsInitializing())) {
       self->PushShadowFrame(shadow_frame);
-      if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass,
-                                                                            true, true))) {
+      SirtRef<mirror::Class> sirt_c(self, declaringClass);
+      if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_c, true, true))) {
         self->PopShadowFrame();
         DCHECK(self->IsExceptionPending());
         return;
       }
       self->PopShadowFrame();
-      CHECK(declaringClass->IsInitializing());
+      CHECK(sirt_c->IsInitializing());
     }
   }
   uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_;
diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
index 61f7440..2162dcc 100644
--- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
@@ -208,8 +208,8 @@
 
     if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
       // Ensure static method's class is initialized.
-      if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
-                                                                   true, true)) {
+      SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
+      if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_c, true, true)) {
         DCHECK(Thread::Current()->IsExceptionPending());
         self->PopManagedStackFragment(fragment);
         return 0;
@@ -390,7 +390,7 @@
   const void* code = NULL;
   if (LIKELY(!thread->IsExceptionPending())) {
     // Ensure that the called method's class is initialized.
-    mirror::Class* called_class = called->GetDeclaringClass();
+    SirtRef<mirror::Class> called_class(thread, called->GetDeclaringClass());
     linker->EnsureInitialized(called_class, true, true);
     if (LIKELY(called_class->IsInitialized())) {
       code = called->GetEntryPointFromCompiledCode();
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 8ba08ee..b589384 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -298,8 +298,8 @@
 
     if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
       // Ensure static method's class is initialized.
-      if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
-                                                                   true, true)) {
+      SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
+      if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_c, true, true)) {
         DCHECK(Thread::Current()->IsExceptionPending());
         self->PopManagedStackFragment(fragment);
         return 0;
@@ -564,7 +564,7 @@
       }
     }
     // Ensure that the called method's class is initialized.
-    mirror::Class* called_class = called->GetDeclaringClass();
+    SirtRef<mirror::Class> called_class(soa.Self(), called->GetDeclaringClass());
     linker->EnsureInitialized(called_class, true, true);
     if (LIKELY(called_class->IsInitialized())) {
       code = called->GetEntryPointFromCompiledCode();
diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc
index 8f542d8..978faeb 100644
--- a/runtime/exception_test.cc
+++ b/runtime/exception_test.cc
@@ -37,11 +37,13 @@
     CommonTest::SetUp();
 
     ScopedObjectAccess soa(Thread::Current());
-    SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
-                                      soa.Decode<mirror::ClassLoader*>(LoadDex("ExceptionHandle")));
+    SirtRef<mirror::ClassLoader> class_loader(
+        soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("ExceptionHandle")));
     my_klass_ = class_linker_->FindClass("LExceptionHandle;", class_loader);
     ASSERT_TRUE(my_klass_ != NULL);
-    class_linker_->EnsureInitialized(my_klass_, true, true);
+    SirtRef<mirror::Class> sirt_klass(soa.Self(), my_klass_);
+    class_linker_->EnsureInitialized(sirt_klass, true, true);
+    my_klass_ = sirt_klass.get();
 
     dex_ = my_klass_->GetDexCache()->GetDexFile();
 
diff --git a/runtime/gc/accounting/card_table.cc b/runtime/gc/accounting/card_table.cc
index 7818bc8..e099137 100644
--- a/runtime/gc/accounting/card_table.cc
+++ b/runtime/gc/accounting/card_table.cc
@@ -95,8 +95,8 @@
 }
 
 void CardTable::ClearCardTable() {
-  // TODO: clear just the range of the table that has been modified
-  memset(mem_map_->Begin(), kCardClean, mem_map_->Size());
+  COMPILE_ASSERT(kCardClean == 0, clean_card_must_be_0);
+  madvise(mem_map_->Begin(), mem_map_->Size(), MADV_DONTNEED);
 }
 
 bool CardTable::AddrIsInCardTable(const void* addr) const {
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index faa198a..b428e74 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -82,7 +82,7 @@
     if (ref != nullptr) {
       Object* new_ref = visitor_(ref, arg_);
       if (new_ref != ref) {
-        obj->SetFieldObject(offset, new_ref, true);
+        obj->SetFieldPtr(offset, new_ref, true);
       }
     }
   }
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index 7a51553..9c1c5dc 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -69,15 +69,14 @@
   DCHECK(obj->GetClass() != NULL);
   mirror::Class* klass = obj->GetClass();
   DCHECK(klass != NULL);
-  if (visit_class) {
-    visitor(obj, klass, mirror::Object::ClassOffset(), false);
-  }
   if (klass == mirror::Class::GetJavaLangClass()) {
     DCHECK_EQ(klass->GetClass(), mirror::Class::GetJavaLangClass());
     VisitClassReferences(klass, obj, visitor);
   } else {
     if (klass->IsArrayClass()) {
-      visitor(obj, klass, mirror::Object::ClassOffset(), false);
+      if (visit_class) {
+        visitor(obj, klass, mirror::Object::ClassOffset(), false);
+      }
       if (klass->IsObjectArrayClass()) {
         VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object>(), visitor);
       }
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 53d85b0..62991bb 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -89,10 +89,12 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void MarkNonThreadRoots()
-      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void MarkConcurrentRoots();
-      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+  void MarkConcurrentRoots()
+      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void MarkRootsCheckpoint(Thread* self)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index 3939354..63e0cfa 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -173,6 +173,10 @@
   BindBitmaps();
   // Process dirty cards and add dirty cards to mod-union tables.
   heap_->ProcessCards(timings_);
+  // Clear the whole card table since we can not get any additional dirty cards during the
+  // paused GC. This saves memory but only works for pause the world collectors.
+  timings_.NewSplit("ClearCardTable");
+  heap_->GetCardTable()->ClearCardTable();
   // Need to do this before the checkpoint since we don't want any threads to add references to
   // the live stack during the recursive mark.
   timings_.NewSplit("SwapStacks");
@@ -318,8 +322,6 @@
         memcpy(reinterpret_cast<void*>(forward_address), obj, object_size);
         // Make sure to only update the forwarding address AFTER you copy the object so that the
         // monitor word doesn't get stomped over.
-        COMPILE_ASSERT(sizeof(uint32_t) == sizeof(mirror::Object*),
-                       monitor_size_must_be_same_as_object);
         obj->SetLockWord(LockWord::FromForwardingAddress(reinterpret_cast<size_t>(forward_address)));
         MarkStackPush(forward_address);
       }
@@ -508,7 +510,10 @@
     mirror::Object* new_address = MarkObject(ref);
     if (new_address != ref) {
       DCHECK(new_address != nullptr);
-      obj->SetFieldObject(offset, new_address, false);
+      // Don't need to mark the card since we updating the object address and not changing the
+      // actual objects its pointing to. Using SetFieldPtr is better in this case since it does not
+      // dirty cards and use additional memory.
+      obj->SetFieldPtr(offset, new_address, false);
     }
   }, kMovingClasses);
   mirror::Class* klass = obj->GetClass();
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index 08ab6b8..99f084a 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -41,24 +41,20 @@
   // done in the runnable state where suspension is expected.
   DCHECK_EQ(self->GetState(), kRunnable);
   self->AssertThreadSuspensionIsAllowable();
+  // Need to check that we arent the large object allocator since the large object allocation code
+  // path this function. If we didn't check we would have an infinite loop.
+  if (allocator != kAllocatorTypeLOS && UNLIKELY(ShouldAllocLargeObject(klass, byte_count))) {
+    return AllocLargeObject<kInstrumented, PreFenceVisitor>(self, klass, byte_count,
+                                                            pre_fence_visitor);
+  }
   mirror::Object* obj;
   size_t bytes_allocated;
   AllocationTimer alloc_timer(this, &obj);
-  if (UNLIKELY(ShouldAllocLargeObject(klass, byte_count))) {
-    obj = TryToAllocate<kInstrumented>(self, kAllocatorTypeLOS, byte_count, false,
-                                       &bytes_allocated);
-    allocator = kAllocatorTypeLOS;
-  } else {
-    obj = TryToAllocate<kInstrumented>(self, allocator, byte_count, false, &bytes_allocated);
-  }
-
+  obj = TryToAllocate<kInstrumented, false>(self, allocator, byte_count, &bytes_allocated);
   if (UNLIKELY(obj == nullptr)) {
-    SirtRef<mirror::Class> sirt_c(self, klass);
-    obj = AllocateInternalWithGc(self, allocator, byte_count, &bytes_allocated);
+    obj = AllocateInternalWithGc(self, allocator, byte_count, &bytes_allocated, &klass);
     if (obj == nullptr) {
       return nullptr;
-    } else {
-      klass = sirt_c.get();
     }
   }
   obj->SetClass(klass);
@@ -105,11 +101,19 @@
   return obj;
 }
 
-template <const bool kInstrumented>
+template <bool kInstrumented, typename PreFenceVisitor>
+inline mirror::Object* Heap::AllocLargeObject(Thread* self, mirror::Class* klass,
+                                              size_t byte_count,
+                                              const PreFenceVisitor& pre_fence_visitor) {
+  return AllocObjectWithAllocator<kInstrumented, PreFenceVisitor>(self, klass, byte_count,
+                                                                  kAllocatorTypeLOS,
+                                                                  pre_fence_visitor);
+}
+
+template <const bool kInstrumented, const bool kGrow>
 inline mirror::Object* Heap::TryToAllocate(Thread* self, AllocatorType allocator_type,
-                                           size_t alloc_size, bool grow,
-                                           size_t* bytes_allocated) {
-  if (UNLIKELY(IsOutOfMemoryOnAllocation(alloc_size, grow))) {
+                                           size_t alloc_size, size_t* bytes_allocated) {
+  if (UNLIKELY(IsOutOfMemoryOnAllocation<kGrow>(alloc_size))) {
     return nullptr;
   }
   if (kInstrumented) {
@@ -190,14 +194,15 @@
   return byte_count >= kLargeObjectThreshold && have_zygote_space_ && c->IsPrimitiveArray();
 }
 
-inline bool Heap::IsOutOfMemoryOnAllocation(size_t alloc_size, bool grow) {
+template <const bool kGrow>
+inline bool Heap::IsOutOfMemoryOnAllocation(size_t alloc_size) {
   size_t new_footprint = num_bytes_allocated_ + alloc_size;
   if (UNLIKELY(new_footprint > max_allowed_footprint_)) {
     if (UNLIKELY(new_footprint > growth_limit_)) {
       return true;
     }
     if (!concurrent_gc_) {
-      if (!grow) {
+      if (!kGrow) {
         return true;
       }
       // TODO: Grow for allocation is racy, fix it.
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index f92a821..11acd33 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -881,14 +881,17 @@
 }
 
 mirror::Object* Heap::AllocateInternalWithGc(Thread* self, AllocatorType allocator,
-                                             size_t alloc_size, size_t* bytes_allocated) {
+                                             size_t alloc_size, size_t* bytes_allocated,
+                                             mirror::Class** klass) {
   mirror::Object* ptr = nullptr;
+  DCHECK(klass != nullptr);
+  SirtRef<mirror::Class> sirt_klass(self, *klass);
   // The allocation failed. If the GC is running, block until it completes, and then retry the
   // allocation.
   collector::GcType last_gc = WaitForGcToComplete(self);
   if (last_gc != collector::kGcTypeNone) {
     // A GC was in progress and we blocked, retry allocation now that memory has been freed.
-    ptr = TryToAllocate<true>(self, allocator, alloc_size, false, bytes_allocated);
+    ptr = TryToAllocate<true, false>(self, allocator, alloc_size, bytes_allocated);
   }
 
   // Loop through our different Gc types and try to Gc until we get enough free memory.
@@ -899,13 +902,13 @@
     // Attempt to run the collector, if we succeed, re-try the allocation.
     if (CollectGarbageInternal(gc_type, kGcCauseForAlloc, false) != collector::kGcTypeNone) {
       // Did we free sufficient memory for the allocation to succeed?
-      ptr = TryToAllocate<true>(self, allocator, alloc_size, false, bytes_allocated);
+      ptr = TryToAllocate<true, false>(self, allocator, alloc_size, bytes_allocated);
     }
   }
   // Allocations have failed after GCs;  this is an exceptional state.
   if (ptr == nullptr) {
     // Try harder, growing the heap if necessary.
-    ptr = TryToAllocate<true>(self, allocator, alloc_size, true, bytes_allocated);
+    ptr = TryToAllocate<true, true>(self, allocator, alloc_size, bytes_allocated);
   }
   if (ptr == nullptr) {
     // Most allocations should have succeeded by now, so the heap is really full, really fragmented,
@@ -918,11 +921,12 @@
     // We don't need a WaitForGcToComplete here either.
     DCHECK(!gc_plan_.empty());
     CollectGarbageInternal(gc_plan_.back(), kGcCauseForAlloc, true);
-    ptr = TryToAllocate<true>(self, allocator, alloc_size, true, bytes_allocated);
+    ptr = TryToAllocate<true, true>(self, allocator, alloc_size, bytes_allocated);
     if (ptr == nullptr) {
       ThrowOutOfMemoryError(self, alloc_size, false);
     }
   }
+  *klass = sirt_klass.get();
   return ptr;
 }
 
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 3bff3f9..9788064 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -126,11 +126,6 @@
   kProcessStateJankImperceptible = 1,
 };
 
-// If true, measure the total allocation time.
-static constexpr bool kMeasureAllocationTime = false;
-// Primitive arrays larger than this size are put in the large object space.
-static constexpr size_t kLargeObjectThreshold = 3 * kPageSize;
-
 class Heap {
  public:
   // If true, measure the total allocation time.
@@ -522,10 +517,16 @@
   ALWAYS_INLINE void CheckConcurrentGC(Thread* self, size_t new_num_bytes_allocated,
                                        mirror::Object* obj);
 
+  // We don't force this to be inline since it is a slow path.
+  template <bool kInstrumented, typename PreFenceVisitor>
+  mirror::Object* AllocLargeObject(Thread* self, mirror::Class* klass, size_t byte_count,
+                                   const PreFenceVisitor& pre_fence_visitor)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // Handles Allocate()'s slow allocation path with GC involved after
   // an initial allocation attempt failed.
   mirror::Object* AllocateInternalWithGc(Thread* self, AllocatorType allocator, size_t num_bytes,
-                                         size_t* bytes_allocated)
+                                         size_t* bytes_allocated, mirror::Class** klass)
       LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -536,15 +537,15 @@
 
   // Try to allocate a number of bytes, this function never does any GCs. Needs to be inlined so
   // that the switch statement is constant optimized in the entrypoints.
-  template <const bool kInstrumented>
+  template <const bool kInstrumented, const bool kGrow>
   ALWAYS_INLINE mirror::Object* TryToAllocate(Thread* self, AllocatorType allocator_type,
-                                              size_t alloc_size, bool grow,
-                                              size_t* bytes_allocated)
+                                              size_t alloc_size, size_t* bytes_allocated)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void ThrowOutOfMemoryError(Thread* self, size_t byte_count, bool large_object_allocation)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool IsOutOfMemoryOnAllocation(size_t alloc_size, bool grow);
+  template <const bool kGrow>
+  bool IsOutOfMemoryOnAllocation(size_t alloc_size);
 
   // Pushes a list of cleared references out to the managed heap.
   void SetReferenceReferent(mirror::Object* reference, mirror::Object* referent)
diff --git a/runtime/globals.h b/runtime/globals.h
index c2fe67e..a0d7e48 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -82,7 +82,7 @@
 // Garbage collector constants.
 static constexpr bool kMovingCollector = true && !kUsePortableCompiler;
 // True if we allow moving classes.
-static constexpr bool kMovingClasses = false;
+static constexpr bool kMovingClasses = true;
 // True if we allow moving fields.
 static constexpr bool kMovingFields = false;
 // True if we allow moving methods.
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 9938478..02c9012 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -343,12 +343,13 @@
     ++cur_reg;
   } else if (UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    if (UNLIKELY(!class_linker->EnsureInitialized(method->GetDeclaringClass(), true, true))) {
+    SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
+    if (UNLIKELY(!class_linker->EnsureInitialized(sirt_c, true, true))) {
       CHECK(self->IsExceptionPending());
       self->PopShadowFrame();
       return;
     }
-    CHECK(method->GetDeclaringClass()->IsInitializing());
+    CHECK(sirt_c->IsInitializing());
   }
   const char* shorty = mh.GetShorty();
   for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
@@ -428,7 +429,7 @@
   ArtMethod* method = shadow_frame->GetMethod();
   // Ensure static methods are initialized.
   if (method->IsStatic()) {
-    Class* declaringClass = method->GetDeclaringClass();
+    SirtRef<Class> declaringClass(self, method->GetDeclaringClass());
     if (UNLIKELY(!declaringClass->IsInitializing())) {
       if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass, true,
                                                                             true))) {
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 0bc834c..3b8d50b 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -334,13 +334,14 @@
 // java.lang.String class is initialized.
 static inline String* ResolveString(Thread* self, MethodHelper& mh, uint32_t string_idx)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  CHECK(!kMovingMethods);
   Class* java_lang_string_class = String::GetJavaLangString();
   if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    if (UNLIKELY(!class_linker->EnsureInitialized(java_lang_string_class,
-                                                  true, true))) {
+    SirtRef<mirror::Class> sirt_class(self, java_lang_string_class);
+    if (UNLIKELY(!class_linker->EnsureInitialized(sirt_class, true, true))) {
       DCHECK(self->IsExceptionPending());
-      return NULL;
+      return nullptr;
     }
   }
   return mh.ResolveString(string_idx);
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 466edeb..3300279 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -225,13 +225,24 @@
                                  kind, ClassHelper(c).GetDescriptor(), name, sig);
 }
 
+static mirror::Class* EnsureInitialized(Thread* self, mirror::Class* klass)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  if (LIKELY(klass->IsInitialized())) {
+    return klass;
+  }
+  SirtRef<mirror::Class> sirt_klass(self, klass);
+  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) {
+    return nullptr;
+  }
+  return sirt_klass.get();
+}
+
 static jmethodID FindMethodID(ScopedObjectAccess& soa, jclass jni_class,
                               const char* name, const char* sig, bool is_static)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Class* c = soa.Decode<Class*>(jni_class);
-  DCHECK(c != nullptr);
-  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
-    return NULL;
+  Class* c = EnsureInitialized(soa.Self(), soa.Decode<Class*>(jni_class));
+  if (c == nullptr) {
+    return nullptr;
   }
 
   ArtMethod* method = NULL;
@@ -284,9 +295,9 @@
 static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, const char* name,
                             const char* sig, bool is_static)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Class* c = soa.Decode<Class*>(jni_class);
-  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
-    return NULL;
+  Class* c = EnsureInitialized(soa.Self(), soa.Decode<Class*>(jni_class));
+  if (c == nullptr) {
+    return nullptr;
   }
 
   ArtField* field = NULL;
@@ -910,9 +921,9 @@
   static jobject AllocObject(JNIEnv* env, jclass java_class) {
     CHECK_NON_NULL_ARGUMENT(AllocObject, java_class);
     ScopedObjectAccess soa(env);
-    Class* c = soa.Decode<Class*>(java_class);
-    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
-      return NULL;
+    Class* c = EnsureInitialized(soa.Self(), soa.Decode<Class*>(java_class));
+    if (c == nullptr) {
+      return nullptr;
     }
     return soa.AddLocalReference<jobject>(c->AllocObject(soa.Self()));
   }
@@ -931,20 +942,20 @@
     CHECK_NON_NULL_ARGUMENT(NewObjectV, java_class);
     CHECK_NON_NULL_ARGUMENT(NewObjectV, mid);
     ScopedObjectAccess soa(env);
-    Class* c = soa.Decode<Class*>(java_class);
-    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
-      return NULL;
+    Class* c = EnsureInitialized(soa.Self(), soa.Decode<Class*>(java_class));
+    if (c == nullptr) {
+      return nullptr;
     }
     Object* result = c->AllocObject(soa.Self());
-    if (result == NULL) {
-      return NULL;
+    if (result == nullptr) {
+      return nullptr;
     }
     jobject local_result = soa.AddLocalReference<jobject>(result);
     CallNonvirtualVoidMethodV(env, local_result, java_class, mid, args);
     if (!soa.Self()->IsExceptionPending()) {
       return local_result;
     } else {
-      return NULL;
+      return nullptr;
     }
   }
 
@@ -952,9 +963,9 @@
     CHECK_NON_NULL_ARGUMENT(NewObjectA, java_class);
     CHECK_NON_NULL_ARGUMENT(NewObjectA, mid);
     ScopedObjectAccess soa(env);
-    Class* c = soa.Decode<Class*>(java_class);
-    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
-      return NULL;
+    Class* c = EnsureInitialized(soa.Self(), soa.Decode<Class*>(java_class));
+    if (c == nullptr) {
+      return nullptr;
     }
     Object* result = c->AllocObject(soa.Self());
     if (result == NULL) {
@@ -3303,8 +3314,9 @@
   // If this is a static method, it could be called before the class
   // has been initialized.
   if (m->IsStatic()) {
-    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
-      return NULL;
+    c = EnsureInitialized(Thread::Current(), c);
+    if (c == nullptr) {
+      return nullptr;
     }
   } else {
     CHECK(c->IsInitializing()) << c->GetStatus() << " " << PrettyMethod(m);
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index a754b69..cf4b48c 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -108,6 +108,13 @@
                Runtime::Current()->GetHeap()->GetCurrentAllocator());
 }
 
+template<class T>
+inline void PrimitiveArray<T>::VisitRoots(RootVisitor* visitor, void* arg) {
+  if (array_class_ != nullptr) {
+    array_class_ = down_cast<Class*>(visitor(array_class_, arg));
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index a332f97..5265946 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -149,6 +149,9 @@
     array_class_ = NULL;
   }
 
+  static void VisitRoots(RootVisitor* visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  private:
   static Class* array_class_;
 
diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc
index a8bbe4b..c3a4efb 100644
--- a/runtime/mirror/art_field.cc
+++ b/runtime/mirror/art_field.cc
@@ -52,5 +52,12 @@
   SetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_), num_bytes.Uint32Value(), false);
 }
 
+void ArtField::VisitRoots(RootVisitor* visitor, void* arg) {
+  if (java_lang_reflect_ArtField_ != nullptr) {
+    java_lang_reflect_ArtField_ = down_cast<mirror::Class*>(
+        visitor(java_lang_reflect_ArtField_, arg));
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
index ae34cb1..62bcf06 100644
--- a/runtime/mirror/art_field.h
+++ b/runtime/mirror/art_field.h
@@ -130,6 +130,8 @@
 
   static void SetClass(Class* java_lang_reflect_ArtField);
   static void ResetClass();
+  static void VisitRoots(RootVisitor* visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsVolatile() const {
     return (GetAccessFlags() & kAccVolatile) != 0;
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index f5c0e9f..a4f6b3b 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -40,6 +40,13 @@
 // TODO: get global references for these
 Class* ArtMethod::java_lang_reflect_ArtMethod_ = NULL;
 
+void ArtMethod::VisitRoots(RootVisitor* visitor, void* arg) {
+  if (java_lang_reflect_ArtMethod_ != nullptr) {
+    java_lang_reflect_ArtMethod_ = down_cast<mirror::Class*>(
+        visitor(java_lang_reflect_ArtMethod_, arg));
+  }
+}
+
 InvokeType ArtMethod::GetInvokeType() const {
   // TODO: kSuper?
   if (GetDeclaringClass()->IsInterface()) {
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index f396fbe..d5524ec 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -23,6 +23,7 @@
 #include "locks.h"
 #include "modifiers.h"
 #include "object.h"
+#include "root_visitor.h"
 
 namespace art {
 
@@ -381,6 +382,9 @@
 
   static void ResetClass();
 
+  static void VisitRoots(RootVisitor* visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  protected:
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   // The class we are a part of
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index cdc5ab2..2746e1e 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -50,6 +50,12 @@
   java_lang_Class_ = NULL;
 }
 
+void Class::VisitRoots(RootVisitor* visitor, void* arg) {
+  if (java_lang_Class_ != nullptr) {
+    java_lang_Class_ = down_cast<Class*>(visitor(java_lang_Class_, arg));
+  }
+}
+
 void Class::SetStatus(Status new_status, Thread* self) {
   Status old_status = GetStatus();
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 5f64bb4..50ede66 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -787,6 +787,8 @@
   // Can't call this SetClass or else gets called instead of Object::SetClass in places.
   static void SetClassClass(Class* java_lang_Class);
   static void ResetClass();
+  static void VisitRoots(RootVisitor* visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // When class is verified, set the kAccPreverified flag on each method.
   void SetPreverifiedFlagOnAllMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 0fb2039..fe89b7e 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -225,6 +225,11 @@
 
   void SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile);
 
+  template<typename T>
+  void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile, bool this_is_valid = true) {
+    SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
+  }
+
  protected:
   // Accessors for non-Java type fields
   template<class T>
@@ -232,11 +237,6 @@
     return reinterpret_cast<T>(GetField32(field_offset, is_volatile));
   }
 
-  template<typename T>
-  void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile, bool this_is_valid = true) {
-    SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
-  }
-
  private:
   static void VerifyObject(const Object* obj) ALWAYS_INLINE;
   // Verify the type correctness of stores to fields.
diff --git a/runtime/mirror/stack_trace_element.cc b/runtime/mirror/stack_trace_element.cc
index 32a50fe..a7ebe07 100644
--- a/runtime/mirror/stack_trace_element.cc
+++ b/runtime/mirror/stack_trace_element.cc
@@ -58,5 +58,12 @@
   return trace;
 }
 
+void StackTraceElement::VisitRoots(RootVisitor* visitor, void* arg) {
+  if (java_lang_StackTraceElement_ != nullptr) {
+    java_lang_StackTraceElement_ = down_cast<Class*>(visitor(java_lang_StackTraceElement_, arg));
+  }
+}
+
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h
index 2af5128..d1be4dc 100644
--- a/runtime/mirror/stack_trace_element.h
+++ b/runtime/mirror/stack_trace_element.h
@@ -57,8 +57,9 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void SetClass(Class* java_lang_StackTraceElement);
-
   static void ResetClass();
+  static void VisitRoots(RootVisitor* visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index b372fe7..d6e509d 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -122,7 +122,7 @@
                                const uint16_t* utf16_data_in,
                                int32_t hash_code) {
   CHECK(utf16_data_in != NULL || utf16_length == 0);
-  String* string = Alloc(self, GetJavaLangString(), utf16_length);
+  String* string = Alloc(self, utf16_length);
   if (UNLIKELY(string == nullptr)) {
     return nullptr;
   }
@@ -152,7 +152,7 @@
 
 String* String::AllocFromModifiedUtf8(Thread* self, int32_t utf16_length,
                                       const char* utf8_data_in) {
-  String* string = Alloc(self, GetJavaLangString(), utf16_length);
+  String* string = Alloc(self, utf16_length);
   if (UNLIKELY(string == nullptr)) {
     return nullptr;
   }
@@ -163,21 +163,20 @@
   return string;
 }
 
-String* String::Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length) {
-  CharArray* array = CharArray::Alloc(self, utf16_length);
-  if (UNLIKELY(array == nullptr)) {
+String* String::Alloc(Thread* self, int32_t utf16_length) {
+  SirtRef<CharArray> array(self, CharArray::Alloc(self, utf16_length));
+  if (UNLIKELY(array.get() == nullptr)) {
     return nullptr;
   }
-  return Alloc(self, java_lang_String, array);
+  return Alloc(self, array);
 }
 
-String* String::Alloc(Thread* self, Class* java_lang_String, CharArray* array) {
+String* String::Alloc(Thread* self, const SirtRef<CharArray>& array) {
   // Hold reference in case AllocObject causes GC.
-  SirtRef<CharArray> array_ref(self, array);
-  String* string = down_cast<String*>(java_lang_String->AllocObject(self));
+  String* string = down_cast<String*>(GetJavaLangString()->AllocObject(self));
   if (LIKELY(string != nullptr)) {
-    string->SetArray(array_ref.get());
-    string->SetCount(array_ref->GetLength());
+    string->SetArray(array.get());
+    string->SetCount(array->GetLength());
   }
   return string;
 }
@@ -287,5 +286,11 @@
   return countDiff;
 }
 
+void String::VisitRoots(RootVisitor* visitor, void* arg) {
+  if (java_lang_String_ != nullptr) {
+    java_lang_String_ = down_cast<Class*>(visitor(java_lang_String_, arg));
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 7520c4d..4bbcb9c 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -19,6 +19,7 @@
 
 #include "class.h"
 #include "gtest/gtest.h"
+#include "root_visitor.h"
 
 namespace art {
 
@@ -77,12 +78,6 @@
                                        const char* utf8_data_in)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static String* Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  static String* Alloc(Thread* self, Class* java_lang_String, CharArray* array)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   bool Equals(const char* modified_utf8) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -114,6 +109,8 @@
 
   static void SetClass(Class* java_lang_String);
   static void ResetClass();
+  static void VisitRoots(RootVisitor* visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
   void SetHashCode(int32_t new_hash_code) {
@@ -132,6 +129,12 @@
     SetField32(OFFSET_OF_OBJECT_MEMBER(String, offset_), new_offset, false);
   }
 
+  static String* Alloc(Thread* self, int32_t utf16_length)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static String* Alloc(Thread* self, const SirtRef<CharArray>& array)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   void SetArray(CharArray* new_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index 961f6de..b55db72 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -93,5 +93,11 @@
   java_lang_Throwable_ = NULL;
 }
 
+void Throwable::VisitRoots(RootVisitor* visitor, void* arg) {
+  if (java_lang_Throwable_ != nullptr) {
+    java_lang_Throwable_ = down_cast<Class*>(visitor(java_lang_Throwable_, arg));
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h
index 27f6e12..5a90599 100644
--- a/runtime/mirror/throwable.h
+++ b/runtime/mirror/throwable.h
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_MIRROR_THROWABLE_H_
 
 #include "object.h"
+#include "root_visitor.h"
 #include "string.h"
 
 namespace art {
@@ -50,6 +51,8 @@
 
   static void SetClass(Class* java_lang_Throwable);
   static void ResetClass();
+  static void VisitRoots(RootVisitor* visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
   Object* GetStackState() const {
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 3389107..3e3f608 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -46,8 +46,8 @@
 static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize, jobject javaLoader) {
   ScopedObjectAccess soa(env);
   ScopedUtfChars name(env, javaName);
-  if (name.c_str() == NULL) {
-    return NULL;
+  if (name.c_str() == nullptr) {
+    return nullptr;
   }
 
   // We need to validate and convert the name (from x.y.z to x/y/z).  This
@@ -57,27 +57,27 @@
     ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
     soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ClassNotFoundException;",
                                    "Invalid name: %s", name.c_str());
-    return NULL;
+    return nullptr;
   }
 
   std::string descriptor(DotToDescriptor(name.c_str()));
   SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
                                             soa.Decode<mirror::ClassLoader*>(javaLoader));
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  mirror::Class* c = class_linker->FindClass(descriptor.c_str(), class_loader);
-  if (c == NULL) {
+  SirtRef<mirror::Class> c(soa.Self(), class_linker->FindClass(descriptor.c_str(), class_loader));
+  if (c.get() == nullptr) {
     ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
     env->ExceptionClear();
     jthrowable cnfe = reinterpret_cast<jthrowable>(env->NewObject(WellKnownClasses::java_lang_ClassNotFoundException,
                                                                   WellKnownClasses::java_lang_ClassNotFoundException_init,
                                                                   javaName, cause.get()));
     env->Throw(cnfe);
-    return NULL;
+    return nullptr;
   }
   if (initialize) {
     class_linker->EnsureInitialized(c, true, true);
   }
-  return soa.AddLocalReference<jclass>(c);
+  return soa.AddLocalReference<jclass>(c.get());
 }
 
 static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index 04dfcb5..5811992 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -41,24 +41,24 @@
       javaMethod, WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
 
   mirror::ArtMethod* m = soa.Decode<mirror::Object*>(art_method)->AsArtMethod();
-  mirror::Class* c = m->GetDeclaringClass();
+  SirtRef<mirror::Class> c(soa.Self(), m->GetDeclaringClass());
   if (UNLIKELY(c->IsAbstract())) {
     ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
     soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/InstantiationException;",
                                    "Can't instantiate %s %s",
                                    c->IsInterface() ? "interface" : "abstract class",
-                                   PrettyDescriptor(c).c_str());
-    return NULL;
+                                   PrettyDescriptor(c.get()).c_str());
+    return nullptr;
   }
 
   if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
     DCHECK(soa.Self()->IsExceptionPending());
-    return NULL;
+    return nullptr;
   }
 
   mirror::Object* receiver = c->AllocNonMovableObject(soa.Self());
-  if (receiver == NULL) {
-    return NULL;
+  if (receiver == nullptr) {
+    return nullptr;
   }
 
   jobject javaReceiver = soa.AddLocalReference<jobject>(receiver);
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 4d69a68..553aeb8 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -31,10 +31,13 @@
                           mirror::ArtField* f, JValue& value, bool allow_references)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK_EQ(value.GetJ(), 0LL);
-  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(f->GetDeclaringClass(),
-                                                               true, true)) {
+  CHECK(!kMovingFields);
+  SirtRef<mirror::Object> sirt_obj(soa.Self(), o);
+  SirtRef<mirror::Class> sirt_klass(soa.Self(), f->GetDeclaringClass());
+  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) {
     return false;
   }
+  o = sirt_obj.get();
   switch (FieldHelper(f).GetTypeAsPrimitiveType()) {
   case Primitive::kPrimBoolean:
     value.SetZ(f->GetBoolean(o));
@@ -168,13 +171,16 @@
   return GetPrimitiveField(env, javaField, javaObj, 'S').GetS();
 }
 
-static void SetFieldValue(mirror::Object* o, mirror::ArtField* f, const JValue& new_value,
-                          bool allow_references)
+static void SetFieldValue(ScopedFastNativeObjectAccess& soa, mirror::Object* o,
+                          mirror::ArtField* f, const JValue& new_value, bool allow_references)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(f->GetDeclaringClass(),
-                                                               true, true)) {
+  CHECK(!kMovingFields);
+  SirtRef<mirror::Object> sirt_obj(soa.Self(), o);
+  SirtRef<mirror::Class> sirt_klass(soa.Self(), f->GetDeclaringClass());
+  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) {
     return;
   }
+  o = sirt_obj.get();
   switch (FieldHelper(f).GetTypeAsPrimitiveType()) {
   case Primitive::kPrimBoolean:
     f->SetBoolean(o, new_value.GetZ());
@@ -237,7 +243,7 @@
     return;
   }
 
-  SetFieldValue(o, f, unboxed_value, true);
+  SetFieldValue(soa, o, f, unboxed_value, true);
 }
 
 static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char src_descriptor,
@@ -264,7 +270,7 @@
   }
 
   // Write the value.
-  SetFieldValue(o, f, wide_value, false);
+  SetFieldValue(soa, o, f, wide_value, false);
 }
 
 static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) {
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index e37510c..cc996bc 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -34,34 +34,36 @@
 
 namespace art {
 
+template <typename T>
 class ObjectLock {
  public:
-  explicit ObjectLock(Thread* self, mirror::Object* object)
+  explicit ObjectLock(Thread* self, const SirtRef<T>* object)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       : self_(self), obj_(object) {
-    CHECK(object != NULL);
-    obj_->MonitorEnter(self_);
+    CHECK(object != nullptr);
+    CHECK(object->get() != nullptr);
+    obj_->get()->MonitorEnter(self_);
   }
 
   ~ObjectLock() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    obj_->MonitorExit(self_);
+    obj_->get()->MonitorExit(self_);
   }
 
   void WaitIgnoringInterrupts() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Monitor::Wait(self_, obj_, 0, 0, false, kWaiting);
+    Monitor::Wait(self_, obj_->get(), 0, 0, false, kWaiting);
   }
 
   void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    obj_->Notify(self_);
+    obj_->get()->Notify(self_);
   }
 
   void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    obj_->NotifyAll(self_);
+    obj_->get()->NotifyAll(self_);
   }
 
  private:
   Thread* const self_;
-  mirror::Object* obj_;
+  const SirtRef<T>* obj_;
   DISALLOW_COPY_AND_ASSIGN(ObjectLock);
 };
 
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 80e16aa..ac8f5ef 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -39,8 +39,12 @@
   mirror::ArtMethod* m = soa.DecodeMethod(mid);
 
   mirror::Class* declaring_class = m->GetDeclaringClass();
-  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaring_class, true, true)) {
-    return NULL;
+  if (UNLIKELY(!declaring_class->IsInitialized())) {
+    SirtRef<mirror::Class> sirt_c(soa.Self(), declaring_class);
+    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_c, true, true)) {
+      return nullptr;
+    }
+    declaring_class = sirt_c.get();
   }
 
   mirror::Object* receiver = NULL;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 4048bd3..e1b4d7e 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -47,6 +47,7 @@
 #include "mirror/array.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
+#include "mirror/stack_trace_element.h"
 #include "mirror/throwable.h"
 #include "monitor.h"
 #include "oat_file.h"
@@ -86,6 +87,7 @@
       resolution_method_(NULL),
       imt_conflict_method_(NULL),
       default_imt_(NULL),
+      method_verifiers_lock_("Method verifiers lock"),
       threads_being_born_(0),
       shutdown_cond_(new ConditionVariable("Runtime shutdown", *Locks::runtime_shutdown_lock_)),
       shutting_down_(false),
@@ -699,35 +701,38 @@
   }
 
   ScopedObjectAccess soa(Thread::Current());
+  ClassLinker* cl = Runtime::Current()->GetClassLinker();
 
-  mirror::Class* class_loader_class =
-      soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader);
-  CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(class_loader_class, true, true));
+  SirtRef<mirror::Class> class_loader_class(
+      soa.Self(), soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader));
+  CHECK(cl->EnsureInitialized(class_loader_class, true, true));
 
   mirror::ArtMethod* getSystemClassLoader =
       class_loader_class->FindDirectMethod("getSystemClassLoader", "()Ljava/lang/ClassLoader;");
   CHECK(getSystemClassLoader != NULL);
 
   JValue result;
-  ArgArray arg_array(NULL, 0);
+  ArgArray arg_array(nullptr, 0);
   InvokeWithArgArray(soa, getSystemClassLoader, &arg_array, &result, 'L');
-  mirror::ClassLoader* class_loader = down_cast<mirror::ClassLoader*>(result.GetL());
-  CHECK(class_loader != NULL);
-
+  SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
+                                            down_cast<mirror::ClassLoader*>(result.GetL()));
+  CHECK(class_loader.get() != nullptr);
   JNIEnv* env = soa.Self()->GetJniEnv();
-  ScopedLocalRef<jobject> system_class_loader(env, soa.AddLocalReference<jobject>(class_loader));
-  CHECK(system_class_loader.get() != NULL);
+  ScopedLocalRef<jobject> system_class_loader(env,
+                                              soa.AddLocalReference<jobject>(class_loader.get()));
+  CHECK(system_class_loader.get() != nullptr);
 
-  soa.Self()->SetClassLoaderOverride(class_loader);
+  soa.Self()->SetClassLoaderOverride(class_loader.get());
 
-  mirror::Class* thread_class = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
-  CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(thread_class, true, true));
+  SirtRef<mirror::Class> thread_class(soa.Self(),
+                                      soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread));
+  CHECK(cl->EnsureInitialized(thread_class, true, true));
 
-  mirror::ArtField* contextClassLoader = thread_class->FindDeclaredInstanceField("contextClassLoader",
-                                                                                 "Ljava/lang/ClassLoader;");
+  mirror::ArtField* contextClassLoader =
+      thread_class->FindDeclaredInstanceField("contextClassLoader", "Ljava/lang/ClassLoader;");
   CHECK(contextClassLoader != NULL);
 
-  contextClassLoader->SetObject(soa.Self()->GetPeer(), class_loader);
+  contextClassLoader->SetObject(soa.Self()->GetPeer(), class_loader.get());
 
   return env->NewGlobalRef(system_class_loader.get());
 }
@@ -1188,9 +1193,25 @@
 }
 
 void Runtime::VisitNonThreadRoots(RootVisitor* visitor, void* arg) {
+  // Visit the classes held as static in mirror classes.
+  mirror::ArtField::VisitRoots(visitor, arg);
+  mirror::ArtMethod::VisitRoots(visitor, arg);
+  mirror::Class::VisitRoots(visitor, arg);
+  mirror::StackTraceElement::VisitRoots(visitor, arg);
+  mirror::String::VisitRoots(visitor, arg);
+  mirror::Throwable::VisitRoots(visitor, arg);
+  // Visit all the primitive array types classes.
+  mirror::PrimitiveArray<uint8_t>::VisitRoots(visitor, arg);   // BooleanArray
+  mirror::PrimitiveArray<int8_t>::VisitRoots(visitor, arg);    // ByteArray
+  mirror::PrimitiveArray<uint16_t>::VisitRoots(visitor, arg);  // CharArray
+  mirror::PrimitiveArray<double>::VisitRoots(visitor, arg);    // DoubleArray
+  mirror::PrimitiveArray<float>::VisitRoots(visitor, arg);     // FloatArray
+  mirror::PrimitiveArray<int32_t>::VisitRoots(visitor, arg);   // IntArray
+  mirror::PrimitiveArray<int64_t>::VisitRoots(visitor, arg);   // LongArray
+  mirror::PrimitiveArray<int16_t>::VisitRoots(visitor, arg);   // ShortArray
   java_vm_->VisitRoots(visitor, arg);
   if (pre_allocated_OutOfMemoryError_ != nullptr) {
-    pre_allocated_OutOfMemoryError_ = reinterpret_cast<mirror::Throwable*>(
+    pre_allocated_OutOfMemoryError_ = down_cast<mirror::Throwable*>(
         visitor(pre_allocated_OutOfMemoryError_, arg));
     DCHECK(pre_allocated_OutOfMemoryError_ != nullptr);
   }
@@ -1209,6 +1230,12 @@
           visitor(callee_save_methods_[i], arg));
     }
   }
+  {
+    MutexLock mu(Thread::Current(), method_verifiers_lock_);
+    for (verifier::MethodVerifier* verifier : method_verifiers_) {
+      verifier->VisitRoots(visitor, arg);
+    }
+  }
 }
 
 void Runtime::VisitNonConcurrentRoots(RootVisitor* visitor, void* arg) {
@@ -1355,4 +1382,18 @@
   compile_time_class_paths_.Put(class_loader, class_path);
 }
 
+void Runtime::AddMethodVerifier(verifier::MethodVerifier* verifier) {
+  DCHECK(verifier != nullptr);
+  MutexLock mu(Thread::Current(), method_verifiers_lock_);
+  method_verifiers_.insert(verifier);
+}
+
+void Runtime::RemoveMethodVerifier(verifier::MethodVerifier* verifier) {
+  DCHECK(verifier != nullptr);
+  MutexLock mu(Thread::Current(), method_verifiers_lock_);
+  auto it = method_verifiers_.find(verifier);
+  CHECK(it != method_verifiers_.end());
+  method_verifiers_.erase(it);
+}
+
 }  // namespace art
diff --git a/runtime/runtime.h b/runtime/runtime.h
index e6951d9..01a605a 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -52,6 +52,9 @@
   class String;
   class Throwable;
 }  // namespace mirror
+namespace verifier {
+class MethodVerifier;
+}
 class ClassLinker;
 class DexFile;
 class InternTable;
@@ -320,14 +323,16 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Visit all of the roots we can do safely do concurrently.
-  void VisitConcurrentRoots(RootVisitor* visitor, void* arg, bool only_dirty, bool clean_dirty);
+  void VisitConcurrentRoots(RootVisitor* visitor, void* arg, bool only_dirty, bool clean_dirty)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Visit all of the non thread roots, we can do this with mutators unpaused.
-  void VisitNonThreadRoots(RootVisitor* visitor, void* arg);
+  void VisitNonThreadRoots(RootVisitor* visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Visit all other roots which must be done with mutators suspended.
   void VisitNonConcurrentRoots(RootVisitor* visitor, void* arg)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Sweep system weaks, the system weak is deleted if the visitor return nullptr. Otherwise, the
   // system weak is updated to be the visitor's returned value.
@@ -438,6 +443,9 @@
     return use_compile_time_class_path_;
   }
 
+  void AddMethodVerifier(verifier::MethodVerifier* verifier);
+  void RemoveMethodVerifier(verifier::MethodVerifier* verifier);
+
   const std::vector<const DexFile*>& GetCompileTimeClassPath(jobject class_loader);
   void SetCompileTimeClassPath(jobject class_loader, std::vector<const DexFile*>& class_path);
 
@@ -520,6 +528,10 @@
 
   mirror::ObjectArray<mirror::ArtMethod>* default_imt_;
 
+  // Method verifier set, used so that we can update their GC roots.
+  Mutex method_verifiers_lock_;
+  std::set<verifier::MethodVerifier*> method_verifiers_;
+
   // A non-zero value indicates that a thread has been created but not yet initialized. Guarded by
   // the shutdown lock so that threads aren't born while we're shutting down.
   size_t threads_being_born_ GUARDED_BY(Locks::runtime_shutdown_lock_);
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 715be99..570379a 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -987,8 +987,9 @@
     mirror::Object* lock =
         soa.DecodeField(WellKnownClasses::java_lang_Thread_lock)->GetObject(opeer_);
     // (This conditional is only needed for tests, where Thread.lock won't have been set.)
-    if (lock != NULL) {
-      ObjectLock locker(self, lock);
+    if (lock != nullptr) {
+      SirtRef<mirror::Object> sirt_obj(self, lock);
+      ObjectLock<mirror::Object> locker(self, &sirt_obj);
       locker.Notify();
     }
   }
@@ -1444,9 +1445,9 @@
   ClearException();
   Runtime* runtime = Runtime::Current();
 
-  mirror::ClassLoader* cl = NULL;
-  if (throw_location.GetMethod() != NULL) {
-    cl = throw_location.GetMethod()->GetDeclaringClass()->GetClassLoader();
+  mirror::ClassLoader* cl = nullptr;
+  if (saved_throw_method.get() != nullptr) {
+    cl = saved_throw_method.get()->GetDeclaringClass()->GetClassLoader();
   }
   SirtRef<mirror::ClassLoader> class_loader(this, cl);
   SirtRef<mirror::Class>
@@ -1458,7 +1459,7 @@
     return;
   }
 
-  if (UNLIKELY(!runtime->GetClassLinker()->EnsureInitialized(exception_class.get(), true, true))) {
+  if (UNLIKELY(!runtime->GetClassLinker()->EnsureInitialized(exception_class, true, true))) {
     DCHECK(IsExceptionPending());
     return;
   }
@@ -1468,7 +1469,9 @@
 
   // If we couldn't allocate the exception, throw the pre-allocated out of memory exception.
   if (exception.get() == nullptr) {
-    SetException(throw_location, Runtime::Current()->GetPreAllocatedOutOfMemoryError());
+    ThrowLocation gc_safe_throw_location(saved_throw_this.get(), saved_throw_method.get(),
+                                         throw_location.GetDexPc());
+    SetException(gc_safe_throw_location, Runtime::Current()->GetPreAllocatedOutOfMemoryError());
     return;
   }
 
diff --git a/runtime/throw_location.cc b/runtime/throw_location.cc
index 01497ef..1cc3e74 100644
--- a/runtime/throw_location.cc
+++ b/runtime/throw_location.cc
@@ -25,7 +25,7 @@
 namespace art {
 
 std::string ThrowLocation::Dump() const {
-  if (method_ != NULL) {
+  if (method_ != nullptr) {
     return StringPrintf("%s:%d", PrettyMethod(method_).c_str(),
                         MethodHelper(method_).GetLineNumFromDexPC(dex_pc_));
   } else {
@@ -35,12 +35,11 @@
 
 void ThrowLocation::VisitRoots(RootVisitor* visitor, void* arg) {
   if (this_object_ != nullptr) {
-    this_object_ = const_cast<mirror::Object*>(visitor(this_object_, arg));
+    this_object_ = visitor(this_object_, arg);
     DCHECK(this_object_ != nullptr);
   }
   if (method_ != nullptr) {
-    method_ = const_cast<mirror::ArtMethod*>(
-        reinterpret_cast<const mirror::ArtMethod*>(visitor(method_, arg)));
+    method_ = down_cast<mirror::ArtMethod*>(visitor(method_, arg));
     DCHECK(method_ != nullptr);
   }
 }
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 5f5d865..9183b5f 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -319,10 +319,12 @@
       allow_soft_failures_(allow_soft_failures),
       has_check_casts_(false),
       has_virtual_or_interface_invokes_(false) {
+  Runtime::Current()->AddMethodVerifier(this);
   DCHECK(class_def != nullptr);
 }
 
 MethodVerifier::~MethodVerifier() {
+  Runtime::Current()->RemoveMethodVerifier(this);
   STLDeleteElements(&failure_messages_);
 }
 
@@ -4385,5 +4387,9 @@
   return (rejected_classes_->find(ref) != rejected_classes_->end());
 }
 
+void MethodVerifier::VisitRoots(RootVisitor* visitor, void* arg) {
+  reg_types_.VisitRoots(visitor, arg);
+}
+
 }  // namespace verifier
 }  // namespace art
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 892b7a8..6b5747b 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -237,6 +237,8 @@
   static bool IsCandidateForCompilation(MethodReference& method_ref,
                                         const uint32_t access_flags);
 
+  void VisitRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  private:
   // Adds the given string to the beginning of the last failure message.
   void PrependToLastFailMessage(std::string);
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index d82e75d..f394bce 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -969,6 +969,12 @@
   }
 }
 
+void RegType::VisitRoots(RootVisitor* visitor, void* arg) {
+  if (klass_ != nullptr) {
+    klass_ = down_cast<mirror::Class*>(visitor(klass_, arg));
+  }
+}
+
 void UninitializedThisReferenceType::CheckInvariants() const {
   CHECK_EQ(GetAllocationPc(), 0U) << *this;
 }
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index f371733..8df481f 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -20,6 +20,7 @@
 #include "base/macros.h"
 #include "globals.h"
 #include "primitive.h"
+#include "root_visitor.h"
 
 #include "jni.h"
 
@@ -269,6 +270,8 @@
 
   virtual ~RegType() {}
 
+  void VisitRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  protected:
   RegType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
@@ -282,7 +285,7 @@
 
 
   const std::string descriptor_;
-  mirror::Class* const klass_;
+  mirror::Class* klass_;
   const uint16_t cache_id_;
 
   friend class RegTypeCache;
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 9c9673a..3d24414 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -554,5 +554,11 @@
   }
 }
 
+void RegTypeCache::VisitRoots(RootVisitor* visitor, void* arg) {
+  for (RegType* entry : entries_) {
+    entry->VisitRoots(visitor, arg);
+  }
+}
+
 }  // namespace verifier
 }  // namespace art
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index a9f8bff..a811696 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -21,6 +21,7 @@
 #include "base/macros.h"
 #include "base/stl_util.h"
 #include "reg_type.h"
+#include "root_visitor.h"
 #include "runtime.h"
 
 #include <stdint.h>
@@ -139,6 +140,8 @@
   void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   const RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
 
+  void VisitRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  private:
   void FillPrimitiveAndSmallConstantTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader)