Skip to content

Commit 2963145

Browse files
committed
ContentCache: Simplify by always owning the MemoryBuffer
This changes `ContentCache::Buffer` to use `std::unique_ptr<MemoryBuffer>` instead of the `PointerIntPair`. It drops the (mostly unused) `DoNotFree` bit, instead creating a (new) non-owning `MemoryBuffer` instance when passed a `MemoryBufferRef`. Differential Revision: https://reviews.llvm.org/D67030
1 parent 134ffa8 commit 2963145

File tree

3 files changed

+61
-78
lines changed

3 files changed

+61
-78
lines changed

clang/include/clang/Basic/SourceManager.h

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,9 @@ namespace SrcMgr {
9494
///
9595
/// This object owns the MemoryBuffer object.
9696
class alignas(8) ContentCache {
97-
enum CCFlags {
98-
/// Whether the buffer should not be freed on destruction.
99-
DoNotFreeFlag = 0x02
100-
};
101-
10297
/// The actual buffer containing the characters from the input
10398
/// file.
104-
///
105-
/// This is owned by the ContentCache object. The bits indicate
106-
/// whether the buffer is invalid.
107-
mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer;
99+
mutable std::unique_ptr<llvm::MemoryBuffer> Buffer;
108100

109101
public:
110102
/// Reference to the file entry representing this ContentCache.
@@ -153,30 +145,26 @@ namespace SrcMgr {
153145
ContentCache(const FileEntry *Ent = nullptr) : ContentCache(Ent, Ent) {}
154146

155147
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
156-
: Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
157-
BufferOverridden(false), IsFileVolatile(false), IsTransient(false),
158-
IsBufferInvalid(false) {}
148+
: OrigEntry(Ent), ContentsEntry(contentEnt), BufferOverridden(false),
149+
IsFileVolatile(false), IsTransient(false), IsBufferInvalid(false) {}
159150

160151
/// The copy ctor does not allow copies where source object has either
161152
/// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
162153
/// is not transferred, so this is a logical error.
163154
ContentCache(const ContentCache &RHS)
164-
: Buffer(nullptr, false), BufferOverridden(false),
165-
IsFileVolatile(false), IsTransient(false), IsBufferInvalid(false) {
155+
: BufferOverridden(false), IsFileVolatile(false), IsTransient(false),
156+
IsBufferInvalid(false) {
166157
OrigEntry = RHS.OrigEntry;
167158
ContentsEntry = RHS.ContentsEntry;
168159

169-
assert(RHS.Buffer.getPointer() == nullptr &&
170-
RHS.SourceLineCache == nullptr &&
160+
assert(!RHS.Buffer && RHS.SourceLineCache == nullptr &&
171161
"Passed ContentCache object cannot own a buffer.");
172162

173163
NumLines = RHS.NumLines;
174164
}
175165

176166
ContentCache &operator=(const ContentCache& RHS) = delete;
177167

178-
~ContentCache();
179-
180168
/// Returns the memory buffer for the associated content.
181169
///
182170
/// \param Diag Object through which diagnostics will be emitted if the
@@ -208,17 +196,21 @@ namespace SrcMgr {
208196

209197
/// Get the underlying buffer, returning NULL if the buffer is not
210198
/// yet available.
211-
const llvm::MemoryBuffer *getRawBuffer() const {
212-
return Buffer.getPointer();
213-
}
199+
const llvm::MemoryBuffer *getRawBuffer() const { return Buffer.get(); }
214200

215-
/// Replace the existing buffer (which will be deleted)
216-
/// with the given buffer.
217-
void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false);
201+
/// Set the buffer.
202+
void setBuffer(std::unique_ptr<llvm::MemoryBuffer> B) {
203+
IsBufferInvalid = false;
204+
Buffer = std::move(B);
205+
}
218206

219-
/// Determine whether the buffer should be freed.
220-
bool shouldFreeBuffer() const {
221-
return (Buffer.getInt() & DoNotFreeFlag) == 0;
207+
/// Set the buffer to one that's not owned (or to nullptr).
208+
///
209+
/// \pre Buffer cannot already be set.
210+
void setUnownedBuffer(const llvm::MemoryBuffer *B) {
211+
assert(!Buffer && "Expected to be called right after construction");
212+
if (B)
213+
setBuffer(llvm::MemoryBuffer::getMemBuffer(B->getMemBufferRef()));
222214
}
223215

224216
// If BufStr has an invalid BOM, returns the BOM name; otherwise, returns
@@ -905,16 +897,21 @@ class SourceManager : public RefCountedBase<SourceManager> {
905897
///
906898
/// \param Buffer the memory buffer whose contents will be used as the
907899
/// data in the given source file.
908-
///
909-
/// \param DoNotFree If true, then the buffer will not be freed when the
910-
/// source manager is destroyed.
911-
void overrideFileContents(const FileEntry *SourceFile,
912-
llvm::MemoryBuffer *Buffer, bool DoNotFree);
913900
void overrideFileContents(const FileEntry *SourceFile,
914-
std::unique_ptr<llvm::MemoryBuffer> Buffer) {
915-
overrideFileContents(SourceFile, Buffer.release(), /*DoNotFree*/ false);
901+
const llvm::MemoryBufferRef &Buffer) {
902+
overrideFileContents(SourceFile, llvm::MemoryBuffer::getMemBuffer(Buffer));
916903
}
917904

905+
/// Override the contents of the given source file by providing an
906+
/// already-allocated buffer.
907+
///
908+
/// \param SourceFile the source file whose contents will be overridden.
909+
///
910+
/// \param Buffer the memory buffer whose contents will be used as the
911+
/// data in the given source file.
912+
void overrideFileContents(const FileEntry *SourceFile,
913+
std::unique_ptr<llvm::MemoryBuffer> Buffer);
914+
918915
/// Override the given source file with another one.
919916
///
920917
/// \param SourceFile the source file which will be overridden.

clang/lib/Basic/SourceManager.cpp

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -49,50 +49,31 @@ using llvm::MemoryBuffer;
4949
// SourceManager Helper Classes
5050
//===----------------------------------------------------------------------===//
5151

52-
ContentCache::~ContentCache() {
53-
if (shouldFreeBuffer())
54-
delete Buffer.getPointer();
55-
}
56-
5752
/// getSizeBytesMapped - Returns the number of bytes actually mapped for this
5853
/// ContentCache. This can be 0 if the MemBuffer was not actually expanded.
5954
unsigned ContentCache::getSizeBytesMapped() const {
60-
return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0;
55+
return Buffer ? Buffer->getBufferSize() : 0;
6156
}
6257

6358
/// Returns the kind of memory used to back the memory buffer for
6459
/// this content cache. This is used for performance analysis.
6560
llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const {
66-
assert(Buffer.getPointer());
61+
assert(Buffer);
6762

6863
// Should be unreachable, but keep for sanity.
69-
if (!Buffer.getPointer())
64+
if (!Buffer)
7065
return llvm::MemoryBuffer::MemoryBuffer_Malloc;
7166

72-
const llvm::MemoryBuffer *buf = Buffer.getPointer();
73-
return buf->getBufferKind();
67+
return Buffer->getBufferKind();
7468
}
7569

7670
/// getSize - Returns the size of the content encapsulated by this ContentCache.
7771
/// This can be the size of the source file or the size of an arbitrary
7872
/// scratch buffer. If the ContentCache encapsulates a source file, that
7973
/// file is not lazily brought in from disk to satisfy this query.
8074
unsigned ContentCache::getSize() const {
81-
return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize()
82-
: (unsigned) ContentsEntry->getSize();
83-
}
84-
85-
void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree) {
86-
if (B && B == Buffer.getPointer()) {
87-
assert(0 && "Replacing with the same buffer");
88-
Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
89-
return;
90-
}
91-
92-
if (shouldFreeBuffer())
93-
delete Buffer.getPointer();
94-
Buffer.setPointer(B);
95-
Buffer.setInt((B && DoNotFree) ? DoNotFreeFlag : 0);
75+
return Buffer ? (unsigned)Buffer->getBufferSize()
76+
: (unsigned)ContentsEntry->getSize();
9677
}
9778

9879
const char *ContentCache::getInvalidBOM(StringRef BufStr) {
@@ -125,8 +106,8 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
125106
// computed it, just return what we have.
126107
if (IsBufferInvalid)
127108
return None;
128-
if (auto *B = Buffer.getPointer())
129-
return B->getMemBufferRef();
109+
if (Buffer)
110+
return Buffer->getMemBufferRef();
130111
if (!ContentsEntry)
131112
return None;
132113

@@ -168,7 +149,7 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
168149
return None;
169150
}
170151

171-
Buffer.setPointer(BufferOrError->release());
152+
Buffer = std::move(*BufferOrError);
172153

173154
// Check that the file's size is the same as in the file entry (which may
174155
// have come from a stat cache).
@@ -187,7 +168,7 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
187168
// If the buffer is valid, check to see if it has a UTF Byte Order Mark
188169
// (BOM). We only support UTF-8 with and without a BOM right now. See
189170
// http://en.wikipedia.org/wiki/Byte_order_mark for more information.
190-
StringRef BufStr = Buffer.getPointer()->getBuffer();
171+
StringRef BufStr = Buffer->getBuffer();
191172
const char *InvalidBOM = getInvalidBOM(BufStr);
192173

193174
if (InvalidBOM) {
@@ -197,7 +178,7 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
197178
return None;
198179
}
199180

200-
return Buffer.getPointer()->getMemBufferRef();
181+
return Buffer->getMemBufferRef();
201182
}
202183

203184
unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) {
@@ -380,7 +361,7 @@ void SourceManager::initializeForReplay(const SourceManager &Old) {
380361
Clone->BufferOverridden = Cache->BufferOverridden;
381362
Clone->IsFileVolatile = Cache->IsFileVolatile;
382363
Clone->IsTransient = Cache->IsTransient;
383-
Clone->replaceBuffer(Cache->getRawBuffer(), /*DoNotFree*/true);
364+
Clone->setUnownedBuffer(Cache->getRawBuffer());
384365
return Clone;
385366
};
386367

@@ -441,7 +422,7 @@ const ContentCache *SourceManager::createMemBufferContentCache(
441422
ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
442423
new (Entry) ContentCache();
443424
MemBufferInfos.push_back(Entry);
444-
Entry->replaceBuffer(Buffer.release(), /*DoNotFree=*/false);
425+
Entry->setBuffer(std::move(Buffer));
445426
return Entry;
446427
}
447428

@@ -493,8 +474,7 @@ const SrcMgr::ContentCache *
493474
SourceManager::getFakeContentCacheForRecovery() const {
494475
if (!FakeContentCacheForRecovery) {
495476
FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
496-
FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(),
497-
/*DoNotFree=*/true);
477+
FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
498478
}
499479
return FakeContentCacheForRecovery.get();
500480
}
@@ -700,14 +680,14 @@ SourceManager::getMemoryBufferForFileOrNone(const FileEntry *File) {
700680
return IR->getBufferOrNone(Diag, getFileManager(), SourceLocation());
701681
}
702682

703-
void SourceManager::overrideFileContents(const FileEntry *SourceFile,
704-
llvm::MemoryBuffer *Buffer,
705-
bool DoNotFree) {
706-
const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
683+
void SourceManager::overrideFileContents(
684+
const FileEntry *SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
685+
auto *IR =
686+
const_cast<SrcMgr::ContentCache *>(getOrCreateContentCache(SourceFile));
707687
assert(IR && "getOrCreateContentCache() cannot return NULL");
708688

709-
const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree);
710-
const_cast<SrcMgr::ContentCache *>(IR)->BufferOverridden = true;
689+
IR->setBuffer(std::move(Buffer));
690+
IR->BufferOverridden = true;
711691

712692
getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
713693
}

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,10 +346,16 @@ static void InitializeFileRemapping(DiagnosticsEngine &Diags,
346346
continue;
347347
}
348348

349-
// Override the contents of the "from" file with the contents of
350-
// the "to" file.
351-
SourceMgr.overrideFileContents(FromFile, RB.second,
352-
InitOpts.RetainRemappedFileBuffers);
349+
// Override the contents of the "from" file with the contents of the
350+
// "to" file. If the caller owns the buffers, then pass a MemoryBufferRef;
351+
// otherwise, pass as a std::unique_ptr<MemoryBuffer> to transfer ownership
352+
// to the SourceManager.
353+
if (InitOpts.RetainRemappedFileBuffers)
354+
SourceMgr.overrideFileContents(FromFile, RB.second->getMemBufferRef());
355+
else
356+
SourceMgr.overrideFileContents(
357+
FromFile, std::unique_ptr<llvm::MemoryBuffer>(
358+
const_cast<llvm::MemoryBuffer *>(RB.second)));
353359
}
354360

355361
// Remap files in the source manager (with other files).

0 commit comments

Comments
 (0)