[PATCH] Add reference counting support to SourceMgr

Alp Toker alp at nuanti.com
Tue Jun 24 22:27:09 PDT 2014


The attached patch switches SourceMgr to use reference counting 
internally by making MemoryBuffer optionally refcounted.

With this change it becomes possible to share ownership of memory 
buffers between multiple source managers in the backend and frontend 
instead of copying file contents into memory or re-reading from disk 
repeatedly.

These are supporting changes for clang with no functional change on the 
LLVM side.

See thread "[PATCH] Don't duplicate entire file contents in memory" 
posted to cfe-commits for details.

Alp.

-- 
http://www.nuanti.com
the browser experts

-------------- next part --------------
diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h
index 8c742c6..a520bc9 100644
--- a/include/llvm/Support/MemoryBuffer.h
+++ b/include/llvm/Support/MemoryBuffer.h
@@ -15,10 +15,12 @@
 #define LLVM_SUPPORT_MEMORYBUFFER_H
 
 #include "llvm-c/Support.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DataTypes.h"
+
 #include <memory>
 #include <system_error>
 
@@ -33,7 +35,11 @@ namespace llvm {
 /// be more efficient for clients which are reading all the data to stop
 /// reading when they encounter a '\0' than to continually check the file
 /// position to see if it has reached the end of the file.
-class MemoryBuffer {
+///
+/// Although this class is optionally refcounted, it is recommended that only
+/// top-level source managers hold IntrusiveRefCntPtr references in order to
+/// maintain clear lifetime semantics.
+class MemoryBuffer : public RefCountedBase<MemoryBuffer> {
   const char *BufferStart; // Start of the buffer.
   const char *BufferEnd;   // End of the buffer.
 
diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h
index 30eccd9..311ffa5 100644
--- a/include/llvm/Support/SourceMgr.h
+++ b/include/llvm/Support/SourceMgr.h
@@ -17,6 +17,7 @@
 #define LLVM_SUPPORT_SOURCEMGR_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/SMLoc.h"
@@ -46,8 +47,10 @@ public:
   typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context);
 private:
   struct SrcBuffer {
+    ~SrcBuffer();
+
     /// The memory buffer for the file.
-    MemoryBuffer *Buffer;
+    IntrusiveRefCntPtr<MemoryBuffer> Buffer;
 
     /// This is the location of the parent include, or null if at the top level.
     SMLoc IncludeLoc;
@@ -94,7 +97,7 @@ public:
 
   const MemoryBuffer *getMemoryBuffer(unsigned i) const {
     assert(i < Buffers.size() && "Invalid Buffer ID!");
-    return Buffers[i].Buffer;
+    return Buffers[i].Buffer.getPtr();
   }
 
   size_t getNumBuffers() const {
@@ -107,14 +110,8 @@ public:
   }
 
   /// Add a new source buffer to this source manager. This takes ownership of
-  /// the memory buffer.
-  size_t AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) {
-    SrcBuffer NB;
-    NB.Buffer = F;
-    NB.IncludeLoc = IncludeLoc;
-    Buffers.push_back(NB);
-    return Buffers.size() - 1;
-  }
+  /// the memory buffer or retains a reference if it is refcounted.
+  size_t AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc);
 
   /// Search for a file with the specified name in the current directory or in
   /// one of the IncludeDirs.
diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp
index 2401ce7..58c69a4 100644
--- a/lib/Support/SourceMgr.cpp
+++ b/lib/Support/SourceMgr.cpp
@@ -42,11 +42,15 @@ SourceMgr::~SourceMgr() {
   // Delete the line # cache if allocated.
   if (LineNoCacheTy *Cache = getCache(LineNoCache))
     delete Cache;
+}
 
-  while (!Buffers.empty()) {
-    delete Buffers.back().Buffer;
-    Buffers.pop_back();
-  }
+SourceMgr::SrcBuffer::~SrcBuffer() {}
+
+size_t SourceMgr::AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) {
+  auto NB = Buffers.insert(Buffers.end(), SrcBuffer());
+  NB->Buffer = F;
+  NB->IncludeLoc = IncludeLoc;
+  return Buffers.size() - 1;
 }
 
 size_t SourceMgr::AddIncludeFile(const std::string &Filename,


More information about the llvm-commits mailing list