summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author David Srbecky <dsrbecky@google.com> 2016-01-29 15:02:44 +0000
committer David Srbecky <dsrbecky@google.com> 2016-02-02 14:49:09 +0000
commit7138d45aa915e4873760fa2cc1ca726753f1d9d4 (patch)
tree51452c73b6eccf178b04e84cf2796564f4d11024
parentd111cce1d266567d71be828c4213f3456dbdac2c (diff)
Optimize DWARF namespace encoding.
Instead of encapsulating each class in its own set of namespace tags, create hierarchy with multiple classes in the leaf namespaces. Change-Id: I1fdb717d45e5ee3aa0c505c90a15b1670f45774f
-rw-r--r--compiler/elf_writer_debug.cc73
1 files changed, 49 insertions, 24 deletions
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index 2e98b69c47..6a69d595a3 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -505,7 +505,7 @@ class DebugInfoWriter {
// Enclose the method in correct class definition.
if (last_dex_class_desc != dex_class_desc) {
if (last_dex_class_desc != nullptr) {
- EndClassTag(last_dex_class_desc);
+ EndClassTag();
}
// Write reference tag for the class we are about to declare.
size_t reference_tag_offset = info_.StartTag(DW_TAG_reference_type);
@@ -601,11 +601,12 @@ class DebugInfoWriter {
CHECK_EQ(info_.Depth(), start_depth); // Balanced start/end.
}
if (last_dex_class_desc != nullptr) {
- EndClassTag(last_dex_class_desc);
+ EndClassTag();
}
- CHECK_EQ(info_.Depth(), 1);
FinishLazyTypes();
+ CloseNamespacesAboveDepth(0);
info_.EndTag(); // DW_TAG_compile_unit
+ CHECK_EQ(info_.Depth(), 0);
std::vector<uint8_t> buffer;
buffer.reserve(info_.data()->size() + KB);
const size_t offset = owner_->builder_->GetDebugInfo()->GetSize();
@@ -633,6 +634,7 @@ class DebugInfoWriter {
uint32_t data_offset = mirror::Array::DataOffset(component_size).Uint32Value();
uint32_t length_offset = mirror::Array::LengthOffset().Uint32Value();
+ CloseNamespacesAboveDepth(0); // Declare in root namespace.
info_.StartTag(DW_TAG_array_type);
std::string descriptor_string;
WriteLazyType(element_type->GetDescriptor(&descriptor_string));
@@ -660,7 +662,7 @@ class DebugInfoWriter {
base_class_declaration_offset = StartClassTag(base_class_desc);
info_.WriteFlag(DW_AT_declaration, true);
WriteLinkageName(base_class);
- EndClassTag(base_class_desc);
+ EndClassTag();
}
std::string descriptor_string;
@@ -743,13 +745,14 @@ class DebugInfoWriter {
info_.EndTag(); // DW_TAG_member.
}
- EndClassTag(desc);
+ EndClassTag();
}
}
- CHECK_EQ(info_.Depth(), 1);
FinishLazyTypes();
+ CloseNamespacesAboveDepth(0);
info_.EndTag(); // DW_TAG_compile_unit.
+ CHECK_EQ(info_.Depth(), 0);
std::vector<uint8_t> buffer;
buffer.reserve(info_.data()->size() + KB);
const size_t offset = owner_->builder_->GetDebugInfo()->GetSize();
@@ -958,7 +961,7 @@ class DebugInfoWriter {
// Class type. For example: Lpackage/name;
size_t class_offset = StartClassTag(desc.c_str());
info_.WriteFlag(DW_AT_declaration, true);
- EndClassTag(desc.c_str());
+ EndClassTag();
// Reference to the class type.
offset = info_.StartTag(DW_TAG_reference_type);
info_.WriteRef(DW_AT_type, class_offset);
@@ -966,6 +969,7 @@ class DebugInfoWriter {
} else if (desc[0] == '[') {
// Array type.
size_t element_type = WriteTypeDeclaration(desc.substr(1));
+ CloseNamespacesAboveDepth(0); // Declare in root namespace.
size_t array_type = info_.StartTag(DW_TAG_array_type);
info_.WriteFlag(DW_AT_declaration, true);
info_.WriteRef(DW_AT_type, element_type);
@@ -1028,6 +1032,7 @@ class DebugInfoWriter {
LOG(FATAL) << "Unknown dex type descriptor: \"" << desc << "\"";
UNREACHABLE();
}
+ CloseNamespacesAboveDepth(0); // Declare in root namespace.
offset = info_.StartTag(DW_TAG_base_type);
WriteName(name);
info_.WriteData1(DW_AT_encoding, encoding);
@@ -1042,29 +1047,47 @@ class DebugInfoWriter {
// Start DW_TAG_class_type tag nested in DW_TAG_namespace tags.
// Returns offset of the class tag in the compilation unit.
size_t StartClassTag(const char* desc) {
- DCHECK(desc != nullptr && desc[0] == 'L');
- // Enclose the type in namespace tags.
- const char* end;
- for (desc = desc + 1; (end = strchr(desc, '/')) != nullptr; desc = end + 1) {
- info_.StartTag(DW_TAG_namespace);
- WriteName(std::string(desc, end - desc).c_str());
- }
- // Start the class tag.
+ std::string name = SetNamespaceForClass(desc);
size_t offset = info_.StartTag(DW_TAG_class_type);
- end = strchr(desc, ';');
- CHECK(end != nullptr);
- WriteName(std::string(desc, end - desc).c_str());
+ WriteName(name.c_str());
return offset;
}
- void EndClassTag(const char* desc) {
- DCHECK(desc != nullptr && desc[0] == 'L');
- // End the class tag.
+ void EndClassTag() {
info_.EndTag();
- // Close namespace tags.
- const char* end;
- for (desc = desc + 1; (end = strchr(desc, '/')) != nullptr; desc = end + 1) {
+ }
+
+ // Set the current namespace nesting to one required by the given class.
+ // Returns the class name with namespaces, 'L', and ';' stripped.
+ std::string SetNamespaceForClass(const char* desc) {
+ DCHECK(desc != nullptr && desc[0] == 'L');
+ desc++; // Skip the initial 'L'.
+ size_t depth = 0;
+ for (const char* end; (end = strchr(desc, '/')) != nullptr; desc = end + 1, ++depth) {
+ // Check whether the name at this depth is already what we need.
+ if (depth < current_namespace_.size()) {
+ const std::string& name = current_namespace_[depth];
+ if (name.compare(0, name.size(), desc, end - desc) == 0) {
+ continue;
+ }
+ }
+ // Otherwise we need to open a new namespace tag at this depth.
+ CloseNamespacesAboveDepth(depth);
+ info_.StartTag(DW_TAG_namespace);
+ std::string name(desc, end - desc);
+ WriteName(name.c_str());
+ current_namespace_.push_back(std::move(name));
+ }
+ CloseNamespacesAboveDepth(depth);
+ return std::string(desc, strchr(desc, ';') - desc);
+ }
+
+ // Close namespace tags to reach the given nesting depth.
+ void CloseNamespacesAboveDepth(size_t depth) {
+ DCHECK_LE(depth, current_namespace_.size());
+ while (current_namespace_.size() > depth) {
info_.EndTag();
+ current_namespace_.pop_back();
}
}
@@ -1079,6 +1102,8 @@ class DebugInfoWriter {
// 32-bit references which need to be resolved to a type later.
// Given type may be used multiple times. Therefore we need a multimap.
std::multimap<std::string, size_t> lazy_types_; // type_desc -> patch_offset.
+ // The current set of open namespace tags which are active and not closed yet.
+ std::vector<std::string> current_namespace_;
};
public: