llvm.org GIT mirror llvm / f7fdad1
Add r127409 back now that the windows file was updated. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127417 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 9 years ago
4 changed file(s) with 87 addition(s) and 33 deletion(s). Raw diff Collapse all Expand all
3939 MemoryBuffer &operator=(const MemoryBuffer &); // DO NOT IMPLEMENT
4040 protected:
4141 MemoryBuffer() {}
42 void init(const char *BufStart, const char *BufEnd);
42 void init(const char *BufStart, const char *BufEnd,
43 bool RequiresNullTerminator);
4344 public:
4445 virtual ~MemoryBuffer();
4546
7172 /// return a MemoryBuffer.
7273 static error_code getOpenFile(int FD, const char *Filename,
7374 OwningPtr &result,
74 int64_t FileSize = -1);
75 size_t FileSize = -1,
76 size_t MapSize = -1,
77 off_t Offset = 0,
78 bool RequiresNullTerminator = true);
7579
7680 /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note
7781 /// that InputData must be null terminated.
607607 ///
608608 /// This API is not intended for general use, clients should use
609609 /// MemoryBuffer::getFile instead.
610 static const char *MapInFilePages(int FD, uint64_t FileSize);
610 static const char *MapInFilePages(int FD, size_t FileSize,
611 off_t Offset);
611612
612613 /// UnMapFilePages - Free pages mapped into the current process by
613614 /// MapInFilePages.
614615 ///
615616 /// This API is not intended for general use, clients should use
616617 /// MemoryBuffer::getFile instead.
617 static void UnMapFilePages(const char *Base, uint64_t FileSize);
618 static void UnMapFilePages(const char *Base, size_t FileSize);
618619
619620 /// @}
620621 /// @name Data
4545
4646 /// init - Initialize this MemoryBuffer as a reference to externally allocated
4747 /// memory, memory that we know is already null terminated.
48 void MemoryBuffer::init(const char *BufStart, const char *BufEnd) {
49 assert(BufEnd[0] == 0 && "Buffer is not null terminated!");
48 void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
49 bool RequiresNullTerminator) {
50 assert((BufEnd[0] == 0 || !RequiresNullTerminator) &&
51 "Buffer is not null terminated!");
5052 BufferStart = BufStart;
5153 BufferEnd = BufEnd;
5254 }
6466
6567 /// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it.
6668 template
67 static T* GetNamedBuffer(StringRef Buffer, StringRef Name) {
69 static T* GetNamedBuffer(StringRef Buffer, StringRef Name,
70 bool RequiresNullTerminator) {
6871 char *Mem = static_cast(operator new(sizeof(T) + Name.size() + 1));
6972 CopyStringRef(Mem + sizeof(T), Name);
70 return new (Mem) T(Buffer);
73 return new (Mem) T(Buffer, RequiresNullTerminator);
7174 }
7275
7376 namespace {
7477 /// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
7578 class MemoryBufferMem : public MemoryBuffer {
7679 public:
77 MemoryBufferMem(StringRef InputData) {
78 init(InputData.begin(), InputData.end());
80 MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
81 init(InputData.begin(), InputData.end(), RequiresNullTerminator);
7982 }
8083
8184 virtual const char *getBufferIdentifier() const {
8992 /// that EndPtr[0] must be a null byte and be accessible!
9093 MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
9194 StringRef BufferName) {
92 return GetNamedBuffer(InputData, BufferName);
95 return GetNamedBuffer(InputData, BufferName, true);
9396 }
9497
9598 /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
126129 char *Buf = Mem + AlignedStringLen;
127130 Buf[Size] = 0; // Null terminate buffer.
128131
129 return new (Mem) MemoryBufferMem(StringRef(Buf, Size));
132 return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
130133 }
131134
132135 /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
171174 /// sys::Path::UnMapFilePages method.
172175 class MemoryBufferMMapFile : public MemoryBufferMem {
173176 public:
174 MemoryBufferMMapFile(StringRef Buffer)
175 : MemoryBufferMem(Buffer) { }
177 MemoryBufferMMapFile(StringRef Buffer, bool RequiresNullTerminator)
178 : MemoryBufferMem(Buffer, RequiresNullTerminator) { }
176179
177180 ~MemoryBufferMMapFile() {
178 sys::Path::UnMapFilePages(getBufferStart(), getBufferSize());
181 static int PageSize = sys::Process::GetPageSize();
182
183 uintptr_t Start = reinterpret_cast(getBufferStart());
184 size_t Size = getBufferSize();
185 uintptr_t RealStart = Start & ~(PageSize - 1);
186 size_t RealSize = Size + (Start - RealStart);
187
188 sys::Path::UnMapFilePages(reinterpret_cast(RealStart),
189 RealSize);
179190 }
180191 };
181192 }
204215 return ret;
205216 }
206217
218 static bool shouldUseMmap(size_t FileSize,
219 size_t MapSize,
220 off_t Offset,
221 bool RequiresNullTerminator,
222 int PageSize) {
223 // We don't use mmap for small files because this can severely fragment our
224 // address space.
225 if (MapSize < 4096*4)
226 return false;
227
228 if (!RequiresNullTerminator)
229 return true;
230
231 // If we need a null terminator and the end of the map is inside the file,
232 // we cannot use mmap.
233 size_t End = Offset + MapSize;
234 assert(End <= FileSize);
235 if (End != FileSize)
236 return false;
237
238 // Don't try to map files that are exactly a multiple of the system page size
239 // if we need a null terminator.
240 if ((FileSize & (PageSize -1)) == 0)
241 return false;
242
243 return true;
244 }
245
207246 error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
208247 OwningPtr &result,
209 int64_t FileSize) {
248 size_t FileSize, size_t MapSize,
249 off_t Offset,
250 bool RequiresNullTerminator) {
251 static int PageSize = sys::Process::GetPageSize();
252
210253 // If we don't know the file size, use fstat to find out. fstat on an open
211254 // file descriptor is cheaper than stat on a random path.
212 if (FileSize == -1) {
255 if (FileSize == size_t(-1)) {
213256 struct stat FileInfo;
214257 // TODO: This should use fstat64 when available.
215258 if (fstat(FD, &FileInfo) == -1) {
218261 FileSize = FileInfo.st_size;
219262 }
220263
221
222 // If the file is large, try to use mmap to read it in. We don't use mmap
223 // for small files, because this can severely fragment our address space. Also
224 // don't try to map files that are exactly a multiple of the system page size,
225 // as the file would not have the required null terminator.
226 //
227 // FIXME: Can we just mmap an extra page in the latter case?
228 if (FileSize >= 4096*4 &&
229 (FileSize & (sys::Process::GetPageSize()-1)) != 0) {
230 if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) {
264 // Default is to map the full file.
265 if (MapSize == size_t(-1))
266 MapSize = FileSize;
267
268 if (shouldUseMmap(FileSize, MapSize, Offset, RequiresNullTerminator,
269 PageSize)) {
270 off_t RealMapOffset = Offset & ~(PageSize - 1);
271 off_t Delta = Offset - RealMapOffset;
272 size_t RealMapSize = MapSize + Delta;
273
274 if (const char *Pages = sys::Path::MapInFilePages(FD,
275 RealMapSize,
276 RealMapOffset)) {
231277 result.reset(GetNamedBuffer(
232 StringRef(Pages, FileSize), Filename));
278 StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator));
233279 return success;
234280 }
235281 }
236282
237 MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename);
283 MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
238284 if (!Buf) {
239285 // Failed to create a buffer. The only way it can fail is if
240286 // new(std::nothrow) returns 0.
244290 OwningPtr SB(Buf);
245291 char *BufPtr = const_cast(SB->getBufferStart());
246292
247 size_t BytesLeft = FileSize;
293 size_t BytesLeft = MapSize;
294 if (lseek(FD, Offset, SEEK_SET) == -1)
295 return error_code(errno, posix_category());
296
248297 while (BytesLeft) {
249298 ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
250299 if (NumRead == -1) {
868868 return false;
869869 }
870870
871 const char *Path::MapInFilePages(int FD, uint64_t FileSize) {
871 const char *Path::MapInFilePages(int FD, size_t FileSize, off_t Offset) {
872872 int Flags = MAP_PRIVATE;
873873 #ifdef MAP_FILE
874874 Flags |= MAP_FILE;
875875 #endif
876 void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, 0);
876 void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, Offset);
877877 if (BasePtr == MAP_FAILED)
878878 return 0;
879879 return (const char*)BasePtr;
880880 }
881881
882 void Path::UnMapFilePages(const char *BasePtr, uint64_t FileSize) {
882 void Path::UnMapFilePages(const char *BasePtr, size_t FileSize) {
883883 ::munmap((void*)BasePtr, FileSize);
884884 }
885885