From: Reid Kleckner Date: Fri, 19 Apr 2019 22:51:49 +0000 (+0000) Subject: [COFF] Pack Name in Symbol as is done in ELF X-Git-Tag: llvmorg-10-init~7418 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a30920c31ffed9445ddc96203812fc812936c456;p=platform%2Fupstream%2Fllvm.git [COFF] Pack Name in Symbol as is done in ELF Summary: This assumes all symbols are <4GB long, so we can store them as a 32-bit integer. This reorders the fields so the length appears first, packing with the other bitfield data in the base Symbol object. This saved 70MB / 3.60% of heap allocations when linking browser_tests.exe with no PDB. It's not much as a percentage, but worth doing. I didn't do performance measurements, I don't think it will be measurable in time. Reviewers: ruiu, inglorion, amccarth, aganea Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60297 llvm-svn: 358794 --- diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp index e14785d..a23429e 100644 --- a/lld/COFF/Symbols.cpp +++ b/lld/COFF/Symbols.cpp @@ -20,6 +20,9 @@ using namespace llvm::object; using namespace lld::coff; +static_assert(sizeof(SymbolUnion) <= 48, + "symbols should be optimized for memory usage"); + // Returns a symbol name for an error message. std::string lld::toString(coff::Symbol &B) { if (Config->Demangle) @@ -39,11 +42,15 @@ StringRef Symbol::getName() { // name. Object files contain lots of non-external symbols, and creating // StringRefs for them (which involves lots of strlen() on the string table) // is a waste of time. - if (Name.empty()) { + if (NameData == nullptr) { auto *D = cast(this); - cast(D->File)->getCOFFObj()->getSymbolName(D->Sym, Name); + StringRef NameStr; + cast(D->File)->getCOFFObj()->getSymbolName(D->Sym, NameStr); + NameData = NameStr.data(); + NameSize = NameStr.size(); + assert(NameSize == NameStr.size() && "name length truncated"); } - return Name; + return StringRef(NameData, NameSize); } InputFile *Symbol::getFile() { @@ -67,9 +74,10 @@ bool Symbol::isLive() const { // MinGW specific. void Symbol::replaceKeepingName(Symbol *Other, size_t Size) { - StringRef OrigName = Name; + StringRef OrigName = getName(); memcpy(this, Other, Size); - Name = OrigName; + NameData = OrigName.data(); + NameSize = OrigName.size(); } COFFSymbolRef DefinedCOFF::getCOFFSymbol() { diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h index 718aceb..ee0c0e7 100644 --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -79,7 +79,8 @@ protected: explicit Symbol(Kind K, StringRef N = "") : SymbolKind(K), IsExternal(true), IsCOMDAT(false), WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false), - IsRuntimePseudoReloc(false), Name(N) {} + IsRuntimePseudoReloc(false), NameSize(N.size()), + NameData(N.empty() ? nullptr : N.data()) {} const unsigned SymbolKind : 8; unsigned IsExternal : 1; @@ -106,7 +107,10 @@ public: unsigned IsRuntimePseudoReloc : 1; protected: - StringRef Name; + // Symbol name length. Assume symbol lengths fit in a 32-bit integer. + uint32_t NameSize; + + const char *NameData; }; // The base class for any defined symbols, including absolute symbols, @@ -129,7 +133,7 @@ public: // Symbols defined via a COFF object file or bitcode file. For COFF files, this // stores a coff_symbol_generic*, and names of internal symbols are lazily // loaded through that. For bitcode files, Sym is nullptr and the name is stored -// as a StringRef. +// as a decomposed StringRef. class DefinedCOFF : public Defined { friend Symbol;