Chromium Code Reviews| Index: base/allocator/allocator_shim.cc |
| diff --git a/base/allocator/allocator_shim.cc b/base/allocator/allocator_shim.cc |
| index 961cda4c5c482fdbe1aadce18eefb6edf4c62797..378f8ed714d32c57fbcfec12ab41013ed9299d48 100644 |
| --- a/base/allocator/allocator_shim.cc |
| +++ b/base/allocator/allocator_shim.cc |
| @@ -2,19 +2,14 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -#include "base/allocator/allocator_shim.h" |
| +#include <new.h> |
| -#include <config.h> |
| #include "base/allocator/allocator_extension_thunks.h" |
| #include "base/profiler/alternate_timer.h" |
| #include "base/sysinfo.h" |
| -// This shim make it possible to use different allocators via an environment |
| -// variable set before running the program. This may reduce the |
| -// amount of inlining that we get with malloc/free/etc. |
| - |
| -// TODO(mbelshe): Ensure that all calls to tcmalloc have the proper call depth |
| -// from the "user code" so that debugging tools (HeapChecker) can work. |
| +// This shim make it possible to perform additional checks on allocations |
| +// before passing them to the Heap functions. |
| // new_mode behaves similarly to MSVC's _set_new_mode. |
| // If flag is 0 (default), calls to malloc will behave normally. |
| @@ -23,56 +18,21 @@ |
| // Can be set by calling _set_new_mode(). |
| static int new_mode = 0; |
|
cpu_(ooo_6.6-7.5)
2015/01/07 17:28:42
I don't see anybody setting new_mode
Will Harris
2015/01/07 17:32:47
new_mode global is removed from libcmt in prep_lib
|
| -typedef enum { |
| - TCMALLOC, // TCMalloc is the default allocator. |
| - WINHEAP, // Windows Heap (standard Windows allocator). |
| - WINLFH, // Windows LFH Heap. |
| -} Allocator; |
| - |
| -// This is the default allocator. This value can be changed at startup by |
| -// specifying environment variables shown below it. |
| -// See SetupSubprocessAllocator() to specify a default secondary (subprocess) |
| -// allocator. |
| -// TODO(jar): Switch to using TCMALLOC for the renderer as well. |
| -#if defined(SYZYASAN) |
| -// SyzyASan requires the use of "WINHEAP". |
| -static Allocator allocator = WINHEAP; |
| -#else |
| -static Allocator allocator = TCMALLOC; |
| -#endif |
| -// The names of the environment variables that can optionally control the |
| -// selection of the allocator. The primary may be used to control overall |
| -// allocator selection, and the secondary can be used to specify an allocator |
| -// to use in sub-processes. |
| -static const char primary_name[] = "CHROME_ALLOCATOR"; |
| -static const char secondary_name[] = "CHROME_ALLOCATOR_2"; |
| - |
| -// We include tcmalloc and the win_allocator to get as much inlining as |
| -// possible. |
| -#include "debugallocation_shim.cc" |
| +// We include the win_allocator to get as much inlining as possible. |
| #include "win_allocator.cc" |
| // Call the new handler, if one has been set. |
| // Returns true on successfully calling the handler, false otherwise. |
| -inline bool call_new_handler(bool nothrow) { |
| - // Get the current new handler. NB: this function is not |
| - // thread-safe. We make a feeble stab at making it so here, but |
| - // this lock only protects against tcmalloc interfering with |
| - // itself, not with other libraries calling set_new_handler. |
| - std::new_handler nh; |
| - { |
| - SpinLockHolder h(&set_new_handler_lock); |
| - nh = std::set_new_handler(0); |
| - (void) std::set_new_handler(nh); |
| - } |
| +inline bool call_new_handler(bool nothrow, size_t size) { |
| + // Get the current new handler. |
| + _PNH nh = _query_new_handler(); |
| #if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ |
| (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) |
| if (!nh) |
| return false; |
| // Since exceptions are disabled, we don't really know if new_handler |
| // failed. Assume it will abort if it fails. |
| - (*nh)(); |
| - return false; // break out of the retry loop. |
| + return nh(size); |
| #else |
| // If no new_handler is established, the allocation failed. |
| if (!nh) { |
| @@ -84,7 +44,7 @@ inline bool call_new_handler(bool nothrow) { |
| // allocation. If it throws std::bad_alloc, fail the allocation. |
| // if it throws something else, don't interfere. |
| try { |
| - (*nh)(); |
| + return nh(size); |
| } catch (const std::bad_alloc&) { |
| if (!nothrow) |
| throw; |
| @@ -98,35 +58,19 @@ extern "C" { |
| void* malloc(size_t size) { |
| void* ptr; |
| for (;;) { |
| - switch (allocator) { |
| - case WINHEAP: |
| - case WINLFH: |
| - ptr = win_heap_malloc(size); |
| - break; |
| - case TCMALLOC: |
| - default: |
| - ptr = do_malloc(size); |
| - break; |
| - } |
| + ptr = win_heap_malloc(size); |
| if (ptr) |
| return ptr; |
| - if (!new_mode || !call_new_handler(true)) |
| + if (!new_mode || !call_new_handler(true, size)) |
| break; |
| } |
| return ptr; |
| } |
| void free(void* p) { |
| - switch (allocator) { |
| - case WINHEAP: |
| - case WINLFH: |
| - win_heap_free(p); |
| - return; |
| - case TCMALLOC: |
| - do_free(p); |
| - return; |
| - } |
| + win_heap_free(p); |
| + return; |
| } |
| void* realloc(void* ptr, size_t size) { |
| @@ -138,23 +82,14 @@ void* realloc(void* ptr, size_t size) { |
| void* new_ptr; |
| for (;;) { |
| - switch (allocator) { |
| - case WINHEAP: |
| - case WINLFH: |
| - new_ptr = win_heap_realloc(ptr, size); |
| - break; |
| - case TCMALLOC: |
| - default: |
| - new_ptr = do_realloc(ptr, size); |
| - break; |
| - } |
| + new_ptr = win_heap_realloc(ptr, size); |
| // Subtle warning: NULL return does not alwas indicate out-of-memory. If |
| // the requested new size is zero, realloc should free the ptr and return |
| // NULL. |
| if (new_ptr || !size) |
| return new_ptr; |
| - if (!new_mode || !call_new_handler(true)) |
| + if (!new_mode || !call_new_handler(true, size)) |
| break; |
| } |
| return new_ptr; |
| @@ -162,28 +97,14 @@ void* realloc(void* ptr, size_t size) { |
| // TODO(mbelshe): Implement this for other allocators. |
| void malloc_stats(void) { |
| - switch (allocator) { |
| - case WINHEAP: |
| - case WINLFH: |
| - // No stats. |
| - return; |
| - case TCMALLOC: |
| - tc_malloc_stats(); |
| - return; |
| - } |
| + // No stats. |
| + return; |
| } |
| #ifdef WIN32 |
| extern "C" size_t _msize(void* p) { |
| - switch (allocator) { |
| - case WINHEAP: |
| - case WINLFH: |
| - return win_heap_msize(p); |
| - } |
| - |
| - // TCMALLOC |
| - return MallocExtension::instance()->GetAllocatedSize(p); |
| + return win_heap_msize(p); |
| } |
| // This is included to resolve references from libcmt. |
| @@ -192,84 +113,13 @@ extern "C" intptr_t _get_heap_handle() { |
| } |
| static bool get_allocator_waste_size_thunk(size_t* size) { |
| - switch (allocator) { |
| - case WINHEAP: |
| - case WINLFH: |
| - // TODO(alexeif): Implement for allocators other than tcmalloc. |
| - return false; |
| - } |
| - size_t heap_size, allocated_bytes, unmapped_bytes; |
| - MallocExtension* ext = MallocExtension::instance(); |
| - if (ext->GetNumericProperty("generic.heap_size", &heap_size) && |
| - ext->GetNumericProperty("generic.current_allocated_bytes", |
| - &allocated_bytes) && |
| - ext->GetNumericProperty("tcmalloc.pageheap_unmapped_bytes", |
| - &unmapped_bytes)) { |
| - *size = heap_size - allocated_bytes - unmapped_bytes; |
| - return true; |
| - } |
| + // TODO(alexeif): Implement for allocators other than tcmalloc. |
| return false; |
| } |
| -static void get_stats_thunk(char* buffer, int buffer_length) { |
| - MallocExtension::instance()->GetStats(buffer, buffer_length); |
| -} |
| - |
| -static void release_free_memory_thunk() { |
| - MallocExtension::instance()->ReleaseFreeMemory(); |
| -} |
| - |
| // The CRT heap initialization stub. |
| extern "C" int _heap_init() { |
| -// Don't use the environment variable if SYZYASAN is defined, as the |
| -// implementation requires Winheap to be the allocator. |
| -#if !defined(SYZYASAN) |
| - const char* environment_value = GetenvBeforeMain(primary_name); |
| - if (environment_value) { |
| - if (!stricmp(environment_value, "winheap")) |
| - allocator = WINHEAP; |
| - else if (!stricmp(environment_value, "winlfh")) |
| - allocator = WINLFH; |
| - else if (!stricmp(environment_value, "tcmalloc")) |
| - allocator = TCMALLOC; |
| - } |
| -#endif |
| - |
| - switch (allocator) { |
| - case WINHEAP: |
| - return win_heap_init(false) ? 1 : 0; |
| - case WINLFH: |
| - return win_heap_init(true) ? 1 : 0; |
| - case TCMALLOC: |
| - default: |
| - // fall through |
| - break; |
| - } |
| - |
| - // Initializing tcmalloc. |
| - // We intentionally leak this object. It lasts for the process |
| - // lifetime. Trying to teardown at _heap_term() is so late that |
| - // you can't do anything useful anyway. |
| - new TCMallocGuard(); |
| - |
| - // Provide optional hook for monitoring allocation quantities on a per-thread |
| - // basis. Only set the hook if the environment indicates this needs to be |
| - // enabled. |
| - const char* profiling = |
| - GetenvBeforeMain(tracked_objects::kAlternateProfilerTime); |
| - if (profiling && *profiling == '1') { |
| - tracked_objects::SetAlternateTimeSource( |
| - tcmalloc::ThreadCache::GetBytesAllocatedOnCurrentThread, |
| - tracked_objects::TIME_SOURCE_TYPE_TCMALLOC); |
| - } |
| - |
| - base::allocator::thunks::SetGetAllocatorWasteSizeFunction( |
| - get_allocator_waste_size_thunk); |
| - base::allocator::thunks::SetGetStatsFunction(get_stats_thunk); |
| - base::allocator::thunks::SetReleaseFreeMemoryFunction( |
| - release_free_memory_thunk); |
| - |
| - return 1; |
| + return win_heap_init() ? 1 : 0; |
| } |
| // The CRT heap cleanup stub. |
| @@ -292,16 +142,7 @@ void* _aligned_malloc(size_t size, size_t alignment) { |
| void* ptr; |
| for (;;) { |
| - switch (allocator) { |
| - case WINHEAP: |
| - case WINLFH: |
| - ptr = win_heap_memalign(alignment, size); |
| - break; |
| - case TCMALLOC: |
| - default: |
| - ptr = tc_memalign(alignment, size); |
| - break; |
| - } |
| + ptr = win_heap_memalign(alignment, size); |
| if (ptr) { |
| // Sanity check alignment. |
| @@ -309,24 +150,16 @@ void* _aligned_malloc(size_t size, size_t alignment) { |
| return ptr; |
| } |
| - if (!new_mode || !call_new_handler(true)) |
| + if (!new_mode || !call_new_handler(true, size)) |
| break; |
| } |
| return ptr; |
| } |
| void _aligned_free(void* p) { |
| - // TCMalloc returns pointers from memalign() that are safe to use with free(). |
| // Pointers allocated with win_heap_memalign() MUST be freed via |
| // win_heap_memalign_free() since the aligned pointer is not the real one. |
| - switch (allocator) { |
| - case WINHEAP: |
| - case WINLFH: |
| - win_heap_memalign_free(p); |
| - return; |
| - case TCMALLOC: |
| - do_free(p); |
| - } |
| + win_heap_memalign_free(p); |
| } |
| #endif // WIN32 |
| @@ -334,45 +167,3 @@ void _aligned_free(void* p) { |
| #include "generic_allocators.cc" |
| } // extern C |
| - |
| -namespace base { |
| -namespace allocator { |
| - |
| -void SetupSubprocessAllocator() { |
| - size_t primary_length = 0; |
| - getenv_s(&primary_length, NULL, 0, primary_name); |
| - |
| - size_t secondary_length = 0; |
| - char buffer[20]; |
| - getenv_s(&secondary_length, buffer, sizeof(buffer), secondary_name); |
| - DCHECK_GT(sizeof(buffer), secondary_length); |
| - buffer[sizeof(buffer) - 1] = '\0'; |
| - |
| - if (secondary_length || !primary_length) { |
| -// Don't use the environment variable if SYZYASAN is defined, as the |
| -// implementation require Winheap to be the allocator. |
| -#if !defined(SYZYASAN) |
| - const char* secondary_value = secondary_length ? buffer : "TCMALLOC"; |
| - // Force renderer (or other subprocesses) to use secondary_value. |
| -#else |
| - const char* secondary_value = "WINHEAP"; |
| -#endif |
| - int ret_val = _putenv_s(primary_name, secondary_value); |
| - DCHECK_EQ(0, ret_val); |
| - } |
| -} |
| - |
| -void* TCMallocDoMallocForTest(size_t size) { |
| - return do_malloc(size); |
| -} |
| - |
| -void TCMallocDoFreeForTest(void* ptr) { |
| - do_free(ptr); |
| -} |
| - |
| -size_t ExcludeSpaceForMarkForTest(size_t size) { |
| - return ExcludeSpaceForMark(size); |
| -} |
| - |
| -} // namespace allocator. |
| -} // namespace base. |