Previously we added all undefined symbols found in object files to
the dead strip root. This patch makes the linker to stop doing that.
Undefined symbols would be resolved anyway, so this patch doesn't
change the linker behavior. It should slightly improve performance
but it's really marginal. This is a cleanup.
llvm-svn: 231545
Previously applying 1 million relocations took about 2 seconds on my
Xeon 2.4GHz 8 core workstation. After this patch, it takes about 300
milliseconds. As a result, time to link chrome.dll becomes 23 seconds
to 21 seconds.
llvm-svn: 231454
In the resolver, we maintain a list of undefined symbols, and when we
visit an archive file, we check that file if undefined symbols can be
resolved using files in the archive. The archive file class provides
find() function to lookup a symbol.
Previously, we call find() for each undefined symbols. Archive files
may be visited multiple times if they are in a --start-group and
--end-group. If we visit a file M times and if we have N undefined
symbols, find() is called M*N times. I found that that is one of the
most significant bottlenecks in LLD when linking a large executable.
find() is not a very cheap operation because it looks up a hash table
for a given string. And a string, or a symbol name, can be pretty long
if you are dealing with C++ symbols.
We can eliminate the bottleneck.
Calling find() with the same symbol multiple times is a waste. If a
result of looking up a symbol is "not found", it stays "not found"
forever because the symbol simply doesn't exist in the archive.
Thus, we should call find() only for newly-added undefined symbols.
This optimization makes O(M*N) O(N).
In this patch, all undefined symbols are added to a vector. For each
archive/shared library file, we maintain a start position P. All
symbols [0, P) are already searched. [P, end of the vector) are not
searched yet. For each file, we scan the vector only once.
This patch changes the order in which undefined symbols are looked for.
Previously, we iterated over the result of _symbolTable.undefines().
Now we iterate over the new vector. This is a benign change but caused
differences in output if remaining undefines exist. This is why some
tests are updated.
The performance improvement of this patch seems sometimes significant.
Previously, linking chrome.dll on my workstation (Xeon 2.4GHz 8 cores)
took about 70 seconds. Now it takes (only?) 30 seconds!
http://reviews.llvm.org/D8091
llvm-svn: 231434
_reverseRef is a multimap from atoms to atoms. The map contains
reverse edges of "layout-before" and "group" edges for dead-stripping.
The type of the variable was DenseMap<Atom *, DenseSet<Atom *>>.
This patch changes that to std::unordered_multimap<Atom *, Atom *>.
A DenseMap with a value type of DenseSet was not fast. Inserting 900k
items to the map took about 1.6 seconds on my workstation.
unordered_multimap on the other hand took only 0.6 seconds.
Use of the map also got faster -- originally markLive took 1.3 seconds
in the same test case, and it now took 1.0 seconds. In total we shove
off 1.3 seconds out of 27 seconds in that test case.
llvm-svn: 231432
We maintain a map from symbols to archive files for the archive file
pre-loading. That map is created at the beginning of the resolve()
and is never updated. However, the input file list may be updated by
File::beforeLink(). This is a patch to update the map after beforeLink.
llvm-svn: 231395
I converted them to non-range-based loops in r226883 and r226893
because at that moment File::parse() may have side effects and
may update the vector that the reference returned from
LinkingContext::nodes().
Now File::parse() is free from side effects. We can use range-based
loops again.
llvm-svn: 231321
The last use of layout-after edge for PE/COFF was removed in r231290.
Now layout-after edges do nothing. We can stop adding them to the graph.
No functionality change intended.
llvm-svn: 231301
Merge::mergeByLargestSection is half-baked since it's defined
in terms of section size, there's no way to get the section size
of an atom.
Currently we work around the issue by traversing the layout edges
to both directions and calculate the sum of all atoms reachable.
I wrote that code but I knew it's hacky. It's even not guaranteed
to work. If you add layout edges before the core linking, it
miscalculates a size.
Also it's of course slow. It's basically a linked list traversal.
In this patch I added DefinedAtom::sectionSize so that we can use
that for mergeByLargestSection. I'm not very happy to add a new
field to DefinedAtom base class, but I think it's legitimate since
mergeByLargestSection is defined for section size, and the section
size is currently just missing.
http://reviews.llvm.org/D7966
llvm-svn: 231290
File objects are not really const in the resolver. We set ordinals to
them and call beforeLink hooks. Also, File's member functions marked
as const are not really const. ArchiveFile never returns the same
member file twice, so it remembers files returned before. find() has
side effects.
In order to deal with the inconsistencies, we sprinkled const_casts
and marked member varaibles as mutable.
This patch removes const from there to reflect the reality.
llvm-svn: 231212
std::promise and std::future in old version of libstdc++ are buggy.
I think that's the reason why LLD tests were flaky on Ubuntu 13
buildbots until we disabled file preloading.
In this patch, I implemented very simple future and used that in
FileArchive. Compared to std::promise and std::future, it lacks
many features, but should serve our purpose.
http://reviews.llvm.org/D8025
llvm-svn: 231153
Yet another chapter in the story. We're getting there, finally.
Note for the future: the tests for relocation have a lot of duplication
and probably can be unified in a single file. Let's reevaluate this once
the support will be complete (hopefully, soon).
llvm-svn: 231057
"virtual" was present at a wrong place. FileArchive is a subclass of
ArchiveLibraryFile, and a FileArchive can be deleted through a
pointer of ArchiveLibraryFile. We want to make the destructor of the
base class virtual.
llvm-svn: 231033
This reverts commit r228955. Previously files appear in a .drectve
section are parsed synchronously to avoid threading issues. I believe
it's now safe to do that asynchronously.
llvm-svn: 230905
This reverts commit r230086. I added a lock to guard FileCOFF::doParse(),
which killed parallel file parsing. Now the buildbots got back to green,
I believe the threading issue was resolved, so it's time to remove the
guard to see if it works with the buildbots.
llvm-svn: 230886
Previously we didn't call the hook on a file in an archive, which
let the PE/COFF port fail to link files in archives. It was a
simple mistake. Added a call to the hook and also added a test to
catch that error.
const_cast is an unfortunate hack. Files in the resolver are usually
const, but they are not actually const objects, since they are
mutated if either a file is taken from an archive (an archive file
does never return the same file twice) or the beforeLink hook is
called. Maybe we should just remove const from there -- because they
are not const.
llvm-svn: 230808
In doParse, we shouldn't do anything that has side effects. That function may be
called speculatively and possibly in parallel.
We called WinLinkDriver::parse from doParse to parse a command line in a .drectve
section. The parse function updates a linking context object, so it has many side
effects. It was not safe to call that function from doParse. beforeLink is a
function for a File object to do something that has side effects. Moving a call
of WinLinkDriver::parse to there.
llvm-svn: 230791
If no initial live symbols are set up, and deadStrip() == true,
the Resolver ends up reclaiming all the symbols that aren't absolute. This is wrong.
This patch fixes the issue by setting entrySymbolName() as live, and this allows
us to self-host lld when --gc-sections is enabled. There are still quite a few problems
with --gc-sections (test failures), so the option can't be enabled by default.
Differential Revision: D7926
Reviewed by: ruiu, shankarke
llvm-svn: 230737
It is observed that the function throws std::future_error on a few buildbots.
That cannot be easily reproducible on local machines. Kill the feature
temporarily to see if this is going to fix the buildbot issue.
llvm-svn: 230735
This reverts commit r230732.
sectionSize() in lib/Core/SymbolTable.cpp still depends on the layout-
after edges, so we couldn't remove them yet.
llvm-svn: 230734
Previously we needed to create atoms as a doubly-linked link, but it's
no longer needed. Also we don't use layout-after edges in PE/COFF.
Creating such edges is just waste.
llvm-svn: 230732
Nothing wrong with reinterpret_cast<llvm::support::ulittle32_t *>(loc),
but that's redundant and not great from readability point of view.
The new functions are wrappers for that kind of reinterpet_casts.
Surprisingly or unsurprisingly, there was no use of big endian read
and write. {read,write}{16,32,64}be have no user. But I think they
still worth to be there in the header for completeness.
http://reviews.llvm.org/D7927
llvm-svn: 230725
Previously we have a string -> string map to keep the weak alias
symbol mapping. Naturally we can't define more than one weak alias
with that data structure.
This patch is to allow multiple aliases for the same symbol by
changing the map type to string -> set of string map.
llvm-svn: 230702