[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
This commit is contained in:
Reid Kleckner 2019-04-19 22:51:49 +00:00
parent a27252794e
commit a30920c31f
2 changed files with 20 additions and 8 deletions

View File

@ -20,6 +20,9 @@ using namespace llvm::object;
using namespace lld::coff; using namespace lld::coff;
static_assert(sizeof(SymbolUnion) <= 48,
"symbols should be optimized for memory usage");
// Returns a symbol name for an error message. // Returns a symbol name for an error message.
std::string lld::toString(coff::Symbol &B) { std::string lld::toString(coff::Symbol &B) {
if (Config->Demangle) if (Config->Demangle)
@ -39,11 +42,15 @@ StringRef Symbol::getName() {
// name. Object files contain lots of non-external symbols, and creating // name. Object files contain lots of non-external symbols, and creating
// StringRefs for them (which involves lots of strlen() on the string table) // StringRefs for them (which involves lots of strlen() on the string table)
// is a waste of time. // is a waste of time.
if (Name.empty()) { if (NameData == nullptr) {
auto *D = cast<DefinedCOFF>(this); auto *D = cast<DefinedCOFF>(this);
cast<ObjFile>(D->File)->getCOFFObj()->getSymbolName(D->Sym, Name); StringRef NameStr;
cast<ObjFile>(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() { InputFile *Symbol::getFile() {
@ -67,9 +74,10 @@ bool Symbol::isLive() const {
// MinGW specific. // MinGW specific.
void Symbol::replaceKeepingName(Symbol *Other, size_t Size) { void Symbol::replaceKeepingName(Symbol *Other, size_t Size) {
StringRef OrigName = Name; StringRef OrigName = getName();
memcpy(this, Other, Size); memcpy(this, Other, Size);
Name = OrigName; NameData = OrigName.data();
NameSize = OrigName.size();
} }
COFFSymbolRef DefinedCOFF::getCOFFSymbol() { COFFSymbolRef DefinedCOFF::getCOFFSymbol() {

View File

@ -79,7 +79,8 @@ protected:
explicit Symbol(Kind K, StringRef N = "") explicit Symbol(Kind K, StringRef N = "")
: SymbolKind(K), IsExternal(true), IsCOMDAT(false), : SymbolKind(K), IsExternal(true), IsCOMDAT(false),
WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(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; const unsigned SymbolKind : 8;
unsigned IsExternal : 1; unsigned IsExternal : 1;
@ -106,7 +107,10 @@ public:
unsigned IsRuntimePseudoReloc : 1; unsigned IsRuntimePseudoReloc : 1;
protected: 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, // 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 // 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 // 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 // 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 { class DefinedCOFF : public Defined {
friend Symbol; friend Symbol;