15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/allocator/allocator_shim.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <config.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/allocator/allocator_extension_thunks.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/profiler/alternate_timer.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sysinfo.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// This shim make it possible to use different allocators via an environment 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// variable set before running the program. This may reduce the 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// amount of inlining that we get with malloc/free/etc. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(mbelshe): Ensure that all calls to tcmalloc have the proper call depth 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from the "user code" so that debugging tools (HeapChecker) can work. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// new_mode behaves similarly to MSVC's _set_new_mode. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If flag is 0 (default), calls to malloc will behave normally. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If flag is 1, calls to malloc will behave like calls to new, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and the std_new_handler will be invoked on failure. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Can be set by calling _set_new_mode(). 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int new_mode = 0; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef enum { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TCMALLOC, // TCMalloc is the default allocator. 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WINHEAP, // Windows Heap (standard Windows allocator). 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WINLFH, // Windows LFH Heap. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} Allocator; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the default allocator. This value can be changed at startup by 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// specifying environment variables shown below it. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See SetupSubprocessAllocator() to specify a default secondary (subprocess) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocator. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jar): Switch to using TCMALLOC for the renderer as well. 37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(SYZYASAN) 38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// SyzyASan requires the use of "WINHEAP". 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static Allocator allocator = WINHEAP; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Allocator allocator = TCMALLOC; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The names of the environment variables that can optionally control the 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// selection of the allocator. The primary may be used to control overall 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocator selection, and the secondary can be used to specify an allocator 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to use in sub-processes. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char primary_name[] = "CHROME_ALLOCATOR"; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char secondary_name[] = "CHROME_ALLOCATOR_2"; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We include tcmalloc and the win_allocator to get as much inlining as 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// possible. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "debugallocation_shim.cc" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "win_allocator.cc" 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Call the new handler, if one has been set. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true on successfully calling the handler, false otherwise. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool call_new_handler(bool nothrow) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the current new handler. NB: this function is not 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread-safe. We make a feeble stab at making it so here, but 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this lock only protects against tcmalloc interfering with 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // itself, not with other libraries calling set_new_handler. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::new_handler nh; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder h(&set_new_handler_lock); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nh = std::set_new_handler(0); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) std::set_new_handler(nh); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!nh) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since exceptions are disabled, we don't really know if new_handler 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // failed. Assume it will abort if it fails. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*nh)(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // break out of the retry loop. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If no new_handler is established, the allocation failed. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!nh) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nothrow) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw std::bad_alloc(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise, try the new_handler. If it returns, retry the 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allocation. If it throws std::bad_alloc, fail the allocation. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if it throws something else, don't interfere. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*nh)(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (const std::bad_alloc&) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!nothrow) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" { 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void* malloc(size_t size) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* ptr; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (allocator) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINHEAP: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINLFH: 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = win_heap_malloc(size); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TCMALLOC: 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = do_malloc(size); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ptr) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ptr; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_mode || !call_new_handler(true)) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ptr; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void free(void* p) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (allocator) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINHEAP: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINLFH: 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win_heap_free(p); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case TCMALLOC: 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) do_free(p); 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void* realloc(void* ptr, size_t size) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Webkit is brittle for allocators that return NULL for malloc(0). The 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // realloc(0, 0) code path does not guarantee a non-NULL return, so be sure 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to call malloc for this case. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ptr) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return malloc(size); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* new_ptr; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (allocator) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINHEAP: 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINLFH: 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_ptr = win_heap_realloc(ptr, size); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TCMALLOC: 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_ptr = do_realloc(ptr, size); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Subtle warning: NULL return does not alwas indicate out-of-memory. If 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the requested new size is zero, realloc should free the ptr and return 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NULL. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_ptr || !size) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new_ptr; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_mode || !call_new_handler(true)) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new_ptr; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(mbelshe): Implement this for other allocators. 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void malloc_stats(void) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (allocator) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINHEAP: 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINLFH: 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No stats. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case TCMALLOC: 171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) tc_malloc_stats(); 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" size_t _msize(void* p) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (allocator) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINHEAP: 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINLFH: 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return win_heap_msize(p); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // TCMALLOC 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocExtension::instance()->GetAllocatedSize(p); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is included to resolve references from libcmt. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" intptr_t _get_heap_handle() { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool get_allocator_waste_size_thunk(size_t* size) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (allocator) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINHEAP: 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINLFH: 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(alexeif): Implement for allocators other than tcmalloc. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t heap_size, allocated_bytes, unmapped_bytes; 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MallocExtension* ext = MallocExtension::instance(); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ext->GetNumericProperty("generic.heap_size", &heap_size) && 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ext->GetNumericProperty("generic.current_allocated_bytes", 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &allocated_bytes) && 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ext->GetNumericProperty("tcmalloc.pageheap_unmapped_bytes", 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &unmapped_bytes)) { 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *size = heap_size - allocated_bytes - unmapped_bytes; 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void get_stats_thunk(char* buffer, int buffer_length) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MallocExtension::instance()->GetStats(buffer, buffer_length); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void release_free_memory_thunk() { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MallocExtension::instance()->ReleaseFreeMemory(); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The CRT heap initialization stub. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" int _heap_init() { 224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Don't use the environment variable if SYZYASAN is defined, as the 225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// implementation requires Winheap to be the allocator. 226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if !defined(SYZYASAN) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* environment_value = GetenvBeforeMain(primary_name); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (environment_value) { 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!stricmp(environment_value, "winheap")) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allocator = WINHEAP; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (!stricmp(environment_value, "winlfh")) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allocator = WINLFH; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (!stricmp(environment_value, "tcmalloc")) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allocator = TCMALLOC; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (allocator) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINHEAP: 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return win_heap_init(false) ? 1 : 0; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINLFH: 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return win_heap_init(true) ? 1 : 0; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TCMALLOC: 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fall through 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initializing tcmalloc. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We intentionally leak this object. It lasts for the process 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lifetime. Trying to teardown at _heap_term() is so late that 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // you can't do anything useful anyway. 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new TCMallocGuard(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Provide optional hook for monitoring allocation quantities on a per-thread 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // basis. Only set the hook if the environment indicates this needs to be 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // enabled. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* profiling = 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetenvBeforeMain(tracked_objects::kAlternateProfilerTime); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profiling && *profiling == '1') { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracked_objects::SetAlternateTimeSource( 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tcmalloc::ThreadCache::GetBytesAllocatedOnCurrentThread, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracked_objects::TIME_SOURCE_TYPE_TCMALLOC); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::allocator::thunks::SetGetAllocatorWasteSizeFunction( 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) get_allocator_waste_size_thunk); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::allocator::thunks::SetGetStatsFunction(get_stats_thunk); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::allocator::thunks::SetReleaseFreeMemoryFunction( 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) release_free_memory_thunk); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The CRT heap cleanup stub. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void _heap_term() {} 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We set this to 1 because part of the CRT uses a check of _crtheap != 0 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test whether the CRT has been initialized. Once we've ripped out 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the allocators from libcmt, we need to provide this definition so that 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the rest of the CRT is still usable. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void* _crtheap = reinterpret_cast<void*>(1); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Provide support for aligned memory through Windows only _aligned_malloc(). 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* _aligned_malloc(size_t size, size_t alignment) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // _aligned_malloc guarantees parameter validation, so do so here. These 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // checks are somewhat stricter than _aligned_malloc() since we're effectively 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // using memalign() under the hood. 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(size, 0U); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(alignment & (alignment - 1), 0U); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(alignment % sizeof(void*), 0U); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* ptr; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (allocator) { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINHEAP: 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINLFH: 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = win_heap_memalign(alignment, size); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TCMALLOC: 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = tc_memalign(alignment, size); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ptr) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sanity check alignment. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(reinterpret_cast<uintptr_t>(ptr) & (alignment - 1), 0U); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ptr; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_mode || !call_new_handler(true)) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ptr; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void _aligned_free(void* p) { 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TCMalloc returns pointers from memalign() that are safe to use with free(). 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Pointers allocated with win_heap_memalign() MUST be freed via 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // win_heap_memalign_free() since the aligned pointer is not the real one. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (allocator) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINHEAP: 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINLFH: 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win_heap_memalign_free(p); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case TCMALLOC: 328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) do_free(p); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // WIN32 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "generic_allocators.cc" 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // extern C 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace allocator { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetupSubprocessAllocator() { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t primary_length = 0; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getenv_s(&primary_length, NULL, 0, primary_name); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t secondary_length = 0; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[20]; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getenv_s(&secondary_length, buffer, sizeof(buffer), secondary_name); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(sizeof(buffer), secondary_length); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[sizeof(buffer) - 1] = '\0'; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (secondary_length || !primary_length) { 352effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Don't use the environment variable if SYZYASAN is defined, as the 353effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// implementation require Winheap to be the allocator. 354effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if !defined(SYZYASAN) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* secondary_value = secondary_length ? buffer : "TCMALLOC"; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force renderer (or other subprocesses) to use secondary_value. 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* secondary_value = "WINHEAP"; 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret_val = _putenv_s(primary_name, secondary_value); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0, ret_val); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* TCMallocDoMallocForTest(size_t size) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return do_malloc(size); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCMallocDoFreeForTest(void* ptr) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do_free(ptr); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ExcludeSpaceForMarkForTest(size_t size) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ExcludeSpaceForMark(size); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace allocator. 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base. 379