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

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: add realloc death test. nits. 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
« no previous file with comments | « base/allocator/allocator_shim.cc ('k') | base/allocator/allocator_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
118 #error "Exceptions in allocator shim are not supported!"
119 #endif // defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
120 return false;
121 }
122
123 extern "C" {
124
125 void* malloc(size_t size) {
126 void* ptr;
127 for (;;) {
128 ptr = win_heap_malloc(size);
129 if (ptr)
130 return ptr;
131
132 if (!new_mode || !call_new_handler(true, size))
133 break;
134 }
135 return ptr;
136 }
137
138 void free(void* p) {
139 win_heap_free(p);
140 return;
141 }
142
143 void* realloc(void* ptr, size_t size) {
144 // Webkit is brittle for allocators that return NULL for malloc(0). The
145 // realloc(0, 0) code path does not guarantee a non-NULL return, so be sure
146 // to call malloc for this case.
147 if (!ptr)
148 return malloc(size);
149
150 void* new_ptr;
151 for (;;) {
152 new_ptr = win_heap_realloc(ptr, size);
153
154 // Subtle warning: NULL return does not alwas indicate out-of-memory. If
155 // the requested new size is zero, realloc should free the ptr and return
156 // NULL.
157 if (new_ptr || !size)
158 return new_ptr;
159 if (!new_mode || !call_new_handler(true, size))
160 break;
161 }
162 return new_ptr;
163 }
164
165
166 size_t _msize(void* p) {
167 return win_heap_msize(p);
168 }
169
170 intptr_t _get_heap_handle() {
171 return reinterpret_cast<intptr_t>(win_heap);
172 }
173
174 // The CRT heap initialization stub.
175 int _heap_init() {
176 return win_heap_init() ? 1 : 0;
177 }
178
179 // The CRT heap cleanup stub.
180 void _heap_term() {
181 win_heap_term();
182 }
183
184 // We set this to 1 because part of the CRT uses a check of _crtheap != 0
185 // to test whether the CRT has been initialized. Once we've ripped out
186 // the allocators from libcmt, we need to provide this definition so that
187 // the rest of the CRT is still usable.
188 void* _crtheap = reinterpret_cast<void*>(1);
189
190 // Provide support for aligned memory through Windows only _aligned_malloc().
191 void* _aligned_malloc(size_t size, size_t alignment) {
192 // _aligned_malloc guarantees parameter validation, so do so here. These
193 // checks are somewhat stricter than _aligned_malloc() since we're effectively
194 // using memalign() under the hood.
195 if (size == 0U || (alignment & (alignment - 1)) != 0U ||
196 (alignment % sizeof(void*)) != 0U)
197 return NULL;
198
199 void* ptr;
200 for (;;) {
201 ptr = win_heap_memalign(alignment, size);
202
203 if (ptr) {
204 return ptr;
205 }
206
207 if (!new_mode || !call_new_handler(true, size))
208 break;
209 }
210 return ptr;
211 }
212
213 void _aligned_free(void* p) {
214 // Pointers allocated with win_heap_memalign() MUST be freed via
215 // win_heap_memalign_free() since the aligned pointer is not the real one.
216 win_heap_memalign_free(p);
217 }
218
219 #include "generic_allocators.cc"
220
221 } // extern C
OLDNEW
« no previous file with comments | « base/allocator/allocator_shim.cc ('k') | base/allocator/allocator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698