| Index: third_party/tcmalloc/chromium/src/windows/port.cc
|
| diff --git a/third_party/tcmalloc/chromium/src/windows/port.cc b/third_party/tcmalloc/chromium/src/windows/port.cc
|
| index e68de163d3ef91229ed305af8148d394710223d4..0205912bd6761a2f09a50c8fba0a762adb06d3ad 100644
|
| --- a/third_party/tcmalloc/chromium/src/windows/port.cc
|
| +++ b/third_party/tcmalloc/chromium/src/windows/port.cc
|
| @@ -61,7 +61,7 @@ int getpagesize() {
|
| return pagesize;
|
| }
|
|
|
| -extern "C" PERFTOOLS_DLL_DECL void* __sbrk(ptrdiff_t increment) {
|
| +extern "C" PERFTOOLS_DLL_DECL void* __sbrk(std::ptrdiff_t increment) {
|
| LOG(FATAL, "Windows doesn't implement sbrk!\n");
|
| return NULL;
|
| }
|
| @@ -154,7 +154,8 @@ static void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv) {
|
| extern "C" {
|
| // This tells the linker to run these functions.
|
| #pragma data_seg(push, old_seg)
|
| -#pragma data_seg(".CRT$XLB")
|
| + // Use CRT$XLY instead of CRT$XLB to ensure we're called LATER in sequence.
|
| +#pragma data_seg(".CRT$XLY")
|
| void (NTAPI *p_thread_callback_tcmalloc)(
|
| HINSTANCE h, DWORD dwReason, PVOID pv) = on_tls_callback;
|
| #pragma data_seg(".CRT$XTU")
|
| @@ -227,35 +228,102 @@ extern void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
|
| if (alignment < pagesize) alignment = pagesize;
|
| size = ((size + alignment - 1) / alignment) * alignment;
|
|
|
| - // Safest is to make actual_size same as input-size.
|
| + // Report the total number of bytes the OS actually delivered. This might be
|
| + // greater than |size| because of alignment concerns. The full size is
|
| + // necessary so that adjacent spans can be coalesced.
|
| + // TODO(antonm): proper processing of alignments
|
| + // in actual_size and decommitting.
|
| if (actual_size) {
|
| *actual_size = size;
|
| }
|
|
|
| - // Ask for extra memory if alignment > pagesize
|
| - size_t extra = 0;
|
| - if (alignment > pagesize) {
|
| - extra = alignment - pagesize;
|
| - }
|
| + // We currently do not support alignments larger than the pagesize or
|
| + // alignments that are not multiples of the pagesize after being floored.
|
| + // If this ability is needed it can be done by the caller (assuming it knows
|
| + // the page size).
|
| + assert(alignment <= pagesize);
|
|
|
| - void* result = VirtualAlloc(0, size + extra,
|
| + void* result = VirtualAlloc(0, size,
|
| MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
|
| if (result == NULL)
|
| return NULL;
|
|
|
| - // Adjust the return memory so it is aligned
|
| - uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
|
| - size_t adjust = 0;
|
| - if ((ptr & (alignment - 1)) != 0) {
|
| - adjust = alignment - (ptr & (alignment - 1));
|
| + // If the result is not aligned memory fragmentation will result which can
|
| + // lead to pathological memory use.
|
| + assert((reinterpret_cast<uintptr_t>(result) & (alignment - 1)) == 0);
|
| +
|
| + return result;
|
| +}
|
| +
|
| +size_t TCMalloc_SystemAddGuard(void* start, size_t size) {
|
| + static size_t pagesize = 0;
|
| + if (pagesize == 0) {
|
| + SYSTEM_INFO system_info;
|
| + GetSystemInfo(&system_info);
|
| + pagesize = system_info.dwPageSize;
|
| + }
|
| +
|
| + // We know that TCMalloc_SystemAlloc will give us a correct page alignment
|
| + // regardless, so we can just assert to detect erroneous callers.
|
| + assert(reinterpret_cast<size_t>(start) % pagesize == 0);
|
| +
|
| + // Add a guard page to catch metadata corruption. We're using the
|
| + // PAGE_GUARD flag rather than NO_ACCESS because we want the unique
|
| + // exception in crash reports.
|
| + DWORD permissions = 0;
|
| + if (size > pagesize &&
|
| + VirtualProtect(start, pagesize, PAGE_READONLY | PAGE_GUARD,
|
| + &permissions)) {
|
| + return pagesize;
|
| }
|
|
|
| - ptr += adjust;
|
| - return reinterpret_cast<void*>(ptr);
|
| + return 0;
|
| }
|
|
|
| void TCMalloc_SystemRelease(void* start, size_t length) {
|
| - // TODO(csilvers): should I be calling VirtualFree here?
|
| + if (VirtualFree(start, length, MEM_DECOMMIT))
|
| + return;
|
| +
|
| + // The decommit may fail if the memory region consists of allocations
|
| + // from more than one call to VirtualAlloc. In this case, fall back to
|
| + // using VirtualQuery to retrieve the allocation boundaries and decommit
|
| + // them each individually.
|
| +
|
| + char* ptr = static_cast<char*>(start);
|
| + char* end = ptr + length;
|
| + MEMORY_BASIC_INFORMATION info;
|
| + while (ptr < end) {
|
| + size_t resultSize = VirtualQuery(ptr, &info, sizeof(info));
|
| + assert(resultSize == sizeof(info));
|
| + size_t decommitSize = std::min<size_t>(info.RegionSize, end - ptr);
|
| + BOOL success = VirtualFree(ptr, decommitSize, MEM_DECOMMIT);
|
| + assert(success == TRUE);
|
| + ptr += decommitSize;
|
| + }
|
| +}
|
| +
|
| +void TCMalloc_SystemCommit(void* start, size_t length) {
|
| + if (VirtualAlloc(start, length, MEM_COMMIT, PAGE_READWRITE) == start)
|
| + return;
|
| +
|
| + // The commit may fail if the memory region consists of allocations
|
| + // from more than one call to VirtualAlloc. In this case, fall back to
|
| + // using VirtualQuery to retrieve the allocation boundaries and commit them
|
| + // each individually.
|
| +
|
| + char* ptr = static_cast<char*>(start);
|
| + char* end = ptr + length;
|
| + MEMORY_BASIC_INFORMATION info;
|
| + while (ptr < end) {
|
| + size_t resultSize = VirtualQuery(ptr, &info, sizeof(info));
|
| + assert(resultSize == sizeof(info));
|
| +
|
| + size_t commitSize = std::min<size_t>(info.RegionSize, end - ptr);
|
| + void* newAddress = VirtualAlloc(ptr, commitSize, MEM_COMMIT,
|
| + PAGE_READWRITE);
|
| + assert(newAddress == ptr);
|
| + ptr += commitSize;
|
| + }
|
| }
|
|
|
| bool RegisterSystemAllocator(SysAllocator *allocator, int priority) {
|
|
|