Merge "Revert "Revert "Fully support pairs in the register allocator."""
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 00f3855..b0d55c3 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2353,6 +2353,18 @@
 
   Handle<mirror::Class> new_class_h(hs.NewHandle(new_class));
 
+  // Instrumentation may have updated entrypoints for all methods of all
+  // classes. However it could not update methods of this class while we
+  // were loading it. Now the class is resolved, we can update entrypoints
+  // as required by instrumentation.
+  if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) {
+    // We must be in the kRunnable state to prevent instrumentation from
+    // suspending all threads to update entrypoints while we are doing it
+    // for this class.
+    DCHECK_EQ(self->GetState(), kRunnable);
+    Runtime::Current()->GetInstrumentation()->InstallStubsForClass(new_class_h.Get());
+  }
+
   /*
    * We send CLASS_PREPARE events to the debugger from here.  The
    * definition of "preparation" is creating the static fields for a
@@ -2670,10 +2682,6 @@
       DCHECK(IsQuickGenericJniStub(entry_point) || IsQuickResolutionStub(entry_point));
     }
   }
-
-  // Allow instrumentation its chance to hijack code.
-  runtime->GetInstrumentation()->UpdateMethodsCode(method.Get(),
-                                                   method->GetEntryPointFromQuickCompiledCode());
 }
 
 
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 1548cfd..14834dd 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -54,7 +54,7 @@
 static constexpr bool kDeoptimizeForAccurateMethodEntryExitListeners = true;
 
 static bool InstallStubsClassVisitor(mirror::Class* klass, void* arg)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Instrumentation* instrumentation = reinterpret_cast<Instrumentation*>(arg);
   return instrumentation->InstallStubsForClass(klass);
 }
@@ -74,11 +74,18 @@
 }
 
 bool Instrumentation::InstallStubsForClass(mirror::Class* klass) {
-  for (size_t i = 0, e = klass->NumDirectMethods(); i < e; i++) {
-    InstallStubsForMethod(klass->GetDirectMethod(i));
-  }
-  for (size_t i = 0, e = klass->NumVirtualMethods(); i < e; i++) {
-    InstallStubsForMethod(klass->GetVirtualMethod(i));
+  if (klass->IsErroneous()) {
+    // We can't execute code in a erroneous class: do nothing.
+  } else if (!klass->IsResolved()) {
+    // We need the class to be resolved to install/uninstall stubs. Otherwise its methods
+    // could not be initialized or linked with regards to class inheritance.
+  } else {
+    for (size_t i = 0, e = klass->NumDirectMethods(); i < e; i++) {
+      InstallStubsForMethod(klass->GetDirectMethod(i));
+    }
+    for (size_t i = 0, e = klass->NumVirtualMethods(); i < e; i++) {
+      InstallStubsForMethod(klass->GetVirtualMethod(i));
+    }
   }
   return true;
 }
@@ -541,6 +548,7 @@
   }
   Thread* const self = Thread::Current();
   Runtime* runtime = Runtime::Current();
+  Locks::mutator_lock_->AssertExclusiveHeld(self);
   Locks::thread_list_lock_->AssertNotHeld(self);
   if (desired_level > 0) {
     if (require_interpreter) {
@@ -631,6 +639,7 @@
 }
 
 void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code) {
+  DCHECK(method->GetDeclaringClass()->IsResolved());
   const void* new_quick_code;
   if (LIKELY(!instrumentation_stubs_installed_)) {
     new_quick_code = quick_code;