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,18 @@ } /* 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. */ + size_t PageSize = lprofGetPageSize(); + uintptr_t CountersBeginAligned = + lprofRoundUpTo((uintptr_t)CountersBegin, PageSize); + uintptr_t CountersEndAligned = + lprofRoundDownTo((uintptr_t)CountersEnd, PageSize); + if (CountersBeginAligned < CountersEndAligned) + madvise((void *)CountersBeginAligned, + CountersEndAligned - CountersBeginAligned, MADV_DONTNEED); } 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,25 @@ 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. */ + size_t PageSize = lprofGetPageSize(); + zx_vaddr_t CountersBeginAligned = + lprofRoundUpTo((uintptr_t)CountersBegin, PageSize); + zx_vaddr_t CountersEndAligned = + lprofRoundDownTo((uintptr_t)CountersEnd, PageSize); + if (CountersBeginAligned < CountersEndAligned) { + Status = _zx_vmar_op_range( + _zx_vmar_root_self(), ZX_VMAR_OP_DECOMMIT, CountersBeginAligned, + CountersEndAligned - CountersBeginAligned, NULL, 0); + if (Status != ZX_OK) { + lprofWrite("LLVM Profile: cannot decommit counters: %s\n", + _zx_status_get_string(Status)); + return; + } + } } #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(); +size_t lprofGetPageSize(); + +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); +} + #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 @@ -32,6 +32,10 @@ #include #endif +#if defined(__Fuchsia__) +#include +#endif + #include "InstrProfiling.h" #include "InstrProfilingUtil.h" @@ -330,3 +334,20 @@ prctl(PR_SET_PDEATHSIG, SIGKILL); #endif } + +COMPILER_RT_VISIBILITY size_t lprofGetPageSize() { +#if defined(__Fuchsia__) + return _zx_system_get_page_size(); +#elif defined(__APPLE__) || \ + defined(__linux__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) + return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy. +#elif defined(_WIN32) + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwPageSize; +#else + return 4096; +#endif +}