diff --git a/lld/Common/CommonLinkerContext.cpp b/lld/Common/CommonLinkerContext.cpp
--- a/lld/Common/CommonLinkerContext.cpp
+++ b/lld/Common/CommonLinkerContext.cpp
@@ -28,12 +28,29 @@
   codegen::RegisterCodeGenFlags CGF;
 }
 
+AllocContext *CommonLinkerContext::alloc() {
+  AllocContext *context = contextIndex.get();
+  if (!context) {
+    // Context didn't exist yet for this thread, so create a new one.
+    context = new AllocContext;
+    contextIndex.set(context);
+
+    llvm::sys::ScopedWriter lock(allContextsMutex);
+    allContexts.push_back(context);
+  }
+  return context;
+}
+
 CommonLinkerContext::~CommonLinkerContext() {
   assert(lctx);
   // Explicitly call the destructors since we created the objects with placement
   // new in SpecificAlloc::create().
-  for (auto &it : instances)
-    it.second->~SpecificAllocBase();
+  llvm::sys::ScopedWriter lock(allContextsMutex);
+  for (AllocContext *context : allContexts) {
+    for (auto &instance : context->instances)
+      instance.second->~SpecificAllocBase();
+    delete context;
+  }
   lctx = nullptr;
 }
 
@@ -48,4 +65,5 @@
   if (lctx == nullptr)
     return;
   delete lctx;
+  lctx = nullptr;
 }
diff --git a/lld/Common/Memory.cpp b/lld/Common/Memory.cpp
--- a/lld/Common/Memory.cpp
+++ b/lld/Common/Memory.cpp
@@ -15,10 +15,10 @@
 SpecificAllocBase *
 lld::SpecificAllocBase::getOrCreate(void *tag, size_t size, size_t align,
                                     SpecificAllocBase *(&creator)(void *)) {
-  auto &instances = context().instances;
-  auto &instance = instances[tag];
-  if (instance == nullptr) {
-    void *storage = context().bAlloc.Allocate(size, align);
+  AllocContext *threadContext = context().alloc();
+  auto &instance = threadContext->instances[tag];
+  if (!instance) {
+    void *storage = threadContext->bAlloc.Allocate(size, align);
     instance = creator(storage);
   }
   return instance;
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -554,9 +554,9 @@
 }
 
 template <typename... T> Defined *makeDefined(T &&...args) {
-  return new (reinterpret_cast<Defined *>(
-      getSpecificAllocSingleton<SymbolUnion>().Allocate()))
-      Defined(std::forward<T>(args)...);
+  auto &bumpAllocator = SpecificAlloc<SymbolUnion>::get().allocator;
+  void *objectStorage = bumpAllocator.Allocate();
+  return new (objectStorage) Defined(std::forward<T>(args)...);
 }
 
 void reportDuplicate(const Symbol &sym, const InputFile *newFile,
diff --git a/lld/include/lld/Common/CommonLinkerContext.h b/lld/include/lld/Common/CommonLinkerContext.h
--- a/lld/include/lld/Common/CommonLinkerContext.h
+++ b/lld/include/lld/Common/CommonLinkerContext.h
@@ -21,7 +21,9 @@
 
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Memory.h"
+#include "llvm/Support/RWMutex.h"
 #include "llvm/Support/StringSaver.h"
+#include "llvm/Support/ThreadLocal.h"
 
 namespace llvm {
 class raw_ostream;
@@ -29,6 +31,13 @@
 
 namespace lld {
 struct SpecificAllocBase;
+
+struct AllocContext {
+  llvm::BumpPtrAllocator bAlloc;
+  llvm::StringSaver saver{bAlloc};
+  llvm::DenseMap<void *, SpecificAllocBase *> instances;
+};
+
 class CommonLinkerContext {
 public:
   CommonLinkerContext();
@@ -36,11 +45,18 @@
 
   static void destroy();
 
-  llvm::BumpPtrAllocator bAlloc;
-  llvm::StringSaver saver{bAlloc};
-  llvm::DenseMap<void *, SpecificAllocBase *> instances;
-
   ErrorHandler e;
+
+  // Returns the thread-local AllocContext.
+  AllocContext *alloc();
+
+private:
+  llvm::sys::ThreadLocal<AllocContext> contextIndex;
+  // Vector of the TLS context's addresses.
+  // We store the TLS variable's addresses so that we can reset the variable's
+  // value from another thread.
+  std::vector<AllocContext *> allContexts;
+  llvm::sys::RWMutex allContextsMutex;
 };
 
 // Retrieve the global state. Currently only one state can exist per process,
@@ -51,11 +67,12 @@
 template <typename T = CommonLinkerContext> T &context() {
   return static_cast<T &>(commonContext());
 }
-
 bool hasContext();
 
-inline llvm::StringSaver &saver() { return context().saver; }
-inline llvm::BumpPtrAllocator &bAlloc() { return context().bAlloc; }
+inline llvm::StringSaver &saver() { return context().alloc()->saver; }
+
+inline llvm::BumpPtrAllocator &bAlloc() { return context().alloc()->bAlloc; }
+
 } // namespace lld
 
 #endif
diff --git a/lld/include/lld/Common/Memory.h b/lld/include/lld/Common/Memory.h
--- a/lld/include/lld/Common/Memory.h
+++ b/lld/include/lld/Common/Memory.h
@@ -33,11 +33,31 @@
 };
 
 // An arena of specific types T, created on-demand.
-template <class T> struct SpecificAlloc : public SpecificAllocBase {
+template <class T> class SpecificAlloc : public SpecificAllocBase {
+  // Ensure that users don't accidentally create instances on the stack.
+  SpecificAlloc() = default;
+
+public:
   static SpecificAllocBase *create(void *storage) {
     return new (storage) SpecificAlloc<T>();
   }
-  llvm::SpecificBumpPtrAllocator<T> alloc;
+
+  // Creates the arena on-demand on the first call; or returns it, if it was
+  // already created.
+  inline static SpecificAlloc<T> &get() {
+    SpecificAllocBase *instance = SpecificAllocBase::getOrCreate(
+        &SpecificAlloc<T>::tag, sizeof(SpecificAlloc<T>),
+        alignof(SpecificAlloc<T>), SpecificAlloc<T>::create);
+    return *(SpecificAlloc<T> *)instance;
+  }
+
+  // Creates new instances of T off a (almost) contiguous arena/object pool. The
+  // instances are destroyed whenever lldMain() goes out of scope.
+  template <typename... U> T *make(U &&...args) {
+    return new (allocator.Allocate()) T(std::forward<U>(args)...);
+  }
+
+  llvm::SpecificBumpPtrAllocator<T> allocator;
   static int tag;
 };
 
@@ -45,21 +65,10 @@
 // CommonLinkerContext::instances. Its value does not matter.
 template <class T> int SpecificAlloc<T>::tag = 0;
 
-// Creates the arena on-demand on the first call; or returns it, if it was
-// already created.
-template <typename T>
-inline llvm::SpecificBumpPtrAllocator<T> &getSpecificAllocSingleton() {
-  SpecificAllocBase *instance = SpecificAllocBase::getOrCreate(
-      &SpecificAlloc<T>::tag, sizeof(SpecificAlloc<T>),
-      alignof(SpecificAlloc<T>), SpecificAlloc<T>::create);
-  return ((SpecificAlloc<T> *)instance)->alloc;
-}
-
 // Creates new instances of T off a (almost) contiguous arena/object pool. The
 // instances are destroyed whenever lldMain() goes out of scope.
 template <typename T, typename... U> T *make(U &&... args) {
-  return new (getSpecificAllocSingleton<T>().Allocate())
-      T(std::forward<U>(args)...);
+  return SpecificAlloc<T>::get().make(std::forward<U>(args)...);
 }
 
 } // namespace lld