Cover more cases in nterp.
- Remove Runtime::IsStarted check which was too conservative
- Support running with access checks.
- Explicitly don't support lock counting and not invokable.
Bug: 112676029
Test: test.py
Change-Id: Ie3b45007cb887e5f3af7d4468484a423d9b83f65
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 b025e3d..4be6e77 100644
--- a/runtime/interpreter/mterp/nterp.cc
+++ b/runtime/interpreter/mterp/nterp.cc
@@ -37,13 +37,19 @@
}
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->IsInvokable() &&
+ !method->MustCountLocks() &&
method->GetDexFile()->IsStandardDexFile() &&
NterpGetFrameSize(method) < kMaxNterpFrame;
}
@@ -500,11 +506,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 2ef1cb4..221b373 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -1479,7 +1479,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 e9fd915..ee82af7 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -319,12 +319,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.
@@ -444,6 +448,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,