| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/allocator/allocator_shim.h" | 5 #include "base/allocator/allocator_shim.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 | 52 |
| 53 class AllocatorShimTest : public testing::Test { | 53 class AllocatorShimTest : public testing::Test { |
| 54 public: | 54 public: |
| 55 static const size_t kMaxSizeTracked = 8192; | 55 static const size_t kMaxSizeTracked = 8192; |
| 56 AllocatorShimTest() : testing::Test() {} | 56 AllocatorShimTest() : testing::Test() {} |
| 57 | 57 |
| 58 static size_t Hash(const void* ptr) { | 58 static size_t Hash(const void* ptr) { |
| 59 return reinterpret_cast<uintptr_t>(ptr) % kMaxSizeTracked; | 59 return reinterpret_cast<uintptr_t>(ptr) % kMaxSizeTracked; |
| 60 } | 60 } |
| 61 | 61 |
| 62 static void* MockAlloc(const AllocatorDispatch* self, size_t size) { | 62 static void* MockAlloc(const AllocatorDispatch* self, |
| 63 size_t size, |
| 64 void* context) { |
| 63 if (instance_ && size < kMaxSizeTracked) | 65 if (instance_ && size < kMaxSizeTracked) |
| 64 ++(instance_->allocs_intercepted_by_size[size]); | 66 ++(instance_->allocs_intercepted_by_size[size]); |
| 65 return self->next->alloc_function(self->next, size); | 67 return self->next->alloc_function(self->next, size, context); |
| 66 } | 68 } |
| 67 | 69 |
| 68 static void* MockAllocZeroInit(const AllocatorDispatch* self, | 70 static void* MockAllocZeroInit(const AllocatorDispatch* self, |
| 69 size_t n, | 71 size_t n, |
| 70 size_t size) { | 72 size_t size, |
| 73 void* context) { |
| 71 const size_t real_size = n * size; | 74 const size_t real_size = n * size; |
| 72 if (instance_ && real_size < kMaxSizeTracked) | 75 if (instance_ && real_size < kMaxSizeTracked) |
| 73 ++(instance_->zero_allocs_intercepted_by_size[real_size]); | 76 ++(instance_->zero_allocs_intercepted_by_size[real_size]); |
| 74 return self->next->alloc_zero_initialized_function(self->next, n, size); | 77 return self->next->alloc_zero_initialized_function(self->next, n, size, |
| 78 context); |
| 75 } | 79 } |
| 76 | 80 |
| 77 static void* MockAllocAligned(const AllocatorDispatch* self, | 81 static void* MockAllocAligned(const AllocatorDispatch* self, |
| 78 size_t alignment, | 82 size_t alignment, |
| 79 size_t size) { | 83 size_t size, |
| 84 void* context) { |
| 80 if (instance_) { | 85 if (instance_) { |
| 81 if (size < kMaxSizeTracked) | 86 if (size < kMaxSizeTracked) |
| 82 ++(instance_->aligned_allocs_intercepted_by_size[size]); | 87 ++(instance_->aligned_allocs_intercepted_by_size[size]); |
| 83 if (alignment < kMaxSizeTracked) | 88 if (alignment < kMaxSizeTracked) |
| 84 ++(instance_->aligned_allocs_intercepted_by_alignment[alignment]); | 89 ++(instance_->aligned_allocs_intercepted_by_alignment[alignment]); |
| 85 } | 90 } |
| 86 return self->next->alloc_aligned_function(self->next, alignment, size); | 91 return self->next->alloc_aligned_function(self->next, alignment, size, |
| 92 context); |
| 87 } | 93 } |
| 88 | 94 |
| 89 static void* MockRealloc(const AllocatorDispatch* self, | 95 static void* MockRealloc(const AllocatorDispatch* self, |
| 90 void* address, | 96 void* address, |
| 91 size_t size) { | 97 size_t size, |
| 98 void* context) { |
| 92 if (instance_) { | 99 if (instance_) { |
| 93 // Size 0xFEED a special sentinel for the NewHandlerConcurrency test. | 100 // Size 0xFEED a special sentinel for the NewHandlerConcurrency test. |
| 94 // Hitting it for the first time will cause a failure, causing the | 101 // Hitting it for the first time will cause a failure, causing the |
| 95 // invocation of the std::new_handler. | 102 // invocation of the std::new_handler. |
| 96 if (size == 0xFEED) { | 103 if (size == 0xFEED) { |
| 97 if (!instance_->did_fail_realloc_0xfeed_once->Get()) { | 104 if (!instance_->did_fail_realloc_0xfeed_once->Get()) { |
| 98 instance_->did_fail_realloc_0xfeed_once->Set(true); | 105 instance_->did_fail_realloc_0xfeed_once->Set(true); |
| 99 return nullptr; | 106 return nullptr; |
| 100 } else { | 107 } else { |
| 101 return address; | 108 return address; |
| 102 } | 109 } |
| 103 } | 110 } |
| 104 | 111 |
| 105 if (size < kMaxSizeTracked) | 112 if (size < kMaxSizeTracked) |
| 106 ++(instance_->reallocs_intercepted_by_size[size]); | 113 ++(instance_->reallocs_intercepted_by_size[size]); |
| 107 ++instance_->reallocs_intercepted_by_addr[Hash(address)]; | 114 ++instance_->reallocs_intercepted_by_addr[Hash(address)]; |
| 108 } | 115 } |
| 109 return self->next->realloc_function(self->next, address, size); | 116 return self->next->realloc_function(self->next, address, size, context); |
| 110 } | 117 } |
| 111 | 118 |
| 112 static void MockFree(const AllocatorDispatch* self, void* address) { | 119 static void MockFree(const AllocatorDispatch* self, |
| 120 void* address, |
| 121 void* context) { |
| 113 if (instance_) { | 122 if (instance_) { |
| 114 ++instance_->frees_intercepted_by_addr[Hash(address)]; | 123 ++instance_->frees_intercepted_by_addr[Hash(address)]; |
| 115 } | 124 } |
| 116 self->next->free_function(self->next, address); | 125 self->next->free_function(self->next, address, context); |
| 117 } | 126 } |
| 118 | 127 |
| 119 static size_t MockGetSizeEstimate(const AllocatorDispatch* self, | 128 static size_t MockGetSizeEstimate(const AllocatorDispatch* self, |
| 120 void* address) { | 129 void* address, |
| 121 return self->next->get_size_estimate_function(self->next, address); | 130 void* context) { |
| 131 return self->next->get_size_estimate_function(self->next, address, context); |
| 122 } | 132 } |
| 123 | 133 |
| 124 static unsigned MockBatchMalloc(const AllocatorDispatch* self, | 134 static unsigned MockBatchMalloc(const AllocatorDispatch* self, |
| 125 size_t size, | 135 size_t size, |
| 126 void** results, | 136 void** results, |
| 127 unsigned num_requested) { | 137 unsigned num_requested, |
| 138 void* context) { |
| 128 if (instance_) { | 139 if (instance_) { |
| 129 instance_->batch_mallocs_intercepted_by_size[size] = | 140 instance_->batch_mallocs_intercepted_by_size[size] = |
| 130 instance_->batch_mallocs_intercepted_by_size[size] + num_requested; | 141 instance_->batch_mallocs_intercepted_by_size[size] + num_requested; |
| 131 } | 142 } |
| 132 return self->next->batch_malloc_function(self->next, size, results, | 143 return self->next->batch_malloc_function(self->next, size, results, |
| 133 num_requested); | 144 num_requested, context); |
| 134 } | 145 } |
| 135 | 146 |
| 136 static void MockBatchFree(const AllocatorDispatch* self, | 147 static void MockBatchFree(const AllocatorDispatch* self, |
| 137 void** to_be_freed, | 148 void** to_be_freed, |
| 138 unsigned num_to_be_freed) { | 149 unsigned num_to_be_freed, |
| 150 void* context) { |
| 139 if (instance_) { | 151 if (instance_) { |
| 140 for (unsigned i = 0; i < num_to_be_freed; ++i) { | 152 for (unsigned i = 0; i < num_to_be_freed; ++i) { |
| 141 ++instance_->batch_frees_intercepted_by_addr[Hash(to_be_freed[i])]; | 153 ++instance_->batch_frees_intercepted_by_addr[Hash(to_be_freed[i])]; |
| 142 } | 154 } |
| 143 } | 155 } |
| 144 self->next->batch_free_function(self->next, to_be_freed, num_to_be_freed); | 156 self->next->batch_free_function(self->next, to_be_freed, num_to_be_freed, |
| 157 context); |
| 145 } | 158 } |
| 146 | 159 |
| 147 static void MockFreeDefiniteSize(const AllocatorDispatch* self, | 160 static void MockFreeDefiniteSize(const AllocatorDispatch* self, |
| 148 void* ptr, | 161 void* ptr, |
| 149 size_t size) { | 162 size_t size, |
| 163 void* context) { |
| 150 if (instance_) { | 164 if (instance_) { |
| 151 ++instance_->frees_intercepted_by_addr[Hash(ptr)]; | 165 ++instance_->frees_intercepted_by_addr[Hash(ptr)]; |
| 152 ++instance_->free_definite_sizes_intercepted_by_size[size]; | 166 ++instance_->free_definite_sizes_intercepted_by_size[size]; |
| 153 } | 167 } |
| 154 self->next->free_definite_size_function(self->next, ptr, size); | 168 self->next->free_definite_size_function(self->next, ptr, size, context); |
| 155 } | 169 } |
| 156 | 170 |
| 157 static void NewHandler() { | 171 static void NewHandler() { |
| 158 if (!instance_) | 172 if (!instance_) |
| 159 return; | 173 return; |
| 160 subtle::Barrier_AtomicIncrement(&instance_->num_new_handler_calls, 1); | 174 subtle::Barrier_AtomicIncrement(&instance_->num_new_handler_calls, 1); |
| 161 } | 175 } |
| 162 | 176 |
| 163 int32_t GetNumberOfNewHandlerCalls() { | 177 int32_t GetNumberOfNewHandlerCalls() { |
| 164 return subtle::Acquire_Load(&instance_->num_new_handler_calls); | 178 return subtle::Acquire_Load(&instance_->num_new_handler_calls); |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 | 447 |
| 434 #if defined(OS_WIN) && BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) | 448 #if defined(OS_WIN) && BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) |
| 435 TEST_F(AllocatorShimTest, ShimReplacesCRTHeapWhenEnabled) { | 449 TEST_F(AllocatorShimTest, ShimReplacesCRTHeapWhenEnabled) { |
| 436 ASSERT_NE(::GetProcessHeap(), reinterpret_cast<HANDLE>(_get_heap_handle())); | 450 ASSERT_NE(::GetProcessHeap(), reinterpret_cast<HANDLE>(_get_heap_handle())); |
| 437 } | 451 } |
| 438 #endif // defined(OS_WIN) && BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) | 452 #endif // defined(OS_WIN) && BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) |
| 439 | 453 |
| 440 } // namespace | 454 } // namespace |
| 441 } // namespace allocator | 455 } // namespace allocator |
| 442 } // namespace base | 456 } // namespace base |
| OLD | NEW |