llvm.org GIT mirror llvm / 4b0e1f1
Revert r127409 which broke all the Windows bots. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127413 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 9 years ago
4 changed file(s) with 33 addition(s) and 87 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,
43 bool RequiresNullTerminator);
42 void init(const char *BufStart, const char *BufEnd);
4443 public:
4544 virtual ~MemoryBuffer();
4645
7271 /// return a MemoryBuffer.
7372 static error_code getOpenFile(int FD, const char *Filename,
7473 OwningPtr &result,
75 size_t FileSize = -1,
76 size_t MapSize = -1,
77 off_t Offset = 0,
78 bool RequiresNullTerminator = true);
74 int64_t FileSize = -1);
7975
8076 /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note
8177 /// 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, size_t FileSize,
611 off_t Offset);
610 static const char *MapInFilePages(int FD, uint64_t FileSize);
612611
613612 /// UnMapFilePages - Free pages mapped into the current process by
614613 /// MapInFilePages.
615614 ///
616615 /// This API is not intended for general use, clients should use
617616 /// MemoryBuffer::getFile instead.
618 static void UnMapFilePages(const char *Base, size_t FileSize);
617 static void UnMapFilePages(const char *Base, uint64_t FileSize);
619618
620619 /// @}
621620 /// @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 bool RequiresNullTerminator) {
50 assert((BufEnd[0] == 0 || !RequiresNullTerminator) &&
51 "Buffer is not null terminated!");
48 void MemoryBuffer::init(const char *BufStart, const char *BufEnd) {
49 assert(BufEnd[0] == 0 && "Buffer is not null terminated!");
5250 BufferStart = BufStart;
5351 BufferEnd = BufEnd;
5452 }
6664
6765 /// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it.
6866 template
69 static T* GetNamedBuffer(StringRef Buffer, StringRef Name,
70 bool RequiresNullTerminator) {
67 static T* GetNamedBuffer(StringRef Buffer, StringRef Name) {
7168 char *Mem = static_cast(operator new(sizeof(T) + Name.size() + 1));
7269 CopyStringRef(Mem + sizeof(T), Name);
73 return new (Mem) T(Buffer, RequiresNullTerminator);
70 return new (Mem) T(Buffer);
7471 }
7572
7673 namespace {
7774 /// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
7875 class MemoryBufferMem : public MemoryBuffer {
7976 public:
80 MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
81 init(InputData.begin(), InputData.end(), RequiresNullTerminator);
77 MemoryBufferMem(StringRef InputData) {
78 init(InputData.begin(), InputData.end());
8279 }
8380
8481 virtual const char *getBufferIdentifier() const {
9289 /// that EndPtr[0] must be a null byte and be accessible!
9390 MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
9491 StringRef BufferName) {
95 return GetNamedBuffer(InputData, BufferName, true);
92 return GetNamedBuffer(InputData, BufferName);
9693 }
9794
9895 /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
129126 char *Buf = Mem + AlignedStringLen;
130127 Buf[Size] = 0; // Null terminate buffer.
131128
132 return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
129 return new (Mem) MemoryBufferMem(StringRef(Buf, Size));
133130 }
134131
135132 /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
174171 /// sys::Path::UnMapFilePages method.
175172 class MemoryBufferMMapFile : public MemoryBufferMem {
176173 public:
177 MemoryBufferMMapFile(StringRef Buffer, bool RequiresNullTerminator)
178 : MemoryBufferMem(Buffer, RequiresNullTerminator) { }
174 MemoryBufferMMapFile(StringRef Buffer)
175 : MemoryBufferMem(Buffer) { }
179176
180177 ~MemoryBufferMMapFile() {
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);
178 sys::Path::UnMapFilePages(getBufferStart(), getBufferSize());
190179 }
191180 };
192181 }
215204 return ret;
216205 }
217206
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
246207 error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
247208 OwningPtr &result,
248 size_t FileSize, size_t MapSize,
249 off_t Offset,
250 bool RequiresNullTerminator) {
251 static int PageSize = sys::Process::GetPageSize();
252
209 int64_t FileSize) {
253210 // If we don't know the file size, use fstat to find out. fstat on an open
254211 // file descriptor is cheaper than stat on a random path.
255 if (FileSize == size_t(-1)) {
212 if (FileSize == -1) {
256213 struct stat FileInfo;
257214 // TODO: This should use fstat64 when available.
258215 if (fstat(FD, &FileInfo) == -1) {
261218 FileSize = FileInfo.st_size;
262219 }
263220
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)) {
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)) {
277231 result.reset(GetNamedBuffer(
278 StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator));
232 StringRef(Pages, FileSize), Filename));
279233 return success;
280234 }
281235 }
282236
283 MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
237 MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename);
284238 if (!Buf) {
285239 // Failed to create a buffer. The only way it can fail is if
286240 // new(std::nothrow) returns 0.
290244 OwningPtr SB(Buf);
291245 char *BufPtr = const_cast(SB->getBufferStart());
292246
293 size_t BytesLeft = MapSize;
294 if (lseek(FD, Offset, SEEK_SET) == -1)
295 return error_code(errno, posix_category());
296
247 size_t BytesLeft = FileSize;
297248 while (BytesLeft) {
298249 ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
299250 if (NumRead == -1) {
868868 return false;
869869 }
870870
871 const char *Path::MapInFilePages(int FD, size_t FileSize, off_t Offset) {
871 const char *Path::MapInFilePages(int FD, uint64_t FileSize) {
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, Offset);
876 void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, 0);
877877 if (BasePtr == MAP_FAILED)
878878 return 0;
879879 return (const char*)BasePtr;
880880 }
881881
882 void Path::UnMapFilePages(const char *BasePtr, size_t FileSize) {
882 void Path::UnMapFilePages(const char *BasePtr, uint64_t FileSize) {
883883 ::munmap((void*)BasePtr, FileSize);
884884 }
885885