Compile time performance improvements focusing on interpret-only.

Reduce virtual method dispatch in the method verifier and make more code
inline-able.
Add a StringPiece with const char* equality operator to avoid redundant
StringPieces and strlens.
Remove back link from register line to verifier and pass as argument to reduce
size of RegisterLine.
Remove instruction length from instruction flags and compute from the
instruction, again to reduce size.
Add suspend checks to resolve and verify to allow for more easy monitor
inflation and reduce contention on Locks::thread_list_suspend_thread_lock_.
Change ThrowEarlierClassFailure to throw pre-allocated exception.
Avoid calls to Thread::Current() by passing self.
Template specialize IsValidClassName.
Make ANR reporting with SIGQUIT run using checkpoints rather than suspending
all threads. This makes the stack/lock analysis less lock error prone.
Extra Barrier assertions and condition variable time out is now returned as a
boolean both from Barrier and ConditionVariable::Wait.

2 threaded host x86-64 interpret-only numbers from 341 samples:
Before change: Avg 176.137ms 99% CI 3.468ms to 1060.770ms
After change: Avg 139.163% 99% CI 3.027ms to 838.257ms
Reduction in average compile time after change is 20.9%.
Slow-down without change is 26.5%.

Bug: 17471626 - Fix bug where RegTypeCache::JavaLangObject/String/Class/Throwable
could return unresolved type when class loading is disabled.
Bug: 17398101

Change-Id: Id59ce3cc520701c6ecf612f7152498107bc40684
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 16cddd5..4474f1b 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -64,7 +64,7 @@
 #include "ScopedLocalRef.h"
 #include "scoped_thread_state_change.h"
 #include "handle_scope-inl.h"
-#include "thread.h"
+#include "thread-inl.h"
 #include "utils.h"
 #include "verifier/method_verifier.h"
 #include "well_known_classes.h"
@@ -89,21 +89,29 @@
   // a NoClassDefFoundError (v2 2.17.5).  The exception to this rule is if we
   // failed in verification, in which case v2 5.4.1 says we need to re-throw
   // the previous error.
-  if (!Runtime::Current()->IsCompiler()) {  // Give info if this occurs at runtime.
+  Runtime* runtime = Runtime::Current();
+  bool is_compiler = runtime->IsCompiler();
+  if (!is_compiler) {  // Give info if this occurs at runtime.
     LOG(INFO) << "Rejecting re-init on previously-failed class " << PrettyClass(c);
   }
 
   CHECK(c->IsErroneous()) << PrettyClass(c) << " " << c->GetStatus();
   Thread* self = Thread::Current();
-  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
-  if (c->GetVerifyErrorClass() != NULL) {
-    // TODO: change the verifier to store an _instance_, with a useful detail message?
-    std::string temp;
-    self->ThrowNewException(throw_location, c->GetVerifyErrorClass()->GetDescriptor(&temp),
-                            PrettyDescriptor(c).c_str());
+  if (is_compiler) {
+    // At compile time, accurate errors and NCDFE are disabled to speed compilation.
+    mirror::Throwable* pre_allocated = runtime->GetPreAllocatedNoClassDefFoundError();
+    self->SetException(ThrowLocation(), pre_allocated);
   } else {
-    self->ThrowNewException(throw_location, "Ljava/lang/NoClassDefFoundError;",
-                            PrettyDescriptor(c).c_str());
+    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+    if (c->GetVerifyErrorClass() != NULL) {
+      // TODO: change the verifier to store an _instance_, with a useful detail message?
+      std::string temp;
+      self->ThrowNewException(throw_location, c->GetVerifyErrorClass()->GetDescriptor(&temp),
+                              PrettyDescriptor(c).c_str());
+    } else {
+      self->ThrowNewException(throw_location, "Ljava/lang/NoClassDefFoundError;",
+                              PrettyDescriptor(c).c_str());
+    }
   }
 }
 
@@ -438,7 +446,7 @@
   for (size_t i = 0; i != boot_class_path.size(); ++i) {
     const DexFile* dex_file = boot_class_path[i];
     CHECK(dex_file != NULL);
-    AppendToBootClassPath(*dex_file);
+    AppendToBootClassPath(self, *dex_file);
   }
 
   // now we can use FindSystemClass
@@ -666,7 +674,7 @@
     if (!c->IsArrayClass() && !c->IsPrimitive()) {
       StackHandleScope<1> hs(self);
       Handle<mirror::Class> h_class(hs.NewHandle(GetClassRoot(ClassRoot(i))));
-      EnsureInitialized(h_class, true, true);
+      EnsureInitialized(self, h_class, true, true);
       self->AssertNoPendingException();
     }
   }
@@ -1880,7 +1888,7 @@
     while (!local_arg.success) {
       size_t class_table_size;
       {
-        ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+        ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
         class_table_size = class_table_.size();
       }
       mirror::Class* class_type = mirror::Class::GetJavaLangClass();
@@ -2024,7 +2032,7 @@
     }
     CHECK(h_class->IsRetired());
     // Get the updated class from class table.
-    klass = LookupClass(descriptor, h_class.Get()->GetClassLoader());
+    klass = LookupClass(self, descriptor, h_class.Get()->GetClassLoader());
   }
 
   // Wait for the class if it has not already been linked.
@@ -2083,11 +2091,11 @@
   ClassPathEntry pair = FindInClassPath(descriptor, boot_class_path_);
   // Check if this would be found in the parent boot class loader.
   if (pair.second != nullptr) {
-    mirror::Class* klass = LookupClass(descriptor, nullptr);
+    mirror::Class* klass = LookupClass(self, descriptor, nullptr);
     if (klass != nullptr) {
       return EnsureResolved(self, descriptor, klass);
     }
-    klass = DefineClass(descriptor, NullHandle<mirror::ClassLoader>(), *pair.first,
+    klass = DefineClass(self, descriptor, NullHandle<mirror::ClassLoader>(), *pair.first,
                         *pair.second);
     if (klass != nullptr) {
       return klass;
@@ -2139,7 +2147,7 @@
               if (dex_class_def != nullptr) {
                 RegisterDexFile(*dex_file);
                 mirror::Class* klass =
-                    DefineClass(descriptor, class_loader, *dex_file, *dex_class_def);
+                    DefineClass(self, descriptor, class_loader, *dex_file, *dex_class_def);
                 if (klass == nullptr) {
                   CHECK(self->IsExceptionPending()) << descriptor;
                   self->ClearException();
@@ -2167,7 +2175,7 @@
     return FindPrimitiveClass(descriptor[0]);
   }
   // Find the class in the loaded classes table.
-  mirror::Class* klass = LookupClass(descriptor, class_loader.Get());
+  mirror::Class* klass = LookupClass(self, descriptor, class_loader.Get());
   if (klass != nullptr) {
     return EnsureResolved(self, descriptor, klass);
   }
@@ -2178,7 +2186,8 @@
     // The boot class loader, search the boot class path.
     ClassPathEntry pair = FindInClassPath(descriptor, boot_class_path_);
     if (pair.second != nullptr) {
-      return DefineClass(descriptor, NullHandle<mirror::ClassLoader>(), *pair.first, *pair.second);
+      return DefineClass(self, descriptor, NullHandle<mirror::ClassLoader>(), *pair.first,
+                         *pair.second);
     } else {
       // The boot class loader is searched ahead of the application class loader, failures are
       // expected and will be wrapped in a ClassNotFoundException. Use the pre-allocated error to
@@ -2190,7 +2199,7 @@
   } else if (Runtime::Current()->UseCompileTimeClassPath()) {
     // First try with the bootstrap class loader.
     if (class_loader.Get() != nullptr) {
-      klass = LookupClass(descriptor, nullptr);
+      klass = LookupClass(self, descriptor, nullptr);
       if (klass != nullptr) {
         return EnsureResolved(self, descriptor, klass);
       }
@@ -2199,7 +2208,8 @@
     // a NoClassDefFoundError being allocated.
     ClassPathEntry pair = FindInClassPath(descriptor, boot_class_path_);
     if (pair.second != nullptr) {
-      return DefineClass(descriptor, NullHandle<mirror::ClassLoader>(), *pair.first, *pair.second);
+      return DefineClass(self, descriptor, NullHandle<mirror::ClassLoader>(), *pair.first,
+                         *pair.second);
     }
     // Next try the compile time class path.
     const std::vector<const DexFile*>* class_path;
@@ -2211,7 +2221,12 @@
     }
     pair = FindInClassPath(descriptor, *class_path);
     if (pair.second != nullptr) {
-      return DefineClass(descriptor, class_loader, *pair.first, *pair.second);
+      return DefineClass(self, descriptor, class_loader, *pair.first, *pair.second);
+    } else {
+      // Use the pre-allocated NCDFE at compile time to avoid wasting time constructing exceptions.
+      mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError();
+      self->SetException(ThrowLocation(), pre_allocated);
+      return nullptr;
     }
   } else {
     ScopedObjectAccessUnchecked soa(self);
@@ -2254,11 +2269,10 @@
   return nullptr;
 }
 
-mirror::Class* ClassLinker::DefineClass(const char* descriptor,
+mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor,
                                         ConstHandle<mirror::ClassLoader> class_loader,
                                         const DexFile& dex_file,
                                         const DexFile::ClassDef& dex_class_def) {
-  Thread* self = Thread::Current();
   StackHandleScope<3> hs(self);
   auto klass = hs.NewHandle<mirror::Class>(nullptr);
   bool should_allocate = false;
@@ -2299,7 +2313,7 @@
     return nullptr;
   }
   klass->SetDexCache(FindDexCache(dex_file));
-  LoadClass(dex_file, dex_class_def, klass, class_loader.Get());
+  LoadClass(self, dex_file, dex_class_def, klass, class_loader.Get());
   ObjectLock<mirror::Class> lock(self, klass);
   if (self->IsExceptionPending()) {
     // An exception occured during load, set status to erroneous while holding klass' lock in case
@@ -2764,7 +2778,7 @@
 
 
 
-void ClassLinker::LoadClass(const DexFile& dex_file,
+void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file,
                             const DexFile::ClassDef& dex_class_def,
                             ConstHandle<mirror::Class> klass,
                             mirror::ClassLoader* class_loader) {
@@ -2800,22 +2814,21 @@
     OatFile::OatClass oat_class = FindOatClass(dex_file, klass->GetDexClassDefIndex(),
                                                &has_oat_class);
     if (has_oat_class) {
-      LoadClassMembers(dex_file, class_data, klass, class_loader, &oat_class);
+      LoadClassMembers(self, dex_file, class_data, klass, class_loader, &oat_class);
     }
   }
   if (!has_oat_class) {
-    LoadClassMembers(dex_file, class_data, klass, class_loader, nullptr);
+    LoadClassMembers(self, dex_file, class_data, klass, class_loader, nullptr);
   }
 }
 
-void ClassLinker::LoadClassMembers(const DexFile& dex_file,
+void ClassLinker::LoadClassMembers(Thread* self, const DexFile& dex_file,
                                    const byte* class_data,
                                    ConstHandle<mirror::Class> klass,
                                    mirror::ClassLoader* class_loader,
                                    const OatFile::OatClass* oat_class) {
   // Load fields.
   ClassDataItemIterator it(dex_file, class_data);
-  Thread* self = Thread::Current();
   if (it.NumStaticFields() != 0) {
     mirror::ObjectArray<mirror::ArtField>* statics = AllocArtFieldArray(self, it.NumStaticFields());
     if (UNLIKELY(statics == NULL)) {
@@ -2834,6 +2847,7 @@
     klass->SetIFields(fields);
   }
   for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
+    self->AllowThreadSuspension();
     StackHandleScope<1> hs(self);
     Handle<mirror::ArtField> sfield(hs.NewHandle(AllocArtField(self)));
     if (UNLIKELY(sfield.Get() == NULL)) {
@@ -2844,6 +2858,7 @@
     LoadField(dex_file, it, klass, sfield);
   }
   for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) {
+    self->AllowThreadSuspension();
     StackHandleScope<1> hs(self);
     Handle<mirror::ArtField> ifield(hs.NewHandle(AllocArtField(self)));
     if (UNLIKELY(ifield.Get() == NULL)) {
@@ -2879,6 +2894,7 @@
   uint32_t last_dex_method_index = DexFile::kDexNoIndex;
   size_t last_class_def_method_index = 0;
   for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
+    self->AllowThreadSuspension();
     StackHandleScope<1> hs(self);
     Handle<mirror::ArtMethod> method(hs.NewHandle(LoadMethod(self, dex_file, it, klass)));
     if (UNLIKELY(method.Get() == NULL)) {
@@ -2899,6 +2915,7 @@
     class_def_method_index++;
   }
   for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
+    self->AllowThreadSuspension();
     StackHandleScope<1> hs(self);
     Handle<mirror::ArtMethod> method(hs.NewHandle(LoadMethod(self, dex_file, it, klass)));
     if (UNLIKELY(method.Get() == NULL)) {
@@ -2987,8 +3004,7 @@
   return dst;
 }
 
-void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) {
-  Thread* self = Thread::Current();
+void ClassLinker::AppendToBootClassPath(Thread* self, const DexFile& dex_file) {
   StackHandleScope<1> hs(self);
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(AllocDexCache(self, dex_file)));
   CHECK(dex_cache.Get() != NULL) << "Failed to allocate dex cache for " << dex_file.GetLocation();
@@ -3142,7 +3158,7 @@
   if (component_type.Get() == nullptr) {
     DCHECK(self->IsExceptionPending());
     // We need to accept erroneous classes as component types.
-    component_type.Assign(LookupClass(descriptor + 1, class_loader.Get()));
+    component_type.Assign(LookupClass(self, descriptor + 1, class_loader.Get()));
     if (component_type.Get() == nullptr) {
       DCHECK(self->IsExceptionPending());
       return nullptr;
@@ -3172,7 +3188,7 @@
   // class to the hash table --- necessary because of possible races with
   // other threads.)
   if (class_loader.Get() != component_type->GetClassLoader()) {
-    mirror::Class* new_class = LookupClass(descriptor, component_type->GetClassLoader());
+    mirror::Class* new_class = LookupClass(self, descriptor, component_type->GetClassLoader());
     if (new_class != NULL) {
       return new_class;
     }
@@ -3391,11 +3407,11 @@
   return false;
 }
 
-mirror::Class* ClassLinker::LookupClass(const char* descriptor,
+mirror::Class* ClassLinker::LookupClass(Thread* self, const char* descriptor,
                                         const mirror::ClassLoader* class_loader) {
   size_t hash = Hash(descriptor);
   {
-    ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+    ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
     mirror::Class* result = LookupClassFromTableLocked(descriptor, class_loader, hash);
     if (result != NULL) {
       return result;
@@ -3531,9 +3547,8 @@
   }
 }
 
-void ClassLinker::VerifyClass(ConstHandle<mirror::Class> klass) {
+void ClassLinker::VerifyClass(Thread* self, ConstHandle<mirror::Class> klass) {
   // TODO: assert that the monitor on the Class is held
-  Thread* self = Thread::Current();
   ObjectLock<mirror::Class> lock(self, klass);
 
   // Don't attempt to re-verify if already sufficiently verified.
@@ -3576,7 +3591,7 @@
     ObjectLock<mirror::Class> lock(self, super);
 
     if (!super->IsVerified() && !super->IsErroneous()) {
-      VerifyClass(super);
+      VerifyClass(self, super);
     }
     if (!super->IsCompileTimeVerified()) {
       std::string error_msg(
@@ -3617,7 +3632,7 @@
   verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
   std::string error_msg;
   if (!preverified) {
-    verifier_failure = verifier::MethodVerifier::VerifyClass(klass.Get(),
+    verifier_failure = verifier::MethodVerifier::VerifyClass(self, klass.Get(),
                                                              Runtime::Current()->IsCompiler(),
                                                              &error_msg);
   }
@@ -3652,7 +3667,7 @@
         klass->SetStatus(mirror::Class::kStatusVerified, self);
         // As this is a fake verified status, make sure the methods are _not_ marked preverified
         // later.
-        klass->SetAccessFlags(klass->GetAccessFlags() | kAccPreverified);
+        klass->SetPreverified();
       }
     }
   } else {
@@ -3675,9 +3690,9 @@
 }
 
 void ClassLinker::EnsurePreverifiedMethods(ConstHandle<mirror::Class> klass) {
-  if ((klass->GetAccessFlags() & kAccPreverified) == 0) {
+  if (!klass->IsPreverified()) {
     klass->SetPreverifiedFlagOnAllMethods();
-    klass->SetAccessFlags(klass->GetAccessFlags() | kAccPreverified);
+    klass->SetPreverified();
   }
 }
 
@@ -4108,12 +4123,8 @@
   return true;
 }
 
-bool ClassLinker::IsInitialized() const {
-  return init_done_;
-}
-
-bool ClassLinker::InitializeClass(ConstHandle<mirror::Class> klass, bool can_init_statics,
-                                  bool can_init_parents) {
+bool ClassLinker::InitializeClass(Thread* self, ConstHandle<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
 
   // Are we already initialized and therefore done?
@@ -4128,7 +4139,7 @@
     return false;
   }
 
-  Thread* self = Thread::Current();
+  self->AllowThreadSuspension();
   uint64_t t0;
   {
     ObjectLock<mirror::Class> lock(self, klass);
@@ -4147,7 +4158,7 @@
     CHECK(klass->IsResolved()) << PrettyClass(klass.Get()) << ": state=" << klass->GetStatus();
 
     if (!klass->IsVerified()) {
-      VerifyClass(klass);
+      VerifyClass(self, klass);
       if (!klass->IsVerified()) {
         // We failed to verify, expect either the klass to be erroneous or verification failed at
         // compile time.
@@ -4186,6 +4197,7 @@
       klass->SetStatus(mirror::Class::kStatusError, self);
       return false;
     }
+    self->AllowThreadSuspension();
 
     CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << PrettyClass(klass.Get());
 
@@ -4205,7 +4217,7 @@
       CHECK(can_init_parents);
       StackHandleScope<1> hs(self);
       Handle<mirror::Class> handle_scope_super(hs.NewHandle(super_class));
-      bool super_initialized = InitializeClass(handle_scope_super, can_init_statics, true);
+      bool super_initialized = InitializeClass(self, handle_scope_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.
@@ -4258,6 +4270,7 @@
     clinit->Invoke(self, NULL, 0, &result, "V");
   }
 
+  self->AllowThreadSuspension();
   uint64_t t1 = NanoTime();
 
   bool success = true;
@@ -4374,15 +4387,14 @@
   return true;
 }
 
-bool ClassLinker::EnsureInitialized(ConstHandle<mirror::Class> c, bool can_init_fields,
-                                    bool can_init_parents) {
+bool ClassLinker::EnsureInitialized(Thread* self, ConstHandle<mirror::Class> c,
+                                    bool can_init_fields, bool can_init_parents) {
   DCHECK(c.Get() != nullptr);
   if (c->IsInitialized()) {
     EnsurePreverifiedMethods(c);
     return true;
   }
-  const bool success = InitializeClass(c, can_init_fields, can_init_parents);
-  Thread* self = Thread::Current();
+  const bool success = InitializeClass(self, c, can_init_fields, can_init_parents);
   if (!success) {
     if (can_init_fields && can_init_parents) {
       CHECK(self->IsExceptionPending()) << PrettyClass(c.Get());
@@ -4442,11 +4454,11 @@
   if (!LinkMethods(self, klass, interfaces)) {
     return false;
   }
-  if (!LinkInstanceFields(klass)) {
+  if (!LinkInstanceFields(self, klass)) {
     return false;
   }
   size_t class_size;
-  if (!LinkStaticFields(klass, &class_size)) {
+  if (!LinkStaticFields(self, klass, &class_size)) {
     return false;
   }
   CreateReferenceInstanceOffsets(klass);
@@ -4603,6 +4615,7 @@
 // Populate the class vtable and itable. Compute return type indices.
 bool ClassLinker::LinkMethods(Thread* self, ConstHandle<mirror::Class> klass,
                               ConstHandle<mirror::ObjectArray<mirror::Class>> interfaces) {
+  self->AllowThreadSuspension();
   if (klass->IsInterface()) {
     // No vtable.
     size_t count = klass->NumVirtualMethods();
@@ -4780,6 +4793,7 @@
       iftable->SetInterface(i, super_interface);
     }
   }
+  self->AllowThreadSuspension();
   // Flatten the interface inheritance hierarchy.
   size_t idx = super_ifcount;
   for (size_t i = 0; i < num_interfaces; i++) {
@@ -4823,6 +4837,7 @@
       }
     }
   }
+  self->AllowThreadSuspension();
   // Shrink iftable in case duplicates were found
   if (idx < ifcount) {
     iftable.Assign(down_cast<mirror::IfTable*>(iftable->CopyOf(self, idx * mirror::IfTable::kMax)));
@@ -4840,6 +4855,7 @@
   if (klass->IsInterface()) {
     return true;
   }
+  self->AllowThreadSuspension();
   // Allocate imtable
   bool imtable_changed = false;
   Handle<mirror::ObjectArray<mirror::ArtMethod>> imtable(
@@ -4858,6 +4874,7 @@
       miranda_list(hs.NewHandle(AllocArtMethodArray(self, max_miranda_methods)));
   size_t miranda_list_size = 0;  // The current size of miranda_list.
   for (size_t i = 0; i < ifcount; ++i) {
+    self->AllowThreadSuspension();
     size_t num_methods = iftable->GetInterface(i)->NumVirtualMethods();
     if (num_methods > 0) {
       StackHandleScope<2> hs(self);
@@ -4984,19 +5001,19 @@
     CHECK(vtable->Get(i) != NULL);
   }
 
-//  klass->DumpClass(std::cerr, Class::kDumpClassFullDetail);
+  self->AllowThreadSuspension();
 
   return true;
 }
 
-bool ClassLinker::LinkInstanceFields(ConstHandle<mirror::Class> klass) {
+bool ClassLinker::LinkInstanceFields(Thread* self, ConstHandle<mirror::Class> klass) {
   CHECK(klass.Get() != NULL);
-  return LinkFields(klass, false, nullptr);
+  return LinkFields(self, klass, false, nullptr);
 }
 
-bool ClassLinker::LinkStaticFields(ConstHandle<mirror::Class> klass, size_t* class_size) {
+bool ClassLinker::LinkStaticFields(Thread* self, ConstHandle<mirror::Class> klass, size_t* class_size) {
   CHECK(klass.Get() != NULL);
-  return LinkFields(klass, true, class_size);
+  return LinkFields(self, klass, true, class_size);
 }
 
 struct LinkFieldsComparator {
@@ -5026,7 +5043,9 @@
   }
 };
 
-bool ClassLinker::LinkFields(ConstHandle<mirror::Class> klass, bool is_static, size_t* class_size) {
+bool ClassLinker::LinkFields(Thread* self, ConstHandle<mirror::Class> klass, bool is_static,
+                             size_t* class_size) {
+  self->AllowThreadSuspension();
   size_t num_fields =
       is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
 
@@ -5057,7 +5076,7 @@
   // we want a relatively stable order so that adding new fields
   // minimizes disruption of C++ version such as Class and Method.
   std::deque<mirror::ArtField*> grouped_and_sorted_fields;
-  const char* old_no_suspend_cause  = Thread::Current()->StartAssertNoThreadSuspension(
+  const char* old_no_suspend_cause  = self->StartAssertNoThreadSuspension(
       "Naked ArtField references in deque");
   for (size_t i = 0; i < num_fields; i++) {
     mirror::ArtField* f = fields->Get(i);
@@ -5103,8 +5122,7 @@
                     fields, &grouped_and_sorted_fields, &gaps);
   CHECK(grouped_and_sorted_fields.empty()) << "Missed " << grouped_and_sorted_fields.size() <<
       " fields.";
-
-  Thread::Current()->EndAssertNoThreadSuspension(old_no_suspend_cause);
+  self->EndAssertNoThreadSuspension(old_no_suspend_cause);
 
   // We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
   if (!is_static && klass->DescriptorEquals("Ljava/lang/ref/Reference;")) {
@@ -5520,10 +5538,12 @@
 }
 
 void ClassLinker::DumpForSigQuit(std::ostream& os) {
+  Thread* self = Thread::Current();
   if (dex_cache_image_class_lookup_required_) {
+    ScopedObjectAccess soa(self);
     MoveImageClassesToClassTable();
   }
-  ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+  ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
   os << "Loaded classes: " << class_table_.size() << " allocated classes\n";
 }