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

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

Issue 6623059: Support mixed allocation in browser vs subprocesses... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « base/allocator/allocator_shim.h ('k') | chrome/browser/browser_main.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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"
6
5 #include <config.h> 7 #include <config.h>
6 8
7 // When defined, different heap allocators can be used via an environment 9 // When defined, different heap allocators can be used via an environment
8 // variable set before running the program. This may reduce the amount 10 // variable set before running the program. This may reduce the amount
9 // of inlining that we get with malloc/free/etc. Disabling makes it 11 // of inlining that we get with malloc/free/etc. Disabling makes it
10 // so that only tcmalloc can be used. 12 // so that only tcmalloc can be used.
11 #define ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 13 #define ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
12 14
13 // TODO(mbelshe): Ensure that all calls to tcmalloc have the proper call depth 15 // TODO(mbelshe): Ensure that all calls to tcmalloc have the proper call depth
14 // from the "user code" so that debugging tools (HeapChecker) can work. 16 // from the "user code" so that debugging tools (HeapChecker) can work.
15 17
16 // __THROW is defined in glibc systems. It means, counter-intuitively, 18 // __THROW is defined in glibc systems. It means, counter-intuitively,
17 // "This function will never throw an exception." It's an optional 19 // "This function will never throw an exception." It's an optional
18 // optimization tool, but we may need to use it to match glibc prototypes. 20 // optimization tool, but we may need to use it to match glibc prototypes.
19 #ifndef __THROW // I guess we're not on a glibc system 21 #ifndef __THROW // I guess we're not on a glibc system
20 # define __THROW // __THROW is just an optimization, so ok to make it "" 22 # define __THROW // __THROW is just an optimization, so ok to make it ""
21 #endif 23 #endif
22 24
23 // new_mode behaves similarly to MSVC's _set_new_mode. 25 // new_mode behaves similarly to MSVC's _set_new_mode.
24 // If flag is 0 (default), calls to malloc will behave normally. 26 // If flag is 0 (default), calls to malloc will behave normally.
25 // If flag is 1, calls to malloc will behave like calls to new, 27 // If flag is 1, calls to malloc will behave like calls to new,
26 // and the std_new_handler will be invoked on failure. 28 // and the std_new_handler will be invoked on failure.
27 // Can be set by calling _set_new_mode(). 29 // Can be set by calling _set_new_mode().
28 static int new_mode = 0; 30 static int new_mode = 0;
29 31
30 typedef enum { 32 typedef enum {
31 TCMALLOC, // TCMalloc is the default allocator. 33 TCMALLOC, // TCMalloc is the default allocator.
32 JEMALLOC, // JEMalloc 34 JEMALLOC, // JEMalloc.
33 WINDEFAULT, // Windows Heap 35 WINHEAP, // Windows Heap (standard Windows allocator).
34 WINLFH, // Windows LFH Heap 36 WINLFH, // Windows LFH Heap.
35 } Allocator; 37 } Allocator;
36 38
37 // This is the default allocator. 39 // This is the default allocator. This value can be changed at startup by
38 static Allocator allocator = TCMALLOC; 40 // specifying environment variables shown below it.
41 // See SetupSubprocessAllocator() to specify a default secondary (subprocess)
42 // allocator.
43 static Allocator allocator = WINHEAP;
44
45 // The names of the environment variables that can optionally control the
46 // selection of the allocator. The primary may be used to control overall
47 // allocator selection, and the secondary can be used to specify an allocator
48 // to use in sub-processes.
49 static const char* primary_name = "CHROME_ALLOCATOR";
50 static const char* secondary_name = "CHROME_ALLOCATOR_2";
39 51
40 // We include tcmalloc and the win_allocator to get as much inlining as 52 // We include tcmalloc and the win_allocator to get as much inlining as
41 // possible. 53 // possible.
42 #include "tcmalloc.cc" 54 #include "tcmalloc.cc"
43 #include "win_allocator.cc" 55 #include "win_allocator.cc"
44 56
45 // Forward declarations from jemalloc. 57 // Forward declarations from jemalloc.
46 extern "C" { 58 extern "C" {
47 void* je_malloc(size_t s); 59 void* je_malloc(size_t s);
48 void* je_realloc(void* p, size_t s); 60 void* je_realloc(void* p, size_t s);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 } 106 }
95 107
96 void* malloc(size_t size) __THROW { 108 void* malloc(size_t size) __THROW {
97 void* ptr; 109 void* ptr;
98 for (;;) { 110 for (;;) {
99 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 111 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
100 switch (allocator) { 112 switch (allocator) {
101 case JEMALLOC: 113 case JEMALLOC:
102 ptr = je_malloc(size); 114 ptr = je_malloc(size);
103 break; 115 break;
104 case WINDEFAULT: 116 case WINHEAP:
105 case WINLFH: 117 case WINLFH:
106 ptr = win_heap_malloc(size); 118 ptr = win_heap_malloc(size);
107 break; 119 break;
108 case TCMALLOC: 120 case TCMALLOC:
109 default: 121 default:
110 ptr = do_malloc(size); 122 ptr = do_malloc(size);
111 break; 123 break;
112 } 124 }
113 #else 125 #else
114 // TCMalloc case. 126 // TCMalloc case.
115 ptr = do_malloc(size); 127 ptr = do_malloc(size);
116 #endif 128 #endif
117 if (ptr) 129 if (ptr)
118 return ptr; 130 return ptr;
119 131
120 if (!new_mode || !call_new_handler(true)) 132 if (!new_mode || !call_new_handler(true))
121 break; 133 break;
122 } 134 }
123 return ptr; 135 return ptr;
124 } 136 }
125 137
126 void free(void* p) __THROW { 138 void free(void* p) __THROW {
127 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 139 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
128 switch (allocator) { 140 switch (allocator) {
129 case JEMALLOC: 141 case JEMALLOC:
130 je_free(p); 142 je_free(p);
131 return; 143 return;
132 case WINDEFAULT: 144 case WINHEAP:
133 case WINLFH: 145 case WINLFH:
134 win_heap_free(p); 146 win_heap_free(p);
135 return; 147 return;
136 } 148 }
137 #endif 149 #endif
138 // TCMalloc case. 150 // TCMalloc case.
139 do_free(p); 151 do_free(p);
140 } 152 }
141 153
142 void* realloc(void* ptr, size_t size) __THROW { 154 void* realloc(void* ptr, size_t size) __THROW {
143 // Webkit is brittle for allocators that return NULL for malloc(0). The 155 // Webkit is brittle for allocators that return NULL for malloc(0). The
144 // realloc(0, 0) code path does not guarantee a non-NULL return, so be sure 156 // realloc(0, 0) code path does not guarantee a non-NULL return, so be sure
145 // to call malloc for this case. 157 // to call malloc for this case.
146 if (!ptr) 158 if (!ptr)
147 return malloc(size); 159 return malloc(size);
148 160
149 void* new_ptr; 161 void* new_ptr;
150 for (;;) { 162 for (;;) {
151 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 163 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
152 switch (allocator) { 164 switch (allocator) {
153 case JEMALLOC: 165 case JEMALLOC:
154 new_ptr = je_realloc(ptr, size); 166 new_ptr = je_realloc(ptr, size);
155 break; 167 break;
156 case WINDEFAULT: 168 case WINHEAP:
157 case WINLFH: 169 case WINLFH:
158 new_ptr = win_heap_realloc(ptr, size); 170 new_ptr = win_heap_realloc(ptr, size);
159 break; 171 break;
160 case TCMALLOC: 172 case TCMALLOC:
161 default: 173 default:
162 new_ptr = do_realloc(ptr, size); 174 new_ptr = do_realloc(ptr, size);
163 break; 175 break;
164 } 176 }
165 #else 177 #else
166 // TCMalloc case. 178 // TCMalloc case.
(...skipping 11 matching lines...) Expand all
178 return new_ptr; 190 return new_ptr;
179 } 191 }
180 192
181 // TODO(mbelshe): Implement this for other allocators. 193 // TODO(mbelshe): Implement this for other allocators.
182 void malloc_stats(void) __THROW { 194 void malloc_stats(void) __THROW {
183 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 195 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
184 switch (allocator) { 196 switch (allocator) {
185 case JEMALLOC: 197 case JEMALLOC:
186 // No stats. 198 // No stats.
187 return; 199 return;
188 case WINDEFAULT: 200 case WINHEAP:
189 case WINLFH: 201 case WINLFH:
190 // No stats. 202 // No stats.
191 return; 203 return;
192 } 204 }
193 #endif 205 #endif
194 tc_malloc_stats(); 206 tc_malloc_stats();
195 } 207 }
196 208
197 #ifdef WIN32 209 #ifdef WIN32
198 210
199 extern "C" size_t _msize(void* p) { 211 extern "C" size_t _msize(void* p) {
200 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 212 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
201 switch (allocator) { 213 switch (allocator) {
202 case JEMALLOC: 214 case JEMALLOC:
203 return je_msize(p); 215 return je_msize(p);
204 case WINDEFAULT: 216 case WINHEAP:
205 case WINLFH: 217 case WINLFH:
206 return win_heap_msize(p); 218 return win_heap_msize(p);
207 } 219 }
208 #endif 220 #endif
209 return MallocExtension::instance()->GetAllocatedSize(p); 221 return MallocExtension::instance()->GetAllocatedSize(p);
210 } 222 }
211 223
212 // This is included to resolve references from libcmt. 224 // This is included to resolve references from libcmt.
213 extern "C" intptr_t _get_heap_handle() { 225 extern "C" intptr_t _get_heap_handle() {
214 return 0; 226 return 0;
215 } 227 }
216 228
217 // The CRT heap initialization stub. 229 // The CRT heap initialization stub.
218 extern "C" int _heap_init() { 230 extern "C" int _heap_init() {
219 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 231 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
220 const char* override = GetenvBeforeMain("CHROME_ALLOCATOR"); 232 const char* environment_value = GetenvBeforeMain(primary_name);
221 if (override) { 233 if (environment_value) {
222 if (!stricmp(override, "jemalloc")) 234 if (!stricmp(environment_value, "jemalloc"))
223 allocator = JEMALLOC; 235 allocator = JEMALLOC;
224 else if (!stricmp(override, "winheap")) 236 else if (!stricmp(environment_value, "winheap"))
225 allocator = WINDEFAULT; 237 allocator = WINHEAP;
226 else if (!stricmp(override, "winlfh")) 238 else if (!stricmp(environment_value, "winlfh"))
227 allocator = WINLFH; 239 allocator = WINLFH;
228 else if (!stricmp(override, "tcmalloc")) 240 else if (!stricmp(environment_value, "tcmalloc"))
229 allocator = TCMALLOC; 241 allocator = TCMALLOC;
230 } 242 }
231 243
232 switch (allocator) { 244 switch (allocator) {
233 case JEMALLOC: 245 case JEMALLOC:
234 return je_malloc_init_hard() ? 0 : 1; 246 return je_malloc_init_hard() ? 0 : 1;
235 case WINDEFAULT: 247 case WINHEAP:
236 return win_heap_init(false) ? 1 : 0; 248 return win_heap_init(false) ? 1 : 0;
237 case WINLFH: 249 case WINLFH:
238 return win_heap_init(true) ? 1 : 0; 250 return win_heap_init(true) ? 1 : 0;
239 case TCMALLOC: 251 case TCMALLOC:
240 default: 252 default:
241 // fall through 253 // fall through
242 break; 254 break;
243 } 255 }
244 #endif 256 #endif
245 // Initializing tcmalloc. 257 // Initializing tcmalloc.
(...skipping 11 matching lines...) Expand all
257 // to test whether the CRT has been initialized. Once we've ripped out 269 // to test whether the CRT has been initialized. Once we've ripped out
258 // the allocators from libcmt, we need to provide this definition so that 270 // the allocators from libcmt, we need to provide this definition so that
259 // the rest of the CRT is still usable. 271 // the rest of the CRT is still usable.
260 extern "C" void* _crtheap = reinterpret_cast<void*>(1); 272 extern "C" void* _crtheap = reinterpret_cast<void*>(1);
261 273
262 #endif // WIN32 274 #endif // WIN32
263 275
264 #include "generic_allocators.cc" 276 #include "generic_allocators.cc"
265 277
266 } // extern C 278 } // extern C
279
280 namespace base {
281 namespace allocator {
282
283 void SetupSubprocessAllocator() {
284 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
285 size_t primary_length = 0;
286 getenv_s(&primary_length, NULL, 0, primary_name);
287
288 size_t secondary_length = 0;
289 char buffer[20];
290 getenv_s(&secondary_length, buffer, sizeof(buffer), secondary_name);
Mike Belshe 2011/03/07 22:37:16 nit: not sure if this API provides null terminatio
jar (doing other things) 2011/03/07 22:45:07 Added safety net null termination (especially sinc
291 DCHECK_GT(sizeof(buffer), secondary_length);
292
293 if (secondary_length || !primary_length) {
294 char* secondary_value = secondary_length ? buffer : "TCMALLOC";
295 // Force renderer (or other subprocesses) to use secondary_value.
296 int ret_val = _putenv_s(primary_name, secondary_value);
297 CHECK_EQ(0, ret_val);
298 }
299 #endif // ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
300 }
301
302 } // namespace base.
303 } // namespace allocator.
OLDNEW
« no previous file with comments | « base/allocator/allocator_shim.h ('k') | chrome/browser/browser_main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698