diff options
| -rw-r--r-- | dex2oat/dex2oat.cc | 5 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 17 | ||||
| -rw-r--r-- | runtime/class_linker.h | 6 | ||||
| -rw-r--r-- | runtime/debugger.cc | 32 | ||||
| -rw-r--r-- | runtime/gc/heap.cc | 9 | ||||
| -rw-r--r-- | runtime/gc/heap.h | 3 | ||||
| -rw-r--r-- | runtime/instrumentation.cc | 23 | ||||
| -rw-r--r-- | runtime/instrumentation.h | 5 | ||||
| -rw-r--r-- | runtime/oat_file.h | 4 |
9 files changed, 78 insertions, 26 deletions
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index cac12d1920..53331284cb 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -696,11 +696,6 @@ class Dex2Oat FINAL { Usage("Can't have both --image and (--app-image-fd or --app-image-file)"); } - if (IsBootImage()) { - // We need the boot image to always be debuggable. - compiler_options_->debuggable_ = true; - } - if (oat_filenames_.empty() && oat_fd_ == -1) { Usage("Output must be supplied with either --oat-file or --oat-fd"); } diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 9ea082769a..cd4daeb7bd 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2608,18 +2608,6 @@ const void* ClassLinker::GetOatMethodQuickCodeFor(ArtMethod* method) { return nullptr; } -const void* ClassLinker::GetQuickOatCodeFor(const DexFile& dex_file, - uint16_t class_def_idx, - uint32_t method_idx) { - bool found; - OatFile::OatClass oat_class = FindOatClass(dex_file, class_def_idx, &found); - if (!found) { - return nullptr; - } - uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, class_def_idx, method_idx); - return oat_class.GetOatMethod(oat_method_idx).GetQuickCode(); -} - bool ClassLinker::ShouldUseInterpreterEntrypoint(ArtMethod* method, const void* quick_code) { if (UNLIKELY(method->IsNative() || method->IsProxyMethod())) { return false; @@ -2650,6 +2638,11 @@ bool ClassLinker::ShouldUseInterpreterEntrypoint(ArtMethod* method, const void* return true; } + if (Dbg::IsDebuggerActive()) { + // Boot image classes are AOT-compiled as non-debuggable. + return runtime->GetHeap()->IsInBootImageOatFile(quick_code); + } + return false; } diff --git a/runtime/class_linker.h b/runtime/class_linker.h index a9448f732c..aa55dac7be 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -472,12 +472,6 @@ class ClassLinker { const void* GetQuickOatCodeFor(ArtMethod* method) SHARED_REQUIRES(Locks::mutator_lock_); - // Get the oat code for a method from a method index. - const void* GetQuickOatCodeFor(const DexFile& dex_file, - uint16_t class_def_idx, - uint32_t method_idx) - SHARED_REQUIRES(Locks::mutator_lock_); - // Get compiled code for a method, return null if no code // exists. This is unlike Get..OatCodeFor which will return a bridge // or interpreter entrypoint. diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 904490aa8c..bc6589380c 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -28,6 +28,7 @@ #include "class_linker-inl.h" #include "dex_file-inl.h" #include "dex_instruction.h" +#include "entrypoints/runtime_asm_entrypoints.h" #include "gc/accounting/card_table-inl.h" #include "gc/allocation_record.h" #include "gc/scoped_gc_critical_section.h" @@ -570,6 +571,29 @@ bool Dbg::RequiresDeoptimization() { return !Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly(); } +// Used to patch boot image method entry point to interpreter bridge. +class UpdateEntryPointsClassVisitor : public ClassVisitor { + public: + explicit UpdateEntryPointsClassVisitor(instrumentation::Instrumentation* instrumentation) + : instrumentation_(instrumentation) {} + + bool operator()(mirror::Class* klass) OVERRIDE REQUIRES(Locks::mutator_lock_) { + auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); + for (auto& m : klass->GetMethods(pointer_size)) { + const void* code = m.GetEntryPointFromQuickCompiledCode(); + if (Runtime::Current()->GetHeap()->IsInBootImageOatFile(code) && + !m.IsNative() && + !m.IsProxyMethod()) { + instrumentation_->UpdateMethodsCode(&m, GetQuickToInterpreterBridge()); + } + } + return true; + } + + private: + instrumentation::Instrumentation* const instrumentation_; +}; + void Dbg::GoActive() { // Enable all debugging features, including scans for breakpoints. // This is a no-op if we're already active. @@ -598,6 +622,14 @@ void Dbg::GoActive() { } Runtime* runtime = Runtime::Current(); + // Since boot image code is AOT compiled as not debuggable, we need to patch + // entry points of methods in boot image to interpreter bridge. + if (!runtime->GetInstrumentation()->IsForcedInterpretOnly()) { + ScopedObjectAccess soa(self); + UpdateEntryPointsClassVisitor visitor(runtime->GetInstrumentation()); + runtime->GetClassLinker()->VisitClasses(&visitor); + } + ScopedSuspendAll ssa(__FUNCTION__); if (RequiresDeoptimization()) { runtime->GetInstrumentation()->EnableDeoptimization(); diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index a656fb8faf..4bee46285d 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -4058,6 +4058,15 @@ bool Heap::ObjectIsInBootImageSpace(mirror::Object* obj) const { return false; } +bool Heap::IsInBootImageOatFile(const void* p) const { + for (gc::space::ImageSpace* space : boot_image_spaces_) { + if (space->GetOatFile()->Contains(p)) { + return true; + } + } + return false; +} + void Heap::GetBootImagesSize(uint32_t* boot_image_begin, uint32_t* boot_image_end, uint32_t* boot_oat_begin, diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index a181e23b53..6edb548155 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -605,6 +605,9 @@ class Heap { bool ObjectIsInBootImageSpace(mirror::Object* obj) const SHARED_REQUIRES(Locks::mutator_lock_); + bool IsInBootImageOatFile(const void* p) const + SHARED_REQUIRES(Locks::mutator_lock_); + void GetBootImagesSize(uint32_t* boot_image_begin, uint32_t* boot_image_end, uint32_t* boot_oat_begin, diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 748463529e..b107b72b55 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -104,6 +104,14 @@ static void UpdateEntrypoints(ArtMethod* method, const void* quick_code) method->SetEntryPointFromQuickCompiledCode(quick_code); } +bool Instrumentation::NeedDebugVersionForBootImageCode(ArtMethod* method, const void* code) const + SHARED_REQUIRES(Locks::mutator_lock_) { + return Dbg::IsDebuggerActive() && + Runtime::Current()->GetHeap()->IsInBootImageOatFile(code) && + !method->IsNative() && + !method->IsProxyMethod(); +} + void Instrumentation::InstallStubsForMethod(ArtMethod* method) { if (!method->IsInvokable() || method->IsProxyMethod()) { // Do not change stubs for these methods. @@ -124,6 +132,9 @@ void Instrumentation::InstallStubsForMethod(ArtMethod* method) { new_quick_code = GetQuickToInterpreterBridge(); } else if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) { new_quick_code = class_linker->GetQuickOatCodeFor(method); + if (NeedDebugVersionForBootImageCode(method, new_quick_code)) { + new_quick_code = GetQuickToInterpreterBridge(); + } } else { new_quick_code = GetQuickResolutionStub(); } @@ -136,10 +147,13 @@ void Instrumentation::InstallStubsForMethod(ArtMethod* method) { // class, all its static methods code will be set to the instrumentation entry point. // For more details, see ClassLinker::FixupStaticTrampolines. if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) { - if (entry_exit_stubs_installed_) { + new_quick_code = class_linker->GetQuickOatCodeFor(method); + if (NeedDebugVersionForBootImageCode(method, new_quick_code)) { + // Oat code should not be used. Don't install instrumentation stub and + // use interpreter for instrumentation. + new_quick_code = GetQuickToInterpreterBridge(); + } else if (entry_exit_stubs_installed_) { new_quick_code = GetQuickInstrumentationEntryPoint(); - } else { - new_quick_code = class_linker->GetQuickOatCodeFor(method); } } else { new_quick_code = GetQuickResolutionStub(); @@ -775,6 +789,9 @@ void Instrumentation::Undeoptimize(ArtMethod* method) { UpdateEntrypoints(method, GetQuickResolutionStub()); } else { const void* quick_code = class_linker->GetQuickOatCodeFor(method); + if (NeedDebugVersionForBootImageCode(method, quick_code)) { + quick_code = GetQuickToInterpreterBridge(); + } UpdateEntrypoints(method, quick_code); } diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h index e3cbf53873..2e4be6b689 100644 --- a/runtime/instrumentation.h +++ b/runtime/instrumentation.h @@ -247,6 +247,11 @@ class Instrumentation { return forced_interpret_only_; } + // Code is in boot image oat file which isn't compiled as debuggable. + // Need debug version (interpreter or jitted) if that's the case. + bool NeedDebugVersionForBootImageCode(ArtMethod* method, const void* code) const + SHARED_REQUIRES(Locks::mutator_lock_); + bool AreExitStubsInstalled() const { return instrumentation_stubs_installed_; } diff --git a/runtime/oat_file.h b/runtime/oat_file.h index 910163c787..fb91a8cdff 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -228,6 +228,10 @@ class OatFile { return End() - Begin(); } + bool Contains(const void* p) const { + return p >= Begin() && p < End(); + } + size_t BssSize() const { return BssEnd() - BssBegin(); } |