[Support] Add MemoryBuffer::dontNeedIfMmap

On *NIX systems, this API calls madvise(MADV_DONTNEED) on read-only file mappings.
It should not be used on a writable buffer.
The API is used to implement ld.lld LTO memory saving trick (D116367).

Note: on read-only file mappings, Linux's MADV_DONTNEED semantics match POSIX
POSIX_MADV_DONTNEED and BSD systems' MADV_DONTNEED.

On Windows, VirtualAllocEx MEM_COMMIT/MEM_RESET have similar semantics
but are unfortunately not drop-in replacements. dontNeedIfMmap is currently a no-op.

Reviewed By: aganea

Differential Revision: https://reviews.llvm.org/D116366
This commit is contained in:
Fangrui Song 2021-12-30 10:42:28 -08:00
parent 25ff448aac
commit 890e8c8f7e
5 changed files with 19 additions and 0 deletions

View File

@ -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;

View File

@ -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.
///

View File

@ -220,6 +220,8 @@ public:
MemoryBuffer::BufferKind getBufferKind() const override {
return MemoryBuffer::MemoryBuffer_MMap;
}
void dontNeedIfMmap() override { MFR.dontNeed(); }
};
} // namespace

View File

@ -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();
}

View File

@ -959,6 +959,8 @@ void mapped_file_region::unmapImpl() {
}
}
void mapped_file_region::dontNeedImpl() {}
int mapped_file_region::alignment() {
SYSTEM_INFO SysInfo;
::GetSystemInfo(&SysInfo);