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/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) {