Do not JIT boot image during native-debugging (keep AOT code instead).
The performance impact is currently significant and being able
to debug framework is not our primary goal for native debugging.
Change-Id: I3366c2a6317004f9dd16700b271a6c9b974f1c6e
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 3c69323..902ba03 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2722,13 +2722,18 @@
return true;
}
- if (runtime->UseJit() && runtime->GetJit()->JitAtFirstUse()) {
- // The force JIT uses the interpreter entry point to execute the JIT.
- return true;
+ if (runtime->IsNativeDebuggable()) {
+ DCHECK(runtime->UseJit() && runtime->GetJit()->JitAtFirstUse());
+ // If we are doing native debugging, ignore application's AOT code,
+ // since we want to JIT it with extra stackmaps for native debugging.
+ // On the other hand, keep all AOT code from the boot image, since the
+ // blocking JIT would results in non-negligible performance impact.
+ return !runtime->GetHeap()->IsInBootImageOatFile(quick_code);
}
if (Dbg::IsDebuggerActive()) {
- // Boot image classes are AOT-compiled as non-debuggable.
+ // Boot image classes may be AOT-compiled as non-debuggable.
+ // This is not suitable for the Java debugger, so ignore the AOT code.
return runtime->GetHeap()->IsInBootImageOatFile(quick_code);
}
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index bc65893..c375bba 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -622,9 +622,11 @@
}
Runtime* runtime = Runtime::Current();
- // Since boot image code is AOT compiled as not debuggable, we need to patch
+ // Since boot image code may be AOT compiled as not debuggable, we need to patch
// entry points of methods in boot image to interpreter bridge.
- if (!runtime->GetInstrumentation()->IsForcedInterpretOnly()) {
+ // However, the performance cost of this is non-negligible during native-debugging due to the
+ // forced JIT, so we keep the AOT code in that case in exchange for limited native debugging.
+ if (!runtime->GetInstrumentation()->IsForcedInterpretOnly() && !runtime->IsNativeDebuggable()) {
ScopedObjectAccess soa(self);
UpdateEntryPointsClassVisitor visitor(runtime->GetInstrumentation());
runtime->GetClassLinker()->VisitClasses(&visitor);
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 65002df..887eee0 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -121,6 +121,7 @@
if ((debug_flags & DEBUG_NATIVE_DEBUGGABLE) != 0) {
runtime->AddCompilerOption("--debuggable");
runtime->AddCompilerOption("--generate-debug-info");
+ runtime->SetNativeDebuggable(true);
debug_flags &= ~DEBUG_NATIVE_DEBUGGABLE;
}
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c8085fb..78e00fd 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -203,6 +203,7 @@
implicit_suspend_checks_(false),
no_sig_chain_(false),
is_native_bridge_loaded_(false),
+ is_native_debuggable_(false),
zygote_max_failed_boots_(0),
experimental_flags_(ExperimentalFlags::kNone),
oat_file_manager_(nullptr),
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 8e99f80..aff7c06 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -583,6 +583,14 @@
bool IsDebuggable() const;
+ bool IsNativeDebuggable() const {
+ return is_native_debuggable_;
+ }
+
+ void SetNativeDebuggable(bool value) {
+ is_native_debuggable_ = value;
+ }
+
// Returns the build fingerprint, if set. Otherwise an empty string is returned.
std::string GetFingerprint() {
return fingerprint_;
@@ -796,6 +804,9 @@
// that there's no native bridge.
bool is_native_bridge_loaded_;
+ // Whether we are running under native debugger.
+ bool is_native_debuggable_;
+
// The maximum number of failed boots we allow before pruning the dalvik cache
// and trying again. This option is only inspected when we're running as a
// zygote.