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);
}
}
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);
if ((debug_flags & DEBUG_NATIVE_DEBUGGABLE) != 0) {
runtime->AddCompilerOption("--debuggable");
runtime->AddCompilerOption("--generate-debug-info");
+ runtime->SetNativeDebuggable(true);
debug_flags &= ~DEBUG_NATIVE_DEBUGGABLE;
}
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),
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_;
// 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.