diff --git a/compiler-rt/lib/profile/InstrProfilingFile.c b/compiler-rt/lib/profile/InstrProfilingFile.c --- a/compiler-rt/lib/profile/InstrProfilingFile.c +++ b/compiler-rt/lib/profile/InstrProfilingFile.c @@ -490,6 +490,8 @@ * __llvm_profile_get_size_for_buffer(). */ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); + const uint64_t *CountersBegin = __llvm_profile_begin_counters(); + const uint64_t *CountersEnd = __llvm_profile_end_counters(); uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd); const uint64_t CountersOffset = sizeof(__llvm_profile_header) + (DataSize * sizeof(__llvm_profile_data)); @@ -542,8 +544,11 @@ } /* Update the profile fields based on the current mapping. */ - __llvm_profile_counter_bias = (intptr_t)Profile - - (uintptr_t)__llvm_profile_begin_counters() + CountersOffset; + __llvm_profile_counter_bias = + (intptr_t)Profile - (uintptr_t)CountersBegin + CountersOffset; + + /* Return the memory allocated for counters to OS. */ + lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd); } static void initializeProfileForContinuousMode(void) { diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c b/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c --- a/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c @@ -192,9 +192,11 @@ lprofWrite("LLVM Profile: {{{dumpfile:%s:%s}}}\n", ProfileSinkName, VmoName); /* Update the profile fields based on the current mapping. */ - __llvm_profile_counter_bias = (intptr_t)Mapping - - (uintptr_t)__llvm_profile_begin_counters() + - CountersOffset; + __llvm_profile_counter_bias = + (intptr_t)Mapping - (uintptr_t)CountersBegin + CountersOffset; + + /* Return the memory allocated for counters to OS. */ + lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd); } #endif diff --git a/compiler-rt/lib/profile/InstrProfilingUtil.h b/compiler-rt/lib/profile/InstrProfilingUtil.h --- a/compiler-rt/lib/profile/InstrProfilingUtil.h +++ b/compiler-rt/lib/profile/InstrProfilingUtil.h @@ -9,6 +9,7 @@ #ifndef PROFILE_INSTRPROFILINGUTIL_H #define PROFILE_INSTRPROFILINGUTIL_H +#include #include #include @@ -73,4 +74,14 @@ /* Restore previously suspended SIGKILL. */ void lprofRestoreSigKill(); +inline size_t lprofRoundUpTo(size_t x, size_t boundary) { + return (x + boundary - 1) & ~(boundary - 1); +} + +inline size_t lprofRoundDownTo(size_t x, size_t boundary) { + return x & ~(boundary - 1); +} + +int lprofReleaseMemoryPagesToOS(uintptr_t Begin, uintptr_t End); + #endif /* PROFILE_INSTRPROFILINGUTIL_H */ diff --git a/compiler-rt/lib/profile/InstrProfilingUtil.c b/compiler-rt/lib/profile/InstrProfilingUtil.c --- a/compiler-rt/lib/profile/InstrProfilingUtil.c +++ b/compiler-rt/lib/profile/InstrProfilingUtil.c @@ -12,12 +12,13 @@ #include #include "WindowsMMap.h" #else +#include +#include #include +#include #include #include #include -#include -#include #endif #ifdef COMPILER_RT_HAS_UNAME @@ -32,6 +33,10 @@ #include #endif +#if defined(__Fuchsia__) +#include +#endif + #include "InstrProfiling.h" #include "InstrProfilingUtil.h" @@ -330,3 +335,21 @@ prctl(PR_SET_PDEATHSIG, SIGKILL); #endif } + +COMPILER_RT_VISIBILITY int lprofReleaseMemoryPagesToOS(uintptr_t Begin, + uintptr_t End) { + size_t PageSize = getpagesize(); + uintptr_t BeginAligned = lprofRoundUpTo((uintptr_t)Begin, PageSize); + uintptr_t EndAligned = lprofRoundDownTo((uintptr_t)End, PageSize); + if (BeginAligned < EndAligned) { +#if defined(__Fuchsia__) + return _zx_vmar_op_range(_zx_vmar_root_self(), ZX_VMAR_OP_DECOMMIT, + (zx_vaddr_t)BeginAligned, + EndAligned - BeginAligned, NULL, 0); +#else + return madvise((void *)BeginAligned, EndAligned - BeginAligned, + MADV_DONTNEED); +#endif + } + return 0; +} diff --git a/compiler-rt/lib/profile/WindowsMMap.h b/compiler-rt/lib/profile/WindowsMMap.h --- a/compiler-rt/lib/profile/WindowsMMap.h +++ b/compiler-rt/lib/profile/WindowsMMap.h @@ -36,6 +36,14 @@ #define MS_INVALIDATE 0x0002 /* invalidate all cached data */ #define MS_SYNC 0x0010 /* msync synchronously */ +/* + * madvise() flags + */ + +#define MADV_NORMAL 0 /* no special treatment */ +#define MADV_WILLNEED 3 /* expect access in the near future */ +#define MADV_DONTNEED 4 /* do not expect access in the near future */ + /* * flock() operations */ @@ -59,6 +67,8 @@ int msync(void *addr, size_t length, int flags); +int madvise(void *addr, size_t length, int advice); + int flock(int fd, int operation); #endif /* _WIN32 */ diff --git a/compiler-rt/lib/profile/WindowsMMap.c b/compiler-rt/lib/profile/WindowsMMap.c --- a/compiler-rt/lib/profile/WindowsMMap.c +++ b/compiler-rt/lib/profile/WindowsMMap.c @@ -112,6 +112,18 @@ return 0; } +COMPILER_RT_VISIBILITY +int madvise(void *addr, size_t length, int advice) +{ + if (advice != MADV_DONTNEED) + return -1; /* Not supported. */ + + if (!VirtualUnlock(addr, length)) + return -1; + + return 0; +} + COMPILER_RT_VISIBILITY int lock(HANDLE handle, DWORD lockType, BOOL blocking) { DWORD flags = lockType;