Reland^2 "Cover more cases in nterp."

This reverts commit dd5db458831cf74ae5813d2278fbd599145c4522.

Bug: 112676029
Bug: 157658616
Bug: 160543640

Reason for revert: Fixed missed class initialization.
Test: wifi tests, run-tests

Change-Id: Ie0a8ae0e92587b5c86203228615534526df640fb
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 124a2a5..059b09c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -227,6 +227,22 @@
   self->AssertPendingException();
 }
 
+static void ChangeInterpreterBridgeToNterp(ArtMethod* method, ClassLinker* class_linker)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  Runtime* runtime = Runtime::Current();
+  if (class_linker->IsQuickToInterpreterBridge(method->GetEntryPointFromQuickCompiledCode()) &&
+      interpreter::CanMethodUseNterp(method)) {
+    if (method->GetDeclaringClass()->IsVisiblyInitialized() ||
+        !NeedsClinitCheckBeforeCall(method)) {
+      runtime->GetInstrumentation()->UpdateMethodsCode(method, interpreter::GetNterpEntryPoint());
+    } else {
+      // Put the resolution stub, which will initialize the class and then
+      // call the method with nterp.
+      runtime->GetInstrumentation()->UpdateMethodsCode(method, GetQuickResolutionStub());
+    }
+  }
+}
+
 // Ensures that methods have the kAccSkipAccessChecks bit set. We use the
 // kAccVerificationAttempted bit on the class access flags to determine whether this has been done
 // before.
@@ -241,16 +257,7 @@
     // to methods that currently use the switch interpreter.
     if (interpreter::CanRuntimeUseNterp()) {
       for (ArtMethod& m : klass->GetMethods(pointer_size)) {
-        if (class_linker->IsQuickToInterpreterBridge(m.GetEntryPointFromQuickCompiledCode()) &&
-            interpreter::CanMethodUseNterp(&m)) {
-          if (klass->IsVisiblyInitialized() || !NeedsClinitCheckBeforeCall(&m)) {
-            runtime->GetInstrumentation()->UpdateMethodsCode(&m, interpreter::GetNterpEntryPoint());
-          } else {
-            // Put the resolution stub, which will initialize the class and then
-            // call the method with nterp.
-            runtime->GetInstrumentation()->UpdateMethodsCode(&m, GetQuickResolutionStub());
-          }
-        }
+        ChangeInterpreterBridgeToNterp(&m, class_linker);
       }
     }
   }
@@ -2195,11 +2202,7 @@
   if (interpreter::CanRuntimeUseNterp()) {
     // Set image methods' entry point that point to the interpreter bridge to the nterp entry point.
     header.VisitPackedArtMethods([&](ArtMethod& method) REQUIRES_SHARED(Locks::mutator_lock_) {
-      if (IsQuickToInterpreterBridge(method.GetEntryPointFromQuickCompiledCode()) &&
-          interpreter::CanMethodUseNterp(&method)) {
-        method.SetEntryPointFromQuickCompiledCodePtrSize(interpreter::GetNterpEntryPoint(),
-                                                         image_pointer_size_);
-      }
+      ChangeInterpreterBridgeToNterp(&method, this);
     }, space->Begin(), image_pointer_size_);
   }
 
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index c6d3258..93d9506 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -147,7 +147,6 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   const Runtime* const runtime = Runtime::Current();
   return
-      runtime->IsStarted() &&
       !runtime->IsAotCompiler() &&
       !runtime->GetInstrumentation()->IsActive() &&
       // mterp only knows how to deal with the normal exits. It cannot handle any of the
diff --git a/runtime/interpreter/mterp/nterp.cc b/runtime/interpreter/mterp/nterp.cc
index f1b6021..2ec142f 100644
--- a/runtime/interpreter/mterp/nterp.cc
+++ b/runtime/interpreter/mterp/nterp.cc
@@ -37,13 +37,20 @@
 }
 
 bool CanRuntimeUseNterp() REQUIRES_SHARED(Locks::mutator_lock_) {
-  // Nterp has the same restrictions as Mterp.
-  return IsNterpSupported() && CanUseMterp();
+  Runtime* runtime = Runtime::Current();
+  instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
+  // Nterp shares the same restrictions as Mterp.
+  // If the runtime is interpreter only, we currently don't use nterp as some
+  // parts of the runtime (like instrumentation) make assumption on an
+  // interpreter-only runtime to always be in a switch-like interpreter.
+  return IsNterpSupported() && CanUseMterp() && !instr->InterpretOnly();
 }
 
 bool CanMethodUseNterp(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
-  return method->SkipAccessChecks() &&
-      !method->IsNative() &&
+  return !method->IsNative() &&
+      method->SkipAccessChecks() &&
+      method->IsInvokable() &&
+      !method->MustCountLocks() &&
       method->GetDexFile()->IsStandardDexFile() &&
       // Proxy methods do not go through the JIT like other methods, so we don't
       // run them with nterp.
@@ -526,11 +533,12 @@
     DCHECK_LE(length, 5);
   }
   uint16_t type_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
-  ObjPtr<mirror::Class> array_class = ResolveVerifyAndClinit(dex::TypeIndex(type_idx),
-                                                             caller,
-                                                             self,
-                                                             /* can_run_clinit= */ true,
-                                                             /* verify_access= */ false);
+  ObjPtr<mirror::Class> array_class =
+      ResolveVerifyAndClinit(dex::TypeIndex(type_idx),
+                             caller,
+                             self,
+                             /* can_run_clinit= */ true,
+                             /* verify_access= */ !caller->SkipAccessChecks());
   if (UNLIKELY(array_class == nullptr)) {
     DCHECK(self->IsExceptionPending());
     return nullptr;
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 5684020..e2df149 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -1481,7 +1481,7 @@
   return added_to_queue;
 }
 
-static bool IgnoreSamplesForMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
+bool Jit::IgnoreSamplesForMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
   if (method->IsClassInitializer() || !method->IsCompilable() || method->IsPreCompiled()) {
     // We do not want to compile such methods.
     return true;
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index e604738..2af58e2 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -320,12 +320,16 @@
 
   void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    AddSamples(self, caller, options_->GetInvokeTransitionWeight(), false);
+    if (!IgnoreSamplesForMethod(caller)) {
+      AddSamples(self, caller, options_->GetInvokeTransitionWeight(), false);
+    }
   }
 
   void NotifyCompiledCodeToInterpreterTransition(Thread* self, ArtMethod* callee)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    AddSamples(self, callee, options_->GetInvokeTransitionWeight(), false);
+    if (!IgnoreSamplesForMethod(callee)) {
+      AddSamples(self, callee, options_->GetInvokeTransitionWeight(), false);
+    }
   }
 
   // Starts the profile saver if the config options allow profile recording.
@@ -445,6 +449,10 @@
  private:
   Jit(JitCodeCache* code_cache, JitOptions* options);
 
+  // Whether we should not add hotness counts for the given method.
+  bool IgnoreSamplesForMethod(ArtMethod* method)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   // Compile an individual method listed in a profile. If `add_to_queue` is
   // true and the method was resolved, return true. Otherwise return false.
   bool CompileMethodFromProfile(Thread* self,