Don't use AOT code for native methods for java debuggable runtime
For java debuggable runtimes we need the capability to deoptimize
the caller to support debug features such as method redefinitions.
To support this we need the ability to call method entry / exit
hooks. Currently this is supported by instrumenting the stack by
updating the return pcs to instrumentation return pcs and installing
instrumentation entry points. This adds additional complexity when
walking the stack and in other places.
We want to avoid this by adding capability to call method entry / exit
hooks directly from JITed code / generic stubs. For generic stubs it
is OK to check if method entry / exit hooks are required always since
generic stubs are on slow path anyway. For JITed code we would enable
this support only for debuggable runtime to avoid any overhead for
regular runtime. Since AOT compiled code doesn't have the capability
to call method entry / exit hooks we want don't want to use them for
debuggable runtime. For non-native methods we don't use AOT code
This CL avoids using AOT code for native methods too.
Test: art/test.py
Bug: 206029744
Change-Id: I566401ebea6d866e818287ede6f000876cb24240
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 867f75c..40b7a7b 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -617,6 +617,15 @@
}
OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromEntryPoint(oat_entry_point);
+ // We could have existing Oat code for native methods but we may not use it if the runtime is java
+ // debuggable or when profiling boot class path. There is no easy way to check if the pc
+ // corresponds to QuickGenericJniStub. Since we have eliminated all the other cases, if the pc
+ // doesn't correspond to the AOT code then we must be running QuickGenericJniStub.
+ if (IsNative() && !method_header->Contains(pc)) {
+ DCHECK_NE(pc, 0u) << "PC 0 for " << PrettyMethod();
+ return nullptr;
+ }
+
DCHECK(method_header->Contains(pc))
<< PrettyMethod()
<< " " << std::hex << pc << " " << oat_entry_point
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 1e328a3..afa7c39 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -300,16 +300,11 @@
Runtime::Current()->GetRuntimeCallbacks()->IsMethodBeingInspected(method);
}
-static bool CanUseAotCode(ArtMethod* method, const void* quick_code)
+static bool CanUseAotCode(const void* quick_code)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (quick_code == nullptr) {
return false;
}
- if (method->IsNative()) {
- // AOT code for native methods can always be used.
- return true;
- }
-
Runtime* runtime = Runtime::Current();
// For simplicity, we never use AOT code for debuggable.
if (runtime->IsJavaDebuggable()) {
@@ -345,7 +340,7 @@
// In debuggable mode, we can only use AOT code for native methods.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
const void* aot_code = method->GetOatMethodQuickCode(class_linker->GetImagePointerSize());
- if (CanUseAotCode(method, aot_code)) {
+ if (CanUseAotCode(aot_code)) {
return aot_code;
}
@@ -404,7 +399,7 @@
}
// Use the provided AOT code if possible.
- if (CanUseAotCode(method, aot_code)) {
+ if (CanUseAotCode(aot_code)) {
UpdateEntryPoints(method, aot_code);
return;
}
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index e20f883..45ca8fe 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -3145,14 +3145,12 @@
for (auto& m : klass->GetMethods(pointer_size)) {
const void* code = m.GetEntryPointFromQuickCompiledCode();
if (Runtime::Current()->GetHeap()->IsInBootImageOatFile(code) &&
- !m.IsNative() &&
!m.IsProxyMethod()) {
instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
}
if (Runtime::Current()->GetJit() != nullptr &&
- Runtime::Current()->GetJit()->GetCodeCache()->IsInZygoteExecSpace(code) &&
- !m.IsNative()) {
+ Runtime::Current()->GetJit()->GetCodeCache()->IsInZygoteExecSpace(code)) {
DCHECK(!m.IsProxyMethod());
instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
}