diff --git a/lld/Common/CommonLinkerContext.cpp b/lld/Common/CommonLinkerContext.cpp
--- a/lld/Common/CommonLinkerContext.cpp
+++ b/lld/Common/CommonLinkerContext.cpp
@@ -34,6 +34,14 @@
   // new in SpecificAlloc::create().
   for (auto &it : instances)
     it.second->~SpecificAllocBase();
+
+  for (PerThreadContext **context : perThreadContexts) {
+    for (auto &instance : (*context)->instances)
+      instance.second->~SpecificAllocBase();
+    delete *context;
+    // Reset the tls variable 's value to sentinel in case we reuse the threads.
+    *context = nullptr;
+  }
   lctx = nullptr;
 }
 
@@ -48,4 +56,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
@@ -6,12 +6,21 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "lld/Common/Memory.h"
+#include <atomic>
+
 #include "lld/Common/CommonLinkerContext.h"
+#include "lld/Common/Memory.h"
 
 using namespace llvm;
 using namespace lld;
 
+namespace {
+// TODO: may need to move these to CommonLinkerContext class when we support
+// multiple processes.
+// Pointer to this thread's context.
+thread_local PerThreadContext *threadContext = nullptr;
+} // namespace
+
 SpecificAllocBase *
 lld::SpecificAllocBase::getOrCreate(void *tag, size_t size, size_t align,
                                     SpecificAllocBase *(&creator)(void *)) {
@@ -23,3 +32,25 @@
   }
   return instance;
 }
+
+PerThreadContext *CommonLinkerContext::perThreadContext() {
+  if (!threadContext) {
+    // Context didn't exist yet for this thread, so create a new one.
+    threadContext = new PerThreadContext;
+    llvm::sys::ScopedWriter lock(contextMutex);
+    perThreadContexts.push_back(&threadContext);
+  }
+  return threadContext;
+}
+
+SpecificAllocBase *lld::SpecificAllocBase::getOrCreatePerThread(
+    void *tag, size_t size, size_t align,
+    SpecificAllocBase *(&creator)(void *)) {
+  PerThreadContext *threadContext = context().perThreadContext();
+  auto &instance = threadContext->instances[tag];
+  if (!instance) {
+    void *storage = threadContext->bAlloc.Allocate(size, align);
+    instance = creator(storage);
+  }
+  return instance;
+}
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,6 +21,7 @@
 
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Memory.h"
+#include "llvm/Support/RWMutex.h"
 #include "llvm/Support/StringSaver.h"
 
 namespace llvm {
@@ -29,6 +30,18 @@
 
 namespace lld {
 struct SpecificAllocBase;
+
+// Max number of threads ever created in a process.
+constexpr uint32_t MAX_THREADS = std::numeric_limits<uint32_t>::max() - 1;
+
+// TODO Maybe just use the CommonLinkerContext class - but I dont want
+// unnecessary nesting of the mutexes
+struct PerThreadContext {
+  llvm::BumpPtrAllocator bAlloc;
+  llvm::DenseMap<void *, SpecificAllocBase *> instances;
+  llvm::StringSaver saver{bAlloc};
+};
+
 class CommonLinkerContext {
 public:
   CommonLinkerContext();
@@ -41,6 +54,15 @@
   llvm::DenseMap<void *, SpecificAllocBase *> instances;
 
   ErrorHandler e;
+
+  // Per thread allocs and savers.
+  PerThreadContext *perThreadContext();
+
+  // 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<PerThreadContext **> perThreadContexts;
+  llvm::sys::RWMutex contextMutex;
 };
 
 // Retrieve the global state. Currently only one state can exist per process,
@@ -54,8 +76,34 @@
 
 bool hasContext();
 
-inline llvm::StringSaver &saver() { return context().saver; }
-inline llvm::BumpPtrAllocator &bAlloc() { return context().bAlloc; }
+inline llvm::StringSaver &perThreadSaver() {
+  return context().perThreadContext()->saver;
+}
+
+inline llvm::BumpPtrAllocator &perThreadBAlloc() {
+  return context().perThreadContext()->bAlloc;
+}
+
+inline llvm::StringSaver &saverUnsafe() { return context().saver; }
+
+inline llvm::BumpPtrAllocator &bAllocUnsafe() { return context().bAlloc; }
+
+inline llvm::StringSaver &saver() {
+#if THREAD_SAFE_MEMORY
+  return context().saver;
+#else
+  return context().perThreadContext()->saver;
+#endif
+}
+
+inline llvm::BumpPtrAllocator &bAlloc() {
+#if THREAD_SAFE_MEMORY
+  return context().bAlloc;
+#else
+  return context().perThreadContext()->bAlloc;
+#endif
+}
+
 } // 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
@@ -22,14 +22,25 @@
 #define LLD_COMMON_MEMORY_H
 
 #include "llvm/Support/Allocator.h"
+#include "llvm/Support/RWMutex.h"
+
+// TODO: What should be the default value for this?
+#ifndef THREAD_SAFE_MEMORY
+#define THREAD_SAFE_MEMORY 0
+#endif
 
 namespace lld {
+
 // A base class only used by the CommonLinkerContext to keep track of the
 // SpecificAlloc<> instances.
 struct SpecificAllocBase {
   virtual ~SpecificAllocBase() = default;
   static SpecificAllocBase *getOrCreate(void *tag, size_t size, size_t align,
                                         SpecificAllocBase *(&creator)(void *));
+
+  static SpecificAllocBase *
+  getOrCreatePerThread(void *tag, size_t size, size_t align,
+                       SpecificAllocBase *(&creator)(void *));
 };
 
 // An arena of specific types T, created on-demand.
@@ -55,11 +66,42 @@
   return ((SpecificAlloc<T> *)instance)->alloc;
 }
 
+template <typename T>
+inline llvm::SpecificBumpPtrAllocator<T> &getSpecificAllocSingletonPerThread() {
+  SpecificAllocBase *instance = SpecificAllocBase::getOrCreatePerThread(
+      &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.
+// This is NOT thread safe.
+template <typename T, typename... U> T *makeUnsafe(U &&...args) {
+  return new (getSpecificAllocSingleton<T>().Allocate())
+      T(std::forward<U>(args)...);
+}
+
+// Creates new instances of T off a (almost) contiguous arena/object pool
+// specific for this thread. The instances are destroyed whenever lldMain() goes
+// out of scope.
+// This is thread safe.
+template <typename T, typename... U> T *makePerThread(U &&...args) {
+  return new (getSpecificAllocSingletonPerThread<T>().Allocate())
+      T(std::forward<U>(args)...);
+}
+
 // 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) {
+// This may or may not be thread-safe, depending on whether THREAD_SAFE_MEMORY
+// is set.
+template <typename T, typename... U> T *make(U &&...args) {
+#if THREAD_SAFE_MEMORY
   return new (getSpecificAllocSingleton<T>().Allocate())
       T(std::forward<U>(args)...);
+#else
+  return new (getSpecificAllocSingletonPerThread<T>().Allocate())
+      T(std::forward<U>(args)...);
+#endif
 }
 
 } // namespace lld