Index: include/lld/Core/Parallel.h
===================================================================
--- include/lld/Core/Parallel.h
+++ include/lld/Core/Parallel.h
@@ -68,6 +68,41 @@
   }
 };
 
+/// \brief An implementation of future. std:future and std::promise in
+/// libstdc++ had a threading bug; there is a small chance that a call
+/// of future::get throws an exception in the normal use case. We want
+/// to use our own future implementation until we drop support of old
+/// version of libstdc++.
+/// https://gcc.gnu.org/ml/gcc-patches/2014-05/msg01389.html
+template<typename T> class Future {
+public:
+  Future() : _hasValue(false) {}
+
+  void set(T &&val) {
+    assert(!_hasValue);
+    {
+      std::unique_lock<std::mutex> lock(_mutex);
+      _val = val;
+      _hasValue = true;
+    }
+    _cond.notify_all();
+  }
+
+  T &get() {
+    std::unique_lock<std::mutex> lock(_mutex);
+    if (_hasValue)
+      return _val;
+    _cond.wait(lock, [&] { return _hasValue; });
+    return _val;
+  }
+
+private:
+  T _val;
+  bool _hasValue;
+  std::mutex _mutex;
+  std::condition_variable _cond;
+};
+
 /// \brief An abstract class that takes closures and runs them asynchronously.
 class Executor {
 public:
Index: lib/Core/Resolver.cpp
===================================================================
--- lib/Core/Resolver.cpp
+++ lib/Core/Resolver.cpp
@@ -31,9 +31,12 @@
   bool undefAdded = false;
   for (const DefinedAtom *atom : file.defined())
     doDefinedAtom(*atom);
-  for (const UndefinedAtom *atom : file.undefined())
-    if (doUndefinedAtom(*atom))
+  for (const UndefinedAtom *atom : file.undefined()) {
+    if (doUndefinedAtom(*atom)) {
       undefAdded = true;
+      maybePreloadArchiveMember(atom->name());
+    }
+  }
   for (const SharedLibraryAtom *atom : file.sharedLibrary())
     doSharedLibraryAtom(*atom);
   for (const AbsoluteAtom *atom : file.absolute())
@@ -230,6 +233,17 @@
     doDefinedAtom(*newAtom);
 }
 
+// Instantiate an archive file member if there's a file containing a
+// defined symbol for a given symbol name. Instantiation is done in a
+// different worker thread and has no visible side effect.
+void Resolver::maybePreloadArchiveMember(StringRef sym) {
+  auto it = _archiveMap.find(sym);
+  if (it == _archiveMap.end())
+    return;
+  ArchiveLibraryFile *archive = it->second;
+  archive->preload(_ctx.getTaskGroup(), sym);
+}
+
 // Returns true if at least one of N previous files has created an
 // undefined symbol.
 bool Resolver::undefinesAdded(int begin, int end) {
Index: lib/ReaderWriter/FileArchive.cpp
===================================================================
--- lib/ReaderWriter/FileArchive.cpp
+++ lib/ReaderWriter/FileArchive.cpp
@@ -10,6 +10,7 @@
 #include "lld/Core/ArchiveLibraryFile.h"
 #include "lld/Core/LLVM.h"
 #include "lld/Core/LinkingContext.h"
+#include "lld/Core/Parallel.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/Archive.h"
@@ -17,7 +18,6 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/MemoryBuffer.h"
-#include <future>
 #include <memory>
 #include <mutex>
 #include <set>
@@ -63,8 +63,9 @@
       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<Future<const File *>> &p = it->second;
+        Future<const File *> *future = p.get();
+        return future->get();
       }
     }
 
@@ -93,17 +94,13 @@
       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));
+    auto *future = new Future<const File *>();
+    _preloaded[memberStart] = std::unique_ptr<Future<const File *>>(future);
 
     group.spawn([=] {
       std::unique_ptr<File> result;
-      if (instantiateMember(ci, result)) {
-        promise->set_value(nullptr);
-        return;
-      }
-      promise->set_value(result.release());
+      std::error_code ec = instantiateMember(ci, result);
+      future->set(ec ? nullptr : result.release());
     });
   }
 
@@ -269,8 +266,7 @@
   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::map<const char *, std::unique_ptr<Future<const File *>>> _preloaded;
   mutable std::mutex _mutex;
 };