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

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 // TODO(jar): Switch to using TCMALLOC for the renderer as well.
44 static Allocator allocator = WINHEAP;
45
46 // The names of the environment variables that can optionally control the
47 // selection of the allocator. The primary may be used to control overall
48 // allocator selection, and the secondary can be used to specify an allocator
49 // to use in sub-processes.
50 static const char* primary_name = "CHROME_ALLOCATOR";
51 static const char* secondary_name = "CHROME_ALLOCATOR_2";
39 52
40 // We include tcmalloc and the win_allocator to get as much inlining as 53 // We include tcmalloc and the win_allocator to get as much inlining as
41 // possible. 54 // possible.
42 #include "tcmalloc.cc" 55 #include "tcmalloc.cc"
43 #include "win_allocator.cc" 56 #include "win_allocator.cc"
44 57
45 // Forward declarations from jemalloc. 58 // Forward declarations from jemalloc.
46 extern "C" { 59 extern "C" {
47 void* je_malloc(size_t s); 60 void* je_malloc(size_t s);
48 void* je_realloc(void* p, size_t s); 61 void* je_realloc(void* p, size_t s);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 } 107 }
95 108
96 void* malloc(size_t size) __THROW { 109 void* malloc(size_t size) __THROW {
97 void* ptr; 110 void* ptr;
98 for (;;) { 111 for (;;) {
99 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 112 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
100 switch (allocator) { 113 switch (allocator) {
101 case JEMALLOC: 114 case JEMALLOC:
102 ptr = je_malloc(size); 115 ptr = je_malloc(size);
103 break; 116 break;
104 case WINDEFAULT: 117 case WINHEAP:
105 case WINLFH: 118 case WINLFH:
106 ptr = win_heap_malloc(size); 119 ptr = win_heap_malloc(size);
107 break; 120 break;
108 case TCMALLOC: 121 case TCMALLOC:
109 default: 122 default:
110 ptr = do_malloc(size); 123 ptr = do_malloc(size);
111 break; 124 break;
112 } 125 }
113 #else 126 #else
114 // TCMalloc case. 127 // TCMalloc case.
115 ptr = do_malloc(size); 128 ptr = do_malloc(size);
116 #endif 129 #endif
117 if (ptr) 130 if (ptr)
118 return ptr; 131 return ptr;
119 132
120 if (!new_mode || !call_new_handler(true)) 133 if (!new_mode || !call_new_handler(true))
121 break; 134 break;
122 } 135 }
123 return ptr; 136 return ptr;
124 } 137 }
125 138
126 void free(void* p) __THROW { 139 void free(void* p) __THROW {
127 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 140 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
128 switch (allocator) { 141 switch (allocator) {
129 case JEMALLOC: 142 case JEMALLOC:
130 je_free(p); 143 je_free(p);
131 return; 144 return;
132 case WINDEFAULT: 145 case WINHEAP:
133 case WINLFH: 146 case WINLFH:
134 win_heap_free(p); 147 win_heap_free(p);
135 return; 148 return;
136 } 149 }
137 #endif 150 #endif
138 // TCMalloc case. 151 // TCMalloc case.
139 do_free(p); 152 do_free(p);
140 } 153 }
141 154
142 void* realloc(void* ptr, size_t size) __THROW { 155 void* realloc(void* ptr, size_t size) __THROW {
143 // Webkit is brittle for allocators that return NULL for malloc(0). The 156 // 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 157 // realloc(0, 0) code path does not guarantee a non-NULL return, so be sure
145 // to call malloc for this case. 158 // to call malloc for this case.
146 if (!ptr) 159 if (!ptr)
147 return malloc(size); 160 return malloc(size);
148 161
149 void* new_ptr; 162 void* new_ptr;
150 for (;;) { 163 for (;;) {
151 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 164 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
152 switch (allocator) { 165 switch (allocator) {
153 case JEMALLOC: 166 case JEMALLOC:
154 new_ptr = je_realloc(ptr, size); 167 new_ptr = je_realloc(ptr, size);
155 break; 168 break;
156 case WINDEFAULT: 169 case WINHEAP:
157 case WINLFH: 170 case WINLFH:
158 new_ptr = win_heap_realloc(ptr, size); 171 new_ptr = win_heap_realloc(ptr, size);
159 break; 172 break;
160 case TCMALLOC: 173 case TCMALLOC:
161 default: 174 default:
162 new_ptr = do_realloc(ptr, size); 175 new_ptr = do_realloc(ptr, size);
163 break; 176 break;
164 } 177 }
165 #else 178 #else
166 // TCMalloc case. 179 // TCMalloc case.
(...skipping 11 matching lines...) Expand all
178 return new_ptr; 191 return new_ptr;
179 } 192 }
180 193
181 // TODO(mbelshe): Implement this for other allocators. 194 // TODO(mbelshe): Implement this for other allocators.
182 void malloc_stats(void) __THROW { 195 void malloc_stats(void) __THROW {
183 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 196 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
184 switch (allocator) { 197 switch (allocator) {
185 case JEMALLOC: 198 case JEMALLOC:
186 // No stats. 199 // No stats.
187 return; 200 return;
188 case WINDEFAULT: 201 case WINHEAP:
189 case WINLFH: 202 case WINLFH:
190 // No stats. 203 // No stats.
191 return; 204 return;
192 } 205 }
193 #endif 206 #endif
194 tc_malloc_stats(); 207 tc_malloc_stats();
195 } 208 }
196 209
197 #ifdef WIN32 210 #ifdef WIN32
198 211
199 extern "C" size_t _msize(void* p) { 212 extern "C" size_t _msize(void* p) {
200 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 213 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
201 switch (allocator) { 214 switch (allocator) {
202 case JEMALLOC: 215 case JEMALLOC:
203 return je_msize(p); 216 return je_msize(p);
204 case WINDEFAULT: 217 case WINHEAP:
205 case WINLFH: 218 case WINLFH:
206 return win_heap_msize(p); 219 return win_heap_msize(p);
207 } 220 }
208 #endif 221 #endif
209 return MallocExtension::instance()->GetAllocatedSize(p); 222 return MallocExtension::instance()->GetAllocatedSize(p);
210 } 223 }
211 224
212 // This is included to resolve references from libcmt. 225 // This is included to resolve references from libcmt.
213 extern "C" intptr_t _get_heap_handle() { 226 extern "C" intptr_t _get_heap_handle() {
214 return 0; 227 return 0;
215 } 228 }
216 229
217 // The CRT heap initialization stub. 230 // The CRT heap initialization stub.
218 extern "C" int _heap_init() { 231 extern "C" int _heap_init() {
219 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING 232 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
220 const char* override = GetenvBeforeMain("CHROME_ALLOCATOR"); 233 const char* environment_value = GetenvBeforeMain(primary_name);
221 if (override) { 234 if (environment_value) {
222 if (!stricmp(override, "jemalloc")) 235 if (!stricmp(environment_value, "jemalloc"))
223 allocator = JEMALLOC; 236 allocator = JEMALLOC;
224 else if (!stricmp(override, "winheap")) 237 else if (!stricmp(environment_value, "winheap"))
225 allocator = WINDEFAULT; 238 allocator = WINHEAP;
226 else if (!stricmp(override, "winlfh")) 239 else if (!stricmp(environment_value, "winlfh"))
227 allocator = WINLFH; 240 allocator = WINLFH;
228 else if (!stricmp(override, "tcmalloc")) 241 else if (!stricmp(environment_value, "tcmalloc"))
229 allocator = TCMALLOC; 242 allocator = TCMALLOC;
230 } 243 }
231 244
232 switch (allocator) { 245 switch (allocator) {
233 case JEMALLOC: 246 case JEMALLOC:
234 return je_malloc_init_hard() ? 0 : 1; 247 return je_malloc_init_hard() ? 0 : 1;
235 case WINDEFAULT: 248 case WINHEAP:
236 return win_heap_init(false) ? 1 : 0; 249 return win_heap_init(false) ? 1 : 0;
237 case WINLFH: 250 case WINLFH:
238 return win_heap_init(true) ? 1 : 0; 251 return win_heap_init(true) ? 1 : 0;
239 case TCMALLOC: 252 case TCMALLOC:
240 default: 253 default:
241 // fall through 254 // fall through
242 break; 255 break;
243 } 256 }
244 #endif 257 #endif
245 // Initializing tcmalloc. 258 // Initializing tcmalloc.
(...skipping 11 matching lines...) Expand all
257 // to test whether the CRT has been initialized. Once we've ripped out 270 // 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 271 // the allocators from libcmt, we need to provide this definition so that
259 // the rest of the CRT is still usable. 272 // the rest of the CRT is still usable.
260 extern "C" void* _crtheap = reinterpret_cast<void*>(1); 273 extern "C" void* _crtheap = reinterpret_cast<void*>(1);
261 274
262 #endif // WIN32 275 #endif // WIN32
263 276
264 #include "generic_allocators.cc" 277 #include "generic_allocators.cc"
265 278
266 } // extern C 279 } // extern C
280
281 namespace base {
282 namespace allocator {
283
284 void SetupSubprocessAllocator() {
285 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
286 size_t primary_length = 0;
287 getenv_s(&primary_length, NULL, 0, primary_name);
288
289 size_t secondary_length = 0;
290 char buffer[20];
291 getenv_s(&secondary_length, buffer, sizeof(buffer), secondary_name);
292 DCHECK_GT(sizeof(buffer), secondary_length);
293 buffer[sizeof(buffer) - 1] = '\0';
294
295 if (secondary_length || !primary_length) {
296 char* secondary_value = secondary_length ? buffer : "TCMALLOC";
297 // Force renderer (or other subprocesses) to use secondary_value.
298 int ret_val = _putenv_s(primary_name, secondary_value);
299 CHECK_EQ(0, ret_val);
300 }
301 #endif // ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
302 }
303
304 } // namespace base.
305 } // 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