diff options
author | 2016-02-01 14:53:48 +0000 | |
---|---|---|
committer | 2016-02-02 14:49:37 +0000 | |
commit | c7eecf9d20de7a7a9c251279248fa0f5c3e376dd (patch) | |
tree | 713447a59e3d1990a6eaeb74f9c57a973bd07c44 | |
parent | fa5ec2b447371008277c457a963fdbd32997aab8 (diff) |
Avoid re-declarations of base classes in DWARF.
Declare each base class only once for sanity and to save space.
If the class also has definition, use it instead.
Change-Id: I07cca012d0db75980b1239f44c6cb4069c3f353e
-rw-r--r-- | compiler/elf_writer_debug.cc | 47 |
1 files changed, 32 insertions, 15 deletions
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc index b93c9dfb81..5dbbbc7e96 100644 --- a/compiler/elf_writer_debug.cc +++ b/compiler/elf_writer_debug.cc @@ -621,6 +621,12 @@ class DebugInfoWriter { info_.WriteStrp(DW_AT_producer, owner_->WriteString("Android dex2oat")); info_.WriteData1(DW_AT_language, DW_LANG_Java); + // Base class references to be patched at the end. + std::map<size_t, mirror::Class*> base_class_references; + + // Already written declarations or definitions. + std::map<mirror::Class*, size_t> class_declarations; + std::vector<uint8_t> expr_buffer; for (mirror::Class* type : types) { if (type->IsPrimitive()) { @@ -652,22 +658,10 @@ class DebugInfoWriter { // Skip. Variables cannot have an interface as a dynamic type. // We do not expose the interface information to the debugger in any way. } else { - // Declare base class. We can not use the standard WriteLazyType - // since we want to avoid the DW_TAG_reference_tag wrapping. - mirror::Class* base_class = type->GetSuperClass(); - size_t base_class_declaration_offset = 0; - if (base_class != nullptr) { - std::string tmp_storage; - const char* base_class_desc = base_class->GetDescriptor(&tmp_storage); - base_class_declaration_offset = StartClassTag(base_class_desc); - info_.WriteFlagPresent(DW_AT_declaration); - WriteLinkageName(base_class); - EndClassTag(); - } - std::string descriptor_string; const char* desc = type->GetDescriptor(&descriptor_string); - StartClassTag(desc); + size_t class_offset = StartClassTag(desc); + class_declarations.emplace(type, class_offset); if (!type->IsVariableSize()) { info_.WriteUdata(DW_AT_byte_size, type->GetObjectSize()); @@ -704,9 +698,11 @@ class DebugInfoWriter { } // Base class. + mirror::Class* base_class = type->GetSuperClass(); if (base_class != nullptr) { info_.StartTag(DW_TAG_inheritance); - info_.WriteRef4(DW_AT_type, base_class_declaration_offset); + base_class_references.emplace(info_.size(), base_class); + info_.WriteRef4(DW_AT_type, 0); info_.WriteUdata(DW_AT_data_member_location, 0); info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_public); info_.EndTag(); // DW_TAG_inheritance. @@ -749,6 +745,27 @@ class DebugInfoWriter { } } + // Write base class declarations. + for (const auto& base_class_reference : base_class_references) { + size_t reference_offset = base_class_reference.first; + mirror::Class* base_class = base_class_reference.second; + const auto& it = class_declarations.find(base_class); + if (it != class_declarations.end()) { + info_.UpdateUint32(reference_offset, it->second); + } else { + // Declare base class. We can not use the standard WriteLazyType + // since we want to avoid the DW_TAG_reference_tag wrapping. + std::string tmp_storage; + const char* base_class_desc = base_class->GetDescriptor(&tmp_storage); + size_t base_class_declaration_offset = StartClassTag(base_class_desc); + info_.WriteFlagPresent(DW_AT_declaration); + WriteLinkageName(base_class); + EndClassTag(); + class_declarations.emplace(base_class, base_class_declaration_offset); + info_.UpdateUint32(reference_offset, base_class_declaration_offset); + } + } + FinishLazyTypes(); CloseNamespacesAboveDepth(0); info_.EndTag(); // DW_TAG_compile_unit. |