summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter')
-rw-r--r--lld/lib/ReaderWriter/FileArchive.cpp50
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp11
2 files changed, 56 insertions, 5 deletions
diff --git a/lld/lib/ReaderWriter/FileArchive.cpp b/lld/lib/ReaderWriter/FileArchive.cpp
index a344fdf72a7..fe336aa4cea 100644
--- a/lld/lib/ReaderWriter/FileArchive.cpp
+++ b/lld/lib/ReaderWriter/FileArchive.cpp
@@ -17,7 +17,9 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
+#include <future>
#include <memory>
+#include <mutex>
#include <set>
#include <unordered_map>
@@ -57,6 +59,17 @@ public:
return nullptr;
_membersInstantiated.insert(memberStart);
+
+ // Check if a file is preloaded.
+ {
+ std::lock_guard<std::mutex> lock(_mutex);
+ auto it = _preloaded.find(memberStart);
+ if (it != _preloaded.end()) {
+ std::future<const File *> &future = it->second;
+ return future.get();
+ }
+ }
+
std::unique_ptr<File> result;
if (instantiateMember(ci, result))
return nullptr;
@@ -65,6 +78,37 @@ public:
return result.release();
}
+ // Instantiate a member file containing a given symbol name.
+ void preload(TaskGroup &group, StringRef name) override {
+ auto member = _symbolMemberMap.find(name);
+ if (member == _symbolMemberMap.end())
+ return;
+ Archive::child_iterator ci = member->second;
+
+ // Do nothing if a member is already instantiated.
+ const char *memberStart = ci->getBuffer().data();
+ if (_membersInstantiated.count(memberStart))
+ return;
+
+ std::lock_guard<std::mutex> lock(_mutex);
+ if (_preloaded.find(memberStart) != _preloaded.end())
+ return;
+
+ // Instantiate the member
+ auto *promise = new std::promise<const File *>;
+ _preloaded[memberStart] = promise->get_future();
+ _promises.push_back(std::unique_ptr<std::promise<const File *>>(promise));
+
+ group.spawn([=] {
+ std::unique_ptr<File> result;
+ if (instantiateMember(ci, result)) {
+ promise->set_value(nullptr);
+ return;
+ }
+ promise->set_value(result.release());
+ });
+ }
+
/// \brief parse each member
std::error_code
parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
@@ -117,7 +161,8 @@ public:
}
/// Returns a set of all defined symbols in the archive.
- std::set<StringRef> getDefinedSymbols() const override {
+ std::set<StringRef> getDefinedSymbols() override {
+ parse();
std::set<StringRef> ret;
for (const auto &e : _symbolMemberMap)
ret.insert(e.first);
@@ -225,6 +270,9 @@ private:
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
bool _logLoading;
mutable std::vector<std::unique_ptr<MemoryBuffer>> _memberBuffers;
+ mutable std::map<const char *, std::future<const File *>> _preloaded;
+ mutable std::vector<std::unique_ptr<std::promise<const File *>>> _promises;
+ mutable std::mutex _mutex;
};
class ArchiveReader : public Reader {
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
index adcee29f649..dd261614c1c 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -106,6 +106,8 @@ public:
return _absoluteAtoms;
}
+ void beforeLink() override;
+
void addDefinedAtom(AliasAtom *atom) {
atom->setOrdinal(_ordinal++);
_definedAtoms._atoms.push_back(atom);
@@ -382,7 +384,10 @@ std::error_code FileCOFF::doParse() {
// The mapping for /alternatename is in the context object. This helper
// function iterate over defined atoms and create alias atoms if needed.
createAlternateNameAtoms();
+ return std::error_code();
+}
+void FileCOFF::beforeLink() {
// Acquire the mutex to mutate _ctx.
std::lock_guard<std::recursive_mutex> lock(_ctx.getMutex());
@@ -392,10 +397,8 @@ std::error_code FileCOFF::doParse() {
_ctx.setSafeSEH(false);
if (_ctx.deadStrip())
- for (StringRef sym : undefinedSymbols)
- _ctx.addDeadStripRoot(sym);
-
- return std::error_code();
+ for (const UndefinedAtom *undef : undefined())
+ _ctx.addDeadStripRoot(undef->name());
}
/// Iterate over the symbol table to retrieve all symbols.
OpenPOWER on IntegriCloud