summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dex2oat/dex2oat.cc5
-rw-r--r--runtime/class_linker.cc17
-rw-r--r--runtime/class_linker.h6
-rw-r--r--runtime/debugger.cc32
-rw-r--r--runtime/gc/heap.cc9
-rw-r--r--runtime/gc/heap.h3
-rw-r--r--runtime/instrumentation.cc23
-rw-r--r--runtime/instrumentation.h5
-rw-r--r--runtime/oat_file.h4
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();
}