Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: base/allocator/allocator_shim_win.cc

Issue 774683003: Remove tcmalloc when not being used. Restore shim on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nits. add new OOM death test. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <malloc.h>
6 #include <new.h>
7 #include <windows.h>
8
9 #include "base/basictypes.h"
10
11 // This shim make it possible to perform additional checks on allocations
12 // before passing them to the Heap functions.
13
14 // new_mode behaves similarly to MSVC's _set_new_mode.
15 // If flag is 0 (default), calls to malloc will behave normally.
16 // If flag is 1, calls to malloc will behave like calls to new,
17 // and the std_new_handler will be invoked on failure.
18 // Can be set by calling _set_new_mode().
19 static int new_mode = 0;
20
21 namespace {
22
23 // This is a simple allocator based on the windows heap.
24 const size_t kWindowsPageSize = 4096;
25 const size_t kMaxWindowsAllocation = INT_MAX - kWindowsPageSize;
26 static HANDLE win_heap;
27
28 // VS2013 crt uses the process heap as its heap, so we do the same here.
29 // See heapinit.c in VS CRT sources.
30 bool win_heap_init() {
31 win_heap = GetProcessHeap();
32 if (win_heap == NULL)
33 return false;
34
35 ULONG enable_lfh = 2;
36 // NOTE: Setting LFH may fail. Vista already has it enabled.
37 // And under the debugger, it won't use LFH. So we
38 // ignore any errors.
39 HeapSetInformation(win_heap, HeapCompatibilityInformation, &enable_lfh,
40 sizeof(enable_lfh));
41
42 return true;
43 }
44
45 void* win_heap_malloc(size_t size) {
46 if (size < kMaxWindowsAllocation)
47 return HeapAlloc(win_heap, 0, size);
48 return NULL;
49 }
50
51 void win_heap_free(void* size) {
52 HeapFree(win_heap, 0, size);
53 }
54
55 void* win_heap_realloc(void* ptr, size_t size) {
56 if (!ptr)
57 return win_heap_malloc(size);
58 if (!size) {
59 win_heap_free(ptr);
60 return NULL;
61 }
62 if (size < kMaxWindowsAllocation)
63 return HeapReAlloc(win_heap, 0, ptr, size);
64 return NULL;
65 }
66
67 size_t win_heap_msize(void* ptr) {
68 return HeapSize(win_heap, 0, ptr);
69 }
70
71 void* win_heap_memalign(size_t alignment, size_t size) {
72 // Reserve enough space to ensure we can align and set aligned_ptr[-1] to the
73 // original allocation for use with win_heap_memalign_free() later.
74 size_t allocation_size = size + (alignment - 1) + sizeof(void*);
75
76 // Check for overflow. Alignment and size are checked in allocator_shim.
77 if (size >= allocation_size || alignment >= allocation_size) {
78 return NULL;
79 }
80
81 // Since we're directly calling the allocator function, before OOM handling,
82 // we need to NULL check to ensure the allocation succeeded.
83 void* ptr = win_heap_malloc(allocation_size);
84 if (!ptr)
85 return ptr;
86
87 char* aligned_ptr = static_cast<char*>(ptr) + sizeof(void*);
88 aligned_ptr +=
89 alignment - reinterpret_cast<uintptr_t>(aligned_ptr) & (alignment - 1);
90
91 reinterpret_cast<void**>(aligned_ptr)[-1] = ptr;
92 return aligned_ptr;
93 }
94
95 void win_heap_memalign_free(void* ptr) {
96 if (ptr)
97 win_heap_free(static_cast<void**>(ptr)[-1]);
98 }
99
100 void win_heap_term() {
101 win_heap = NULL;
102 }
103
104 } // namespace
105
106 // Call the new handler, if one has been set.
107 // Returns true on successfully calling the handler, false otherwise.
108 inline bool call_new_handler(bool nothrow, size_t size) {
109 // Get the current new handler.
110 _PNH nh = _query_new_handler();
111 #if defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
112 if (!nh)
113 return false;
114 // Since exceptions are disabled, we don't really know if new_handler
115 // failed. Assume it will abort if it fails.
116 return nh(size);
117 #else
scottmg 2015/01/12 16:51:01 Could probably just remove the _HAS_EXCEPTIONS arm
Will Harris 2015/01/12 19:03:44 Done. Added an #error like cpu suggested.
118 // If no new_handler is established, the allocation failed.
119 if (!nh) {
120 if (nothrow)
121 return false;
122 throw std::bad_alloc();
123 }
124 // Otherwise, try the new_handler. If it returns, retry the
125 // allocation. If it throws std::bad_alloc, fail the allocation.
126 // if it throws something else, don't interfere.
127 try {
128 return nh(size);
129 } catch (const std::bad_alloc&) {
130 if (!nothrow)
131 throw;
132 return true;
133 }
134 #endif // defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
135 return false;
136 }
137
138 extern "C" {
139
140 void* malloc(size_t size) {
141 void* ptr;
142 for (;;) {
143 ptr = win_heap_malloc(size);
144 if (ptr)
145 return ptr;
146
147 if (!new_mode || !call_new_handler(true, size))
148 break;
149 }
150 return ptr;
151 }
152
153 void free(void* p) {
154 win_heap_free(p);
155 return;
156 }
157
158 void* realloc(void* ptr, size_t size) {
159 // Webkit is brittle for allocators that return NULL for malloc(0). The
160 // realloc(0, 0) code path does not guarantee a non-NULL return, so be sure
161 // to call malloc for this case.
162 if (!ptr)
163 return malloc(size);
164
165 void* new_ptr;
166 for (;;) {
167 new_ptr = win_heap_realloc(ptr, size);
168
169 // Subtle warning: NULL return does not alwas indicate out-of-memory. If
170 // the requested new size is zero, realloc should free the ptr and return
171 // NULL.
172 if (new_ptr || !size)
173 return new_ptr;
174 if (!new_mode || !call_new_handler(true, size))
175 break;
176 }
177 return new_ptr;
178 }
179
180
181 size_t _msize(void* p) {
182 return win_heap_msize(p);
183 }
184
185 intptr_t _get_heap_handle() {
186 return reinterpret_cast<intptr_t>(win_heap);
187 }
188
189 // The CRT heap initialization stub.
190 int _heap_init() {
191 return win_heap_init() ? 1 : 0;
192 }
193
194 // The CRT heap cleanup stub.
195 void _heap_term() {
196 win_heap_term();
197 }
198
199 // We set this to 1 because part of the CRT uses a check of _crtheap != 0
200 // to test whether the CRT has been initialized. Once we've ripped out
201 // the allocators from libcmt, we need to provide this definition so that
202 // the rest of the CRT is still usable.
203 void* _crtheap = reinterpret_cast<void*>(1);
204
205 // Provide support for aligned memory through Windows only _aligned_malloc().
206 void* _aligned_malloc(size_t size, size_t alignment) {
207 // _aligned_malloc guarantees parameter validation, so do so here. These
208 // checks are somewhat stricter than _aligned_malloc() since we're effectively
209 // using memalign() under the hood.
210 if (size == 0U || (alignment & (alignment - 1)) != 0U ||
211 (alignment % sizeof(void*)) != 0U)
212 return NULL;
213
214 void* ptr;
215 for (;;) {
216 ptr = win_heap_memalign(alignment, size);
217
218 if (ptr) {
219 return ptr;
220 }
221
222 if (!new_mode || !call_new_handler(true, size))
223 break;
224 }
225 return ptr;
226 }
227
228 void _aligned_free(void* p) {
229 // Pointers allocated with win_heap_memalign() MUST be freed via
230 // win_heap_memalign_free() since the aligned pointer is not the real one.
231 win_heap_memalign_free(p);
232 }
233
234 #include "generic_allocators.cc"
235
236 } // extern C
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698