diff --git a/llvm/include/llvm/Support/FileSystem.h b/llvm/include/llvm/Support/FileSystem.h index 1a049533b82b..dabd384b400b 100644 --- a/llvm/include/llvm/Support/FileSystem.h +++ b/llvm/include/llvm/Support/FileSystem.h @@ -1279,6 +1279,7 @@ private: } void unmapImpl(); + void dontNeedImpl(); std::error_code init(sys::fs::file_t FD, uint64_t Offset, mapmode Mode); @@ -1308,6 +1309,7 @@ public: unmapImpl(); copyFrom(mapped_file_region()); } + void dontNeed() { dontNeedImpl(); } size_t size() const; char *data() const; diff --git a/llvm/include/llvm/Support/MemoryBuffer.h b/llvm/include/llvm/Support/MemoryBuffer.h index c9ceeedbf3dc..6385805eba1d 100644 --- a/llvm/include/llvm/Support/MemoryBuffer.h +++ b/llvm/include/llvm/Support/MemoryBuffer.h @@ -74,6 +74,13 @@ public: /// from. virtual StringRef getBufferIdentifier() const { return "Unknown buffer"; } + /// For read-only MemoryBuffer_MMap, mark the buffer as unused in the near + /// future and the kernel can free resources associated with it. Further + /// access is supported but may be expensive. This calls + /// madvise(MADV_DONTNEED) on read-only file mappings on *NIX systems. This + /// function should not be called on a writable buffer. + virtual void dontNeedIfMmap() {} + /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer /// if successful, otherwise returning null. /// diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp index d3fa3c6f065d..345b0d4aede5 100644 --- a/llvm/lib/Support/MemoryBuffer.cpp +++ b/llvm/lib/Support/MemoryBuffer.cpp @@ -220,6 +220,8 @@ public: MemoryBuffer::BufferKind getBufferKind() const override { return MemoryBuffer::MemoryBuffer_MMap; } + + void dontNeedIfMmap() override { MFR.dontNeed(); } }; } // namespace diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc index c0712e0a0681..a18650aadb6e 100644 --- a/llvm/lib/Support/Unix/Path.inc +++ b/llvm/lib/Support/Unix/Path.inc @@ -870,6 +870,12 @@ void mapped_file_region::unmapImpl() { ::munmap(Mapping, Size); } +void mapped_file_region::dontNeedImpl() { + assert(Mode == mapped_file_region::readonly); + if (Mapping) + ::madvise(Mapping, Size, MADV_DONTNEED); +} + int mapped_file_region::alignment() { return Process::getPageSizeEstimate(); } diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc index b15e71a9ce2a..175a96a8ba6c 100644 --- a/llvm/lib/Support/Windows/Path.inc +++ b/llvm/lib/Support/Windows/Path.inc @@ -959,6 +959,8 @@ void mapped_file_region::unmapImpl() { } } +void mapped_file_region::dontNeedImpl() {} + int mapped_file_region::alignment() { SYSTEM_INFO SysInfo; ::GetSystemInfo(&SysInfo);