[Support][MemoryBuffer] Use sys::fs::mapped_file_region instead of sys::Path::MapInFilePages.

This gives us memory mapped file I/O on Windows.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176886 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Michael J. Spencer
2013-03-12 19:28:19 +00:00
parent ad5a5e0427
commit cc189bfb08

View File

@ -72,13 +72,15 @@ static void CopyStringRef(char *Memory, StringRef Data) {
Memory[Data.size()] = 0; // Null terminate string. Memory[Data.size()] = 0; // Null terminate string.
} }
/// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it. struct NamedBufferAlloc {
template <typename T> StringRef Name;
static T *GetNamedBuffer(StringRef Buffer, StringRef Name, NamedBufferAlloc(StringRef Name) : Name(Name) {}
bool RequiresNullTerminator) { };
char *Mem = static_cast<char*>(operator new(sizeof(T) + Name.size() + 1));
CopyStringRef(Mem + sizeof(T), Name); void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
return new (Mem) T(Buffer, RequiresNullTerminator); char *Mem = static_cast<char *>(operator new(N + Alloc.Name.size() + 1));
CopyStringRef(Mem + N, Alloc.Name);
return Mem;
} }
namespace { namespace {
@ -105,8 +107,8 @@ public:
MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData, MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
StringRef BufferName, StringRef BufferName,
bool RequiresNullTerminator) { bool RequiresNullTerminator) {
return GetNamedBuffer<MemoryBufferMem>(InputData, BufferName, return new (NamedBufferAlloc(BufferName))
RequiresNullTerminator); MemoryBufferMem(InputData, RequiresNullTerminator);
} }
/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
@ -183,24 +185,38 @@ error_code MemoryBuffer::getFileOrSTDIN(const char *Filename,
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
namespace { namespace {
/// MemoryBufferMMapFile - This represents a file that was mapped in with the /// \brief Memorry maps a file descriptor using sys::fs::mapped_file_region.
/// sys::Path::MapInFilePages method. When destroyed, it calls the ///
/// sys::Path::UnMapFilePages method. /// This handles converting the offset into a legal offset on the platform.
class MemoryBufferMMapFile : public MemoryBufferMem { class MemoryBufferMMapFile : public MemoryBuffer {
sys::fs::mapped_file_region MFR;
static uint64_t getLegalMapOffset(uint64_t Offset) {
return Offset & ~(sys::fs::mapped_file_region::alignment() - 1);
}
static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) {
return Len + (Offset - getLegalMapOffset(Offset));
}
const char *getStart(uint64_t Len, uint64_t Offset) {
return MFR.const_data() + (Offset - getLegalMapOffset(Offset));
}
public: public:
MemoryBufferMMapFile(StringRef Buffer, bool RequiresNullTerminator) MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len,
: MemoryBufferMem(Buffer, RequiresNullTerminator) { } uint64_t Offset, error_code EC)
: MFR(FD, sys::fs::mapped_file_region::readonly,
getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) {
if (!EC) {
const char *Start = getStart(Len, Offset);
init(Start, Start + Len, RequiresNullTerminator);
}
}
~MemoryBufferMMapFile() { virtual const char *getBufferIdentifier() const LLVM_OVERRIDE {
static int PageSize = sys::process::get_self()->page_size(); // The name is stored after the class itself.
return reinterpret_cast<const char *>(this + 1);
uintptr_t Start = reinterpret_cast<uintptr_t>(getBufferStart());
size_t Size = getBufferSize();
uintptr_t RealStart = Start & ~(PageSize - 1);
size_t RealSize = Size + (Start - RealStart);
sys::Path::UnMapFilePages(reinterpret_cast<const char*>(RealStart),
RealSize);
} }
virtual BufferKind getBufferKind() const LLVM_OVERRIDE { virtual BufferKind getBufferKind() const LLVM_OVERRIDE {
@ -265,7 +281,6 @@ error_code MemoryBuffer::getFile(const char *Filename,
error_code ret = getOpenFile(FD, Filename, result, FileSize, FileSize, error_code ret = getOpenFile(FD, Filename, result, FileSize, FileSize,
0, RequiresNullTerminator); 0, RequiresNullTerminator);
close(FD);
return ret; return ret;
} }
@ -344,18 +359,12 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator, if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
PageSize)) { PageSize)) {
off_t RealMapOffset = Offset & ~(PageSize - 1); error_code EC;
off_t Delta = Offset - RealMapOffset; result.reset(new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile(
size_t RealMapSize = MapSize + Delta; RequiresNullTerminator, FD, MapSize, Offset, EC));
if (!EC)
if (const char *Pages = sys::Path::MapInFilePages(FD,
RealMapSize,
RealMapOffset)) {
result.reset(GetNamedBuffer<MemoryBufferMMapFile>(
StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator));
return error_code::success(); return error_code::success();
} }
}
MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename); MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
if (!Buf) { if (!Buf) {