summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tamas Berghammer <tberghammer@google.com> 2016-01-15 13:09:34 +0000
committer David Srbecky <dsrbecky@google.com> 2016-01-18 14:35:14 +0000
commitfffbee4d158259633ec7b7f712eaf75be86bd4e5 (patch)
tree05b9ae8b23be722cf8c2a6a979cc3706437ecf71
parent55380bbe098bace4375d77a2b77d05ef88dfe6f6 (diff)
Report types loaded during init to the native debugger
The runtime loads a lot of type before it creates the jit from the boot image and from hard coded source code (e.g. primitive arrays). This change emits type information for these types after the jit has been created. At the same time we remove the type info generation that happens during AOT compilation because that type information can be modified by a class loader at runtime. Change-Id: Ie5b3b3df9d01c7200a1f670a98d9cbee796234e9
-rw-r--r--compiler/elf_writer_debug.cc46
-rw-r--r--compiler/elf_writer_debug.h4
-rw-r--r--compiler/elf_writer_quick.cc2
-rw-r--r--compiler/jit/jit_compiler.cc5
-rw-r--r--runtime/jit/jit.cc30
-rw-r--r--runtime/jit/jit.h6
-rw-r--r--runtime/runtime.cc3
7 files changed, 47 insertions, 49 deletions
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index 4eb1ca2f03..3e64762096 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -1243,26 +1243,8 @@ class DebugLineWriter {
std::vector<uintptr_t> debug_line_patches;
};
-// Get all types loaded by the runtime.
-static std::vector<mirror::Class*> GetLoadedRuntimeTypes() SHARED_REQUIRES(Locks::mutator_lock_) {
- std::vector<mirror::Class*> result;
- class CollectClasses : public ClassVisitor {
- public:
- virtual bool Visit(mirror::Class* klass) {
- classes_->push_back(klass);
- return true;
- }
- std::vector<mirror::Class*>* classes_;
- };
- CollectClasses visitor;
- visitor.classes_ = &result;
- Runtime::Current()->GetClassLinker()->VisitClasses(&visitor);
- return result;
-}
-
template<typename ElfTypes>
static void WriteDebugSections(ElfBuilder<ElfTypes>* builder,
- bool write_loaded_runtime_types,
const ArrayRef<const MethodDebugInfo>& method_infos) {
// Group the methods into compilation units based on source file.
std::vector<CompilationUnit> compilation_units;
@@ -1291,19 +1273,12 @@ static void WriteDebugSections(ElfBuilder<ElfTypes>* builder,
}
// Write .debug_info section.
- if (!compilation_units.empty() || write_loaded_runtime_types) {
+ if (!compilation_units.empty()) {
DebugInfoWriter<ElfTypes> info_writer(builder);
info_writer.Start();
for (const auto& compilation_unit : compilation_units) {
info_writer.WriteCompilationUnit(compilation_unit);
}
- if (write_loaded_runtime_types) {
- Thread* self = Thread::Current();
- // The lock prevents the classes being moved by the GC.
- ReaderMutexLock mu(self, *Locks::mutator_lock_);
- std::vector<mirror::Class*> types = GetLoadedRuntimeTypes();
- info_writer.WriteTypes(ArrayRef<mirror::Class*>(types.data(), types.size()));
- }
info_writer.End();
}
}
@@ -1370,7 +1345,6 @@ void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
template <typename ElfTypes>
void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
- bool write_loaded_runtime_types,
const ArrayRef<const MethodDebugInfo>& method_infos,
CFIFormat cfi_format) {
// Add methods to .symtab.
@@ -1378,7 +1352,7 @@ void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
// Generate CFI (stack unwinding information).
WriteCFISection(builder, method_infos, cfi_format);
// Write DWARF .debug_* sections.
- WriteDebugSections(builder, write_loaded_runtime_types, method_infos);
+ WriteDebugSections(builder, method_infos);
}
template <typename ElfTypes>
@@ -1391,7 +1365,6 @@ static ArrayRef<const uint8_t> WriteDebugElfFileForMethodInternal(
std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
builder->Start();
WriteDebugInfo(builder.get(),
- false,
ArrayRef<const MethodDebugInfo>(&method_info, 1),
DW_DEBUG_FRAME_FORMAT);
builder->End();
@@ -1413,8 +1386,8 @@ ArrayRef<const uint8_t> WriteDebugElfFileForMethod(const dwarf::MethodDebugInfo&
}
template <typename ElfTypes>
-static ArrayRef<const uint8_t> WriteDebugElfFileForClassInternal(const InstructionSet isa,
- mirror::Class* type)
+static ArrayRef<const uint8_t> WriteDebugElfFileForClassesInternal(
+ const InstructionSet isa, const ArrayRef<mirror::Class*>& types)
SHARED_REQUIRES(Locks::mutator_lock_) {
std::vector<uint8_t> buffer;
buffer.reserve(KB);
@@ -1424,7 +1397,7 @@ static ArrayRef<const uint8_t> WriteDebugElfFileForClassInternal(const Instructi
DebugInfoWriter<ElfTypes> info_writer(builder.get());
info_writer.Start();
- info_writer.WriteTypes(ArrayRef<mirror::Class*>(&type, 1));
+ info_writer.WriteTypes(types);
info_writer.End();
builder->End();
@@ -1436,23 +1409,22 @@ static ArrayRef<const uint8_t> WriteDebugElfFileForClassInternal(const Instructi
return ArrayRef<const uint8_t>(result, buffer.size());
}
-ArrayRef<const uint8_t> WriteDebugElfFileForClass(const InstructionSet isa, mirror::Class* type) {
+ArrayRef<const uint8_t> WriteDebugElfFileForClasses(const InstructionSet isa,
+ const ArrayRef<mirror::Class*>& types) {
if (Is64BitInstructionSet(isa)) {
- return WriteDebugElfFileForClassInternal<ElfTypes64>(isa, type);
+ return WriteDebugElfFileForClassesInternal<ElfTypes64>(isa, types);
} else {
- return WriteDebugElfFileForClassInternal<ElfTypes32>(isa, type);
+ return WriteDebugElfFileForClassesInternal<ElfTypes32>(isa, types);
}
}
// Explicit instantiations
template void WriteDebugInfo<ElfTypes32>(
ElfBuilder<ElfTypes32>* builder,
- bool write_loaded_runtime_types,
const ArrayRef<const MethodDebugInfo>& method_infos,
CFIFormat cfi_format);
template void WriteDebugInfo<ElfTypes64>(
ElfBuilder<ElfTypes64>* builder,
- bool write_loaded_runtime_types,
const ArrayRef<const MethodDebugInfo>& method_infos,
CFIFormat cfi_format);
diff --git a/compiler/elf_writer_debug.h b/compiler/elf_writer_debug.h
index 91da00f97a..e4bc856c5e 100644
--- a/compiler/elf_writer_debug.h
+++ b/compiler/elf_writer_debug.h
@@ -32,13 +32,13 @@ struct MethodDebugInfo;
template <typename ElfTypes>
void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
- bool write_loaded_runtime_types,
const ArrayRef<const MethodDebugInfo>& method_infos,
CFIFormat cfi_format);
ArrayRef<const uint8_t> WriteDebugElfFileForMethod(const dwarf::MethodDebugInfo& method_info);
-ArrayRef<const uint8_t> WriteDebugElfFileForClass(const InstructionSet isa, mirror::Class* type)
+ArrayRef<const uint8_t> WriteDebugElfFileForClasses(const InstructionSet isa,
+ const ArrayRef<mirror::Class*>& types)
SHARED_REQUIRES(Locks::mutator_lock_);
} // namespace dwarf
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index a67f3bd1a9..7b1bdd72e5 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -152,7 +152,7 @@ template <typename ElfTypes>
void ElfWriterQuick<ElfTypes>::WriteDebugInfo(
const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) {
if (compiler_options_->GetGenerateDebugInfo()) {
- dwarf::WriteDebugInfo(builder_.get(), /* write_types */ true, method_infos, kCFIFormat);
+ dwarf::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat);
}
}
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index a4b9c6c0b9..8fdbf4a3f7 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -67,12 +67,13 @@ extern "C" bool jit_compile_method(void* handle, ArtMethod* method, Thread* self
return jit_compiler->CompileMethod(self, method);
}
-extern "C" void jit_type_loaded(void* handle, mirror::Class* type)
+extern "C" void jit_types_loaded(void* handle, mirror::Class** types, size_t count)
SHARED_REQUIRES(Locks::mutator_lock_) {
auto* jit_compiler = reinterpret_cast<JitCompiler*>(handle);
DCHECK(jit_compiler != nullptr);
if (jit_compiler->GetCompilerOptions()->GetGenerateDebugInfo()) {
- ArrayRef<const uint8_t> elf_file = dwarf::WriteDebugElfFileForClass(kRuntimeISA, type);
+ const ArrayRef<mirror::Class*> types_array(types, count);
+ ArrayRef<const uint8_t> elf_file = dwarf::WriteDebugElfFileForClasses(kRuntimeISA, types_array);
CreateJITCodeEntry(std::unique_ptr<const uint8_t[]>(elf_file.data()), elf_file.size());
}
}
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 2a89077388..5c9dab2f38 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -127,11 +127,11 @@ bool Jit::LoadCompiler(std::string* error_msg) {
*error_msg = "JIT couldn't find jit_compile_method entry point";
return false;
}
- jit_type_loaded_ = reinterpret_cast<void (*)(void*, mirror::Class*)>(
- dlsym(jit_library_handle_, "jit_type_loaded"));
- if (jit_type_loaded_ == nullptr) {
+ jit_types_loaded_ = reinterpret_cast<void (*)(void*, mirror::Class**, size_t)>(
+ dlsym(jit_library_handle_, "jit_types_loaded"));
+ if (jit_types_loaded_ == nullptr) {
dlclose(jit_library_handle_);
- *error_msg = "JIT couldn't find jit_type_loaded entry point";
+ *error_msg = "JIT couldn't find jit_types_loaded entry point";
return false;
}
CompilerCallbacks* callbacks = nullptr;
@@ -224,8 +224,26 @@ void Jit::CreateInstrumentationCache(size_t compile_threshold, size_t warmup_thr
void Jit::NewTypeLoadedIfUsingJit(mirror::Class* type) {
jit::Jit* jit = Runtime::Current()->GetJit();
if (jit != nullptr && jit->generate_debug_info_) {
- DCHECK(jit->jit_type_loaded_ != nullptr);
- jit->jit_type_loaded_(jit->jit_compiler_handle_, type);
+ DCHECK(jit->jit_types_loaded_ != nullptr);
+ jit->jit_types_loaded_(jit->jit_compiler_handle_, &type, 1);
+ }
+}
+
+void Jit::DumpTypeInfoForLoadedTypes(ClassLinker* linker) {
+ struct CollectClasses : public ClassVisitor {
+ bool Visit(mirror::Class* klass) override {
+ classes_.push_back(klass);
+ return true;
+ }
+ std::vector<mirror::Class*> classes_;
+ };
+
+ if (generate_debug_info_) {
+ ScopedObjectAccess so(Thread::Current());
+
+ CollectClasses visitor;
+ linker->VisitClasses(&visitor);
+ jit_types_loaded_(jit_compiler_handle_, visitor.classes_.data(), visitor.classes_.size());
}
}
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 443ebe8025..429edf65a6 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -82,6 +82,10 @@ class Jit {
static void NewTypeLoadedIfUsingJit(mirror::Class* type)
SHARED_REQUIRES(Locks::mutator_lock_);
+ // If debug info generation is turned on then write the type information for types already loaded
+ // into the specified class linker to the jit debug interface,
+ void DumpTypeInfoForLoadedTypes(ClassLinker* linker);
+
private:
Jit();
bool LoadCompiler(std::string* error_msg);
@@ -92,7 +96,7 @@ class Jit {
void* (*jit_load_)(CompilerCallbacks**, bool*);
void (*jit_unload_)(void*);
bool (*jit_compile_method_)(void*, ArtMethod*, Thread*);
- void (*jit_type_loaded_)(void*, mirror::Class*);
+ void (*jit_types_loaded_)(void*, mirror::Class**, size_t count);
// Performance monitoring.
bool dump_info_on_shutdown_;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c4694ee291..1101acdf61 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1881,6 +1881,9 @@ void Runtime::CreateJit() {
jit_->CreateInstrumentationCache(jit_options_->GetCompileThreshold(),
jit_options_->GetWarmupThreshold());
jit_->CreateThreadPool();
+
+ // Notify native debugger about the classes already loaded before the creation of the jit.
+ jit_->DumpTypeInfoForLoadedTypes(GetClassLinker());
} else {
LOG(WARNING) << "Failed to create JIT " << error_msg;
}