From 492a649b19527cc0e5b835cbcdd717027c30f8e0 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Thu, 1 Jan 2015 17:32:52 -0500 Subject: [PATCH] Debugger: Optimize type lookups. DwarfImageDebugInfo: - On initialization, we now walk the list of compilation units and build a hash table of all of their contained types. The table is then used by GetType() to quickly find the subset of DIEType objects that match the requested name, and then compare only those to the given constraints to find the best match. For a more complex image such as libbe or Debugger itself, this reduces the time for an uncached type lookup from around 50 msec to < 10 usec on my i7. --- .../debug_info/DwarfImageDebugInfo.cpp | 235 ++++++++++++++---- .../debugger/debug_info/DwarfImageDebugInfo.h | 18 +- 2 files changed, 198 insertions(+), 55 deletions(-) diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index 5daff70c33..78faee2d22 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -232,6 +232,97 @@ struct DwarfImageDebugInfo::EntryListWrapper { }; +// #pragma mark - DwarfImageDebugInfo::TypeNameKey + + +struct DwarfImageDebugInfo::TypeNameKey { + BString typeName; + + TypeNameKey(const BString& typeName) + : + typeName(typeName) + { + } + + uint32 HashValue() const + { + return StringUtils::HashValue(typeName); + } + + bool operator==(const TypeNameKey& other) const + { + return typeName == other.typeName; + } +}; + + +// #pragma mark - DwarfImageDebugInfo::TypeNameEntry + + +struct DwarfImageDebugInfo::TypeNameEntry : TypeNameKey { + TypeNameEntry* next; + TypeEntryList types; + + TypeNameEntry(const BString& name) + : + TypeNameKey(name), + types(10, false) + { + } + + ~TypeNameEntry() + { + } + +}; + + +// #pragma mark - DwarfImageDebugInfo::TypeNameEntryHashDefinition + + +struct DwarfImageDebugInfo::TypeNameEntryHashDefinition { + typedef TypeNameKey KeyType; + typedef TypeNameEntry ValueType; + + size_t HashKey(const TypeNameKey& key) const + { + return key.HashValue(); + } + + size_t Hash(const TypeNameEntry* value) const + { + return value->HashValue(); + } + + bool Compare(const TypeNameKey& key, + const TypeNameEntry* value) const + { + return key == *value; + } + + TypeNameEntry*& GetLink(TypeNameEntry* value) const + { + return value->next; + } +}; + + +// #pragma mark - DwarfImageDebugInfo::TypeEntryInfo + + +struct DwarfImageDebugInfo::TypeEntryInfo { + DIEType* type; + CompilationUnit* unit; + + TypeEntryInfo(DIEType* type, CompilationUnit* unit) + : + type(type), + unit(unit) + { + } +}; + + // #pragma mark - DwarfImageDebugInfo @@ -247,6 +338,7 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, fFileManager(fileManager), fTypeLookup(typeLookup), fTypeCache(typeCache), + fTypeNameTable(NULL), fFile(file), fTextSegment(NULL), fRelocationDelta(0), @@ -266,6 +358,8 @@ DwarfImageDebugInfo::~DwarfImageDebugInfo() fDebuggerInterface->ReleaseReference(); fFile->ReleaseReference(); fTypeCache->ReleaseReference(); + + delete fTypeNameTable; } @@ -294,7 +388,7 @@ DwarfImageDebugInfo::Init() fPLTSectionEnd = fPLTSectionStart + section->Size(); } - return B_OK; + return _BuildTypeNameTable(); } @@ -426,64 +520,47 @@ DwarfImageDebugInfo::GetFunctions(const BObjectList& symbols, status_t -DwarfImageDebugInfo::GetType(GlobalTypeCache* cache, - const BString& name, const TypeLookupConstraints& constraints, - Type*& _type) +DwarfImageDebugInfo::GetType(GlobalTypeCache* cache, const BString& name, + const TypeLookupConstraints& constraints, Type*& _type) { - // iterate through all compilation units - for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); - i++) { - DwarfTypeContext* typeContext = NULL; - BReference typeContextReference; + TypeNameEntry* entry = fTypeNameTable->Lookup(name); + if (entry == NULL) + return B_ENTRY_NOT_FOUND; - // iterate through all types of the compilation unit - for (DebugInfoEntryList::ConstIterator it - = unit->UnitEntry()->Types().GetIterator(); - DIEType* typeEntry = dynamic_cast(it.Next());) { - if (typeEntry->IsDeclaration()) + for (int32 i = 0; TypeEntryInfo* info = entry->types.ItemAt(i); i++) { + DIEType* typeEntry = info->type; + if (constraints.HasTypeKind()) { + if (dwarf_tag_to_type_kind(typeEntry->Tag()) + != constraints.TypeKind()) { continue; - - if (constraints.HasTypeKind()) { - if (dwarf_tag_to_type_kind(typeEntry->Tag()) - != constraints.TypeKind()) - continue; - - if (!_EvaluateBaseTypeConstraints(typeEntry, - constraints)) - continue; } - if (constraints.HasSubtypeKind() - && dwarf_tag_to_subtype_kind(typeEntry->Tag()) - != constraints.SubtypeKind()) + if (!_EvaluateBaseTypeConstraints(typeEntry, constraints)) continue; - - BString typeEntryName; - DwarfUtils::GetFullyQualifiedDIEName(typeEntry, typeEntryName); - if (typeEntryName != name) - continue; - - // The name matches and the entry is not just a declaration -- - // create the type. First create the type context lazily. - if (typeContext == NULL) { - typeContext = new(std::nothrow) - DwarfTypeContext(fArchitecture, fImageInfo.ImageID(), fFile, - unit, NULL, 0, 0, fRelocationDelta, NULL, NULL); - if (typeContext == NULL) - return B_NO_MEMORY; - typeContextReference.SetTo(typeContext, true); - } - - // create the type - DwarfType* type; - DwarfTypeFactory typeFactory(typeContext, fTypeLookup, cache); - status_t error = typeFactory.CreateType(typeEntry, type); - if (error != B_OK) - continue; - - _type = type; - return B_OK; } + + if (constraints.HasSubtypeKind() + && dwarf_tag_to_subtype_kind(typeEntry->Tag()) + != constraints.SubtypeKind()) { + continue; + } + + DwarfTypeContext* typeContext = new(std::nothrow) + DwarfTypeContext(fArchitecture, fImageInfo.ImageID(), fFile, + info->unit, NULL, 0, 0, fRelocationDelta, NULL, NULL); + if (typeContext == NULL) + return B_NO_MEMORY; + BReference typeContextReference(typeContext, true); + + // create the type + DwarfType* type; + DwarfTypeFactory typeFactory(typeContext, fTypeLookup, cache); + status_t error = typeFactory.CreateType(typeEntry, type); + if (error != B_OK) + continue; + + _type = type; + return B_OK; } return B_ENTRY_NOT_FOUND; @@ -1162,7 +1239,7 @@ DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos, bool DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType* type, - const TypeLookupConstraints& constraints) + const TypeLookupConstraints& constraints) const { if (constraints.HasBaseTypeName()) { BString baseEntryName; @@ -1204,3 +1281,55 @@ DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType* type, return true; } + + +status_t +DwarfImageDebugInfo::_BuildTypeNameTable() +{ + fTypeNameTable = new(std::nothrow) TypeNameTable; + if (fTypeNameTable == NULL) + return B_NO_MEMORY; + + status_t error = fTypeNameTable->Init(); + if (error != B_OK) + return error; + + // iterate through all compilation units + for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); + i++) { + + // iterate through all types of the compilation unit + for (DebugInfoEntryList::ConstIterator it + = unit->UnitEntry()->Types().GetIterator(); + DIEType* typeEntry = dynamic_cast(it.Next());) { + if (typeEntry->IsDeclaration()) + continue; + + BString typeEntryName; + DwarfUtils::GetFullyQualifiedDIEName(typeEntry, typeEntryName); + + TypeNameEntry* entry = fTypeNameTable->Lookup(typeEntryName); + if (entry == NULL) { + entry = new(std::nothrow) TypeNameEntry(typeEntryName); + if (entry == NULL) + return B_NO_MEMORY; + + error = fTypeNameTable->Insert(entry); + if (error != B_OK) + return error; + } + + TypeEntryInfo* info = new(std::nothrow) TypeEntryInfo(typeEntry, + unit); + if (info == NULL) + return B_NO_MEMORY; + + if (!entry->types.AddItem(info)) { + delete info; + return B_NO_MEMORY; + } + } + } + + return B_OK; +} diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h index 0a2daf2e48..41f1198156 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2010-2013, Rene Gollent, rene@gollent.com. + * Copyright 2010-2014, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef DWARF_IMAGE_DEBUG_INFO_H @@ -90,6 +90,16 @@ private: struct UnwindTargetInterface; struct EntryListWrapper; + struct TypeNameKey; + struct TypeNameEntry; + struct TypeNameEntryHashDefinition; + + typedef BOpenHashTable + TypeNameTable; + + struct TypeEntryInfo; + typedef BObjectList TypeEntryList; + private: status_t _AddSourceCodeInfo(CompilationUnit* unit, FileSourceCode* sourceCode, @@ -112,7 +122,10 @@ private: DwarfStackFrameDebugInfo& factory); bool _EvaluateBaseTypeConstraints(DIEType* type, - const TypeLookupConstraints& constraints); + const TypeLookupConstraints& constraints) + const; + + status_t _BuildTypeNameTable(); private: BLocker fLock; @@ -122,6 +135,7 @@ private: FileManager* fFileManager; GlobalTypeLookup* fTypeLookup; GlobalTypeCache* fTypeCache; + TypeNameTable* fTypeNameTable; DwarfFile* fFile; ElfSegment* fTextSegment; target_addr_t fRelocationDelta;