Use intrusive refcounted pointers to manage RopeRefCountString lifetime.

std::shared_ptr<char []> would be even nicer, but shared_ptr doesn't work
with arrays :(

No functionality change.

llvm-svn: 217798
This commit is contained in:
Benjamin Kramer 2014-09-15 17:58:03 +00:00
parent f090bda1d5
commit fdacdb26af
2 changed files with 14 additions and 48 deletions

View File

@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H #ifndef LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H
#define LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H #define LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
#include <cassert> #include <cassert>
@ -34,11 +35,10 @@ namespace clang {
unsigned RefCount; unsigned RefCount;
char Data[1]; // Variable sized. char Data[1]; // Variable sized.
void addRef() { void Retain() { ++RefCount; }
++RefCount;
}
void dropRef() { void Release() {
assert(RefCount > 0 && "Reference count is already zero.");
if (--RefCount == 0) if (--RefCount == 0)
delete [] (char*)this; delete [] (char*)this;
} }
@ -57,39 +57,15 @@ namespace clang {
/// that both refer to the same underlying RopeRefCountString (just with /// that both refer to the same underlying RopeRefCountString (just with
/// different offsets) which is a nice constant time operation. /// different offsets) which is a nice constant time operation.
struct RopePiece { struct RopePiece {
RopeRefCountString *StrData; llvm::IntrusiveRefCntPtr<RopeRefCountString> StrData;
unsigned StartOffs; unsigned StartOffs;
unsigned EndOffs; unsigned EndOffs;
RopePiece() : StrData(nullptr), StartOffs(0), EndOffs(0) {} RopePiece() : StrData(nullptr), StartOffs(0), EndOffs(0) {}
RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End) RopePiece(llvm::IntrusiveRefCntPtr<RopeRefCountString> Str, unsigned Start,
: StrData(Str), StartOffs(Start), EndOffs(End) { unsigned End)
if (StrData) : StrData(std::move(Str)), StartOffs(Start), EndOffs(End) {}
StrData->addRef();
}
RopePiece(const RopePiece &RP)
: StrData(RP.StrData), StartOffs(RP.StartOffs), EndOffs(RP.EndOffs) {
if (StrData)
StrData->addRef();
}
~RopePiece() {
if (StrData)
StrData->dropRef();
}
void operator=(const RopePiece &RHS) {
if (StrData != RHS.StrData) {
if (StrData)
StrData->dropRef();
StrData = RHS.StrData;
if (StrData)
StrData->addRef();
}
StartOffs = RHS.StartOffs;
EndOffs = RHS.EndOffs;
}
const char &operator[](unsigned Offset) const { const char &operator[](unsigned Offset) const {
return StrData->Data[Offset+StartOffs]; return StrData->Data[Offset+StartOffs];
@ -191,7 +167,7 @@ class RewriteRope {
/// We allocate space for string data out of a buffer of size AllocChunkSize. /// We allocate space for string data out of a buffer of size AllocChunkSize.
/// This keeps track of how much space is left. /// This keeps track of how much space is left.
RopeRefCountString *AllocBuffer; llvm::IntrusiveRefCntPtr<RopeRefCountString> AllocBuffer;
unsigned AllocOffs; unsigned AllocOffs;
enum { AllocChunkSize = 4080 }; enum { AllocChunkSize = 4080 };
@ -201,12 +177,6 @@ public:
: Chunks(RHS.Chunks), AllocBuffer(nullptr), AllocOffs(AllocChunkSize) { : Chunks(RHS.Chunks), AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {
} }
~RewriteRope() {
// If we had an allocation buffer, drop our reference to it.
if (AllocBuffer)
AllocBuffer->dropRef();
}
typedef RopePieceBTree::iterator iterator; typedef RopePieceBTree::iterator iterator;
typedef RopePieceBTree::iterator const_iterator; typedef RopePieceBTree::iterator const_iterator;
iterator begin() const { return Chunks.begin(); } iterator begin() const { return Chunks.begin(); }

View File

@ -788,18 +788,14 @@ RopePiece RewriteRope::MakeRopeString(const char *Start, const char *End) {
// Otherwise, this was a small request but we just don't have space for it // Otherwise, this was a small request but we just don't have space for it
// Make a new chunk and share it with later allocations. // Make a new chunk and share it with later allocations.
if (AllocBuffer)
AllocBuffer->dropRef();
unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize; unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize;
AllocBuffer = reinterpret_cast<RopeRefCountString *>(new char[AllocSize]); RopeRefCountString *Res =
AllocBuffer->RefCount = 0; reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
memcpy(AllocBuffer->Data, Start, Len); Res->RefCount = 0;
memcpy(Res->Data, Start, Len);
AllocBuffer = Res;
AllocOffs = Len; AllocOffs = Len;
// Start out the new allocation with a refcount of 1, since we have an
// internal reference to it.
AllocBuffer->addRef();
return RopePiece(AllocBuffer, 0, Len); return RopePiece(AllocBuffer, 0, Len);
} }