llvm-project/lld/COFF/Symbols.cpp

101 lines
3.3 KiB
C++
Raw Normal View History

//===- Symbols.cpp --------------------------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "Symbols.h"
#include "Error.h"
#include "InputFiles.h"
#include "Memory.h"
#include "Strings.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::object;
// Returns a symbol name for an error message.
std::string lld::toString(coff::SymbolBody &B) {
if (Optional<std::string> S = coff::demangle(B.getName()))
return ("\"" + *S + "\" (" + B.getName() + ")").str();
return B.getName();
}
namespace lld {
namespace coff {
[opt] Devirtualize the SymbolBody type hierarchy and start compacting its members into the base class. First, to help motivate this kind of change, understand that in a self-link, LLD creates 5.5 million defined regular symbol bodies (and 6 million symbol bodies total). A significant portion of its time is spent allocating the memory for these symbols, and befor ethis patch the defined regular symbol body objects alone consumed some 420mb of memory during the self link. As a consequence, I think it is worth expending considerable effort to make these objects as memory efficient as possible. This is the first of several components of that. This change starts with the goal of removing the virtual functins from SymbolBody so that it can avoid having a vptr embedded in it when it already contains a "kind" member, and that member can be much more compact than a vptr. The primary way of doing this is to sink as much of the logic that we would have to dispatch for into data in the base class. As part of this, I made the various flags bits that will pack into a bitfield with the kind tag. I also sank the Name down to eliminate the dispatch for that, and used LLVM's RTTI-style dispatch for everything else (most of which is cold and so doesn't matter terribly if we get minutely worse lowering than a vtable dispatch). As I was doing this, I wanted to make the RTTI-dispatch (which would become much hotter than before) as efficient as possible, so I've re-organized the tags somewhat. Notably, the common case (regular defined symbols) is now zero which we can test for faster. I also needed to rewrite the comparison routine used during resolving symbols. This proved to be quite complex as the semantics of the existing one were very subtle due to the back-and-forth virtual dispatch caused by re-dispatching with reversed operands. I've consolidated it to a single function and tried to comment it quite a bit more to help explain what is going on. However, this may need more comments or other explanations. It at least passes all the regression tests. I'm not working on Windows, so I can't fully test it. With all of these changes, the size of a DefinedRegular symbol on a 64-bit build goes from 80 bytes to 64 bytes, and we save approximately 84mb or 20% of the memory consumed by these symbol bodies during the link. The link time appears marginally faster as well, and the profile hotness of the memory allocation subsystem got a bit better, but there is still a lot of allocation traffic. Differential Revision: http://reviews.llvm.org/D10792 llvm-svn: 241001
2015-06-30 05:35:48 +08:00
StringRef SymbolBody::getName() {
// COFF symbol names are read lazily for a performance reason.
[opt] Devirtualize the SymbolBody type hierarchy and start compacting its members into the base class. First, to help motivate this kind of change, understand that in a self-link, LLD creates 5.5 million defined regular symbol bodies (and 6 million symbol bodies total). A significant portion of its time is spent allocating the memory for these symbols, and befor ethis patch the defined regular symbol body objects alone consumed some 420mb of memory during the self link. As a consequence, I think it is worth expending considerable effort to make these objects as memory efficient as possible. This is the first of several components of that. This change starts with the goal of removing the virtual functins from SymbolBody so that it can avoid having a vptr embedded in it when it already contains a "kind" member, and that member can be much more compact than a vptr. The primary way of doing this is to sink as much of the logic that we would have to dispatch for into data in the base class. As part of this, I made the various flags bits that will pack into a bitfield with the kind tag. I also sank the Name down to eliminate the dispatch for that, and used LLVM's RTTI-style dispatch for everything else (most of which is cold and so doesn't matter terribly if we get minutely worse lowering than a vtable dispatch). As I was doing this, I wanted to make the RTTI-dispatch (which would become much hotter than before) as efficient as possible, so I've re-organized the tags somewhat. Notably, the common case (regular defined symbols) is now zero which we can test for faster. I also needed to rewrite the comparison routine used during resolving symbols. This proved to be quite complex as the semantics of the existing one were very subtle due to the back-and-forth virtual dispatch caused by re-dispatching with reversed operands. I've consolidated it to a single function and tried to comment it quite a bit more to help explain what is going on. However, this may need more comments or other explanations. It at least passes all the regression tests. I'm not working on Windows, so I can't fully test it. With all of these changes, the size of a DefinedRegular symbol on a 64-bit build goes from 80 bytes to 64 bytes, and we save approximately 84mb or 20% of the memory consumed by these symbol bodies during the link. The link time appears marginally faster as well, and the profile hotness of the memory allocation subsystem got a bit better, but there is still a lot of allocation traffic. Differential Revision: http://reviews.llvm.org/D10792 llvm-svn: 241001
2015-06-30 05:35:48 +08:00
// Non-external symbol names are never used by the linker except for logging
// or debugging. Their internal references are resolved not by name but by
// symbol index. And because they are not external, no one can refer them by
// 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()) {
auto *D = cast<DefinedCOFF>(this);
cast<ObjFile>(D->File)->getCOFFObj()->getSymbolName(D->Sym, Name);
[opt] Devirtualize the SymbolBody type hierarchy and start compacting its members into the base class. First, to help motivate this kind of change, understand that in a self-link, LLD creates 5.5 million defined regular symbol bodies (and 6 million symbol bodies total). A significant portion of its time is spent allocating the memory for these symbols, and befor ethis patch the defined regular symbol body objects alone consumed some 420mb of memory during the self link. As a consequence, I think it is worth expending considerable effort to make these objects as memory efficient as possible. This is the first of several components of that. This change starts with the goal of removing the virtual functins from SymbolBody so that it can avoid having a vptr embedded in it when it already contains a "kind" member, and that member can be much more compact than a vptr. The primary way of doing this is to sink as much of the logic that we would have to dispatch for into data in the base class. As part of this, I made the various flags bits that will pack into a bitfield with the kind tag. I also sank the Name down to eliminate the dispatch for that, and used LLVM's RTTI-style dispatch for everything else (most of which is cold and so doesn't matter terribly if we get minutely worse lowering than a vtable dispatch). As I was doing this, I wanted to make the RTTI-dispatch (which would become much hotter than before) as efficient as possible, so I've re-organized the tags somewhat. Notably, the common case (regular defined symbols) is now zero which we can test for faster. I also needed to rewrite the comparison routine used during resolving symbols. This proved to be quite complex as the semantics of the existing one were very subtle due to the back-and-forth virtual dispatch caused by re-dispatching with reversed operands. I've consolidated it to a single function and tried to comment it quite a bit more to help explain what is going on. However, this may need more comments or other explanations. It at least passes all the regression tests. I'm not working on Windows, so I can't fully test it. With all of these changes, the size of a DefinedRegular symbol on a 64-bit build goes from 80 bytes to 64 bytes, and we save approximately 84mb or 20% of the memory consumed by these symbol bodies during the link. The link time appears marginally faster as well, and the profile hotness of the memory allocation subsystem got a bit better, but there is still a lot of allocation traffic. Differential Revision: http://reviews.llvm.org/D10792 llvm-svn: 241001
2015-06-30 05:35:48 +08:00
}
return Name;
}
InputFile *SymbolBody::getFile() {
if (auto *Sym = dyn_cast<DefinedCOFF>(this))
return Sym->File;
if (auto *Sym = dyn_cast<Lazy>(this))
return Sym->File;
return nullptr;
}
bool SymbolBody::isLive() const {
if (auto *R = dyn_cast<DefinedRegular>(this))
return R->getChunk()->isLive();
if (auto *Imp = dyn_cast<DefinedImportData>(this))
return Imp->File->Live;
if (auto *Imp = dyn_cast<DefinedImportThunk>(this))
return Imp->WrappedSym->File->Live;
// Assume any other kind of symbol is live.
return true;
}
COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
size_t SymSize = cast<ObjFile>(File)->getCOFFObj()->getSymbolTableEntrySize();
if (SymSize == sizeof(coff_symbol16))
return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(Sym));
assert(SymSize == sizeof(coff_symbol32));
return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym));
}
uint16_t DefinedAbsolute::OutputSectionIndex = 0;
static Chunk *makeImportThunk(DefinedImportData *S, uint16_t Machine) {
if (Machine == AMD64)
return make<ImportThunkChunkX64>(S);
if (Machine == I386)
return make<ImportThunkChunkX86>(S);
if (Machine == ARM64)
return make<ImportThunkChunkARM64>(S);
assert(Machine == ARMNT);
return make<ImportThunkChunkARM>(S);
}
DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S,
uint16_t Machine)
: Defined(DefinedImportThunkKind, Name), WrappedSym(S),
Data(makeImportThunk(S, Machine)) {}
Defined *Undefined::getWeakAlias() {
// A weak alias may be a weak alias to another symbol, so check recursively.
for (SymbolBody *A = WeakAlias; A; A = cast<Undefined>(A)->WeakAlias)
if (auto *D = dyn_cast<Defined>(A))
return D;
return nullptr;
}
} // namespace coff
} // namespace lld