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

Side by Side Diff: third_party/tcmalloc/allocator_shim.cc

Issue 165275: Major changes to the Chrome allocator.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 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 | « third_party/tcmalloc/README ('k') | third_party/tcmalloc/generic_allocators.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) 2009 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 <config.h>
6
7 // When defined, different heap allocators can be used via an environment
8 // variable set before running the program. This may reduce the amount
9 // of inlining that we get with malloc/free/etc. Disabling makes it
10 // so that only tcmalloc can be used.
11 #define ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
12
13 // 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.
15
16 // __THROW is defined in glibc systems. It means, counter-intuitively,
17 // "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.
19 #ifndef __THROW // I guess we're not on a glibc system
20 # define __THROW // __THROW is just an optimization, so ok to make it ""
21 #endif
22
23 // new_mode behaves similarly to MSVC's _set_new_mode.
24 // 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,
26 // and the std_new_handler will be invoked on failure.
27 // Can be set by calling _set_new_mode().
28 static int new_mode = 0;
29
30 typedef enum {
31 TCMALLOC, // TCMalloc is the default allocator.
32 JEMALLOC, // JEMalloc
33 WINDEFAULT, // Windows Heap
34 WINLFH, // Windows LFH Heap
35 } Allocator;
36
37 // This is the default allocator.
38 static Allocator allocator = TCMALLOC;
39
40 // We include tcmalloc and the win_allocator to get as much inlining as
41 // possible.
42 #include "tcmalloc.cc"
43 #include "win_allocator.cc"
44
45 // Forward declarations from jemalloc.
46 extern "C" {
47 void* je_malloc(size_t s);
48 void* je_realloc(void* p, size_t s);
49 void je_free(void* s);
50 size_t je_msize(void* p);
51 bool je_malloc_init_hard();
52 }
53
54 extern "C" {
55
56 // Call the new handler, if one has been set.
57 // Returns true on successfully calling the handler, false otherwise.
58 inline bool call_new_handler(bool nothrow) {
59 // Get the current new handler. NB: this function is not
60 // thread-safe. We make a feeble stab at making it so here, but
61 // this lock only protects against tcmalloc interfering with
62 // itself, not with other libraries calling set_new_handler.
63 std::new_handler nh;
64 {
65 SpinLockHolder h(&set_new_handler_lock);
66 nh = std::set_new_handler(0);
67 (void) std::set_new_handler(nh);
68 }
69 #if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) & & !_HAS_EXCEPTIONS)
70 if (!nh)
71 return false;
72 // Since exceptions are disabled, we don't really know if new_handler
73 // failed. Assume it will abort if it fails.
74 (*nh)();
75 return true;
76 #else
77 // If no new_handler is established, the allocation failed.
78 if (!nh) {
79 if (nothrow)
80 return 0;
81 throw std::bad_alloc();
82 }
83 // Otherwise, try the new_handler. If it returns, retry the
84 // allocation. If it throws std::bad_alloc, fail the allocation.
85 // if it throws something else, don't interfere.
86 try {
87 (*nh)();
88 } catch (const std::bad_alloc&) {
89 if (!nothrow)
90 throw;
91 return p;
92 }
93 #endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPT IONS) && !_HAS_EXCEPTIONS)
94 }
95
96 void* malloc(size_t size) __THROW {
97 void* ptr;
98 for (;;) {
99 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
100 switch (allocator) {
101 case JEMALLOC:
102 ptr = je_malloc(size);
103 break;
104 case WINDEFAULT:
105 case WINLFH:
106 ptr = win_heap_malloc(size);
107 break;
108 case TCMALLOC:
109 default:
110 ptr = do_malloc(size);
111 break;
112 }
113 #else
114 // TCMalloc case.
115 ptr = do_malloc(size);
116 #endif
117 if (ptr)
118 return ptr;
119
120 if (!new_mode || !call_new_handler(true))
121 break;
122 }
123 return ptr;
124 }
125
126 void free(void* p) __THROW {
127 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
128 switch (allocator) {
129 case JEMALLOC:
130 je_free(p);
131 return;
132 case WINDEFAULT:
133 case WINLFH:
134 win_heap_free(p);
135 return;
136 }
137 #endif
138 // TCMalloc case.
139 do_free(p);
140 }
141
142 void* realloc(void* ptr, size_t size) __THROW {
143 void* new_ptr;
144 for (;;) {
145 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
146 switch (allocator) {
147 case JEMALLOC:
148 new_ptr = je_realloc(ptr, size);
149 break;
150 case WINDEFAULT:
151 case WINLFH:
152 new_ptr = win_heap_realloc(ptr, size);
153 break;
154 case TCMALLOC:
155 default:
156 new_ptr = do_realloc(ptr, size);
157 break;
158 }
159 #else
160 // TCMalloc case.
161 new_ptr = do_realloc(ptr, size);
162 #endif
163 if (new_ptr)
164 return new_ptr;
165 if (!new_mode || !call_new_handler(true))
166 break;
167 }
168 return new_ptr;
169 }
170
171 // TODO(mbelshe): Implement this for other allocators.
172 void malloc_stats(void) __THROW {
173 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
174 switch (allocator) {
175 case JEMALLOC:
176 // No stats.
177 return;
178 case WINDEFAULT:
179 case WINLFH:
180 // No stats.
181 return;
182 }
183 #endif
184 tc_malloc_stats();
185 }
186
187 #ifdef WIN32
188
189 extern "C" size_t _msize(void* p) {
190 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
191 switch (allocator) {
192 case JEMALLOC:
193 return je_msize(p);
194 case WINDEFAULT:
195 case WINLFH:
196 return win_heap_msize(p);
197 }
198 #endif
199 return MallocExtension::instance()->GetAllocatedSize(p);
200 }
201
202 // This is included to resolve references from libcmt.
203 extern "C" intptr_t _get_heap_handle() {
204 return 0;
205 }
206
207 // The CRT heap initialization stub.
208 extern "C" int _heap_init() {
209 #ifdef ENABLE_DYNAMIC_ALLOCATOR_SWITCHING
210 const char* override = GetenvBeforeMain("CHROME_ALLOCATOR");
211 if (override) {
212 if (!stricmp(override, "jemalloc"))
213 allocator = JEMALLOC;
214 else if (!stricmp(override, "winheap"))
215 allocator = WINDEFAULT;
216 else if (!stricmp(override, "winlfh"))
217 allocator = WINLFH;
218 else if (!stricmp(override, "tcmalloc"))
219 allocator = TCMALLOC;
220 }
221
222 switch (allocator) {
223 case JEMALLOC:
224 return je_malloc_init_hard() ? 0 : 1;
225 case WINDEFAULT:
226 return win_heap_init(false) ? 1 : 0;
227 case WINLFH:
228 return win_heap_init(true) ? 1 : 0;
229 case TCMALLOC:
230 default:
231 // fall through
232 break;
233 }
234 #endif
235 // Initializing tcmalloc.
236 // We intentionally leak this object. It lasts for the process
237 // lifetime. Trying to teardown at _heap_term() is so late that
238 // you can't do anything useful anyway.
239 new TCMallocGuard();
240 return 1;
241 }
242
243 // The CRT heap cleanup stub.
244 extern "C" void _heap_term() {}
245
246 // We set this to 1 because part of the CRT uses a check of _crtheap != 0
247 // to test whether the CRT has been initialized. Once we've ripped out
248 // the allocators from libcmt, we need to provide this definition so that
249 // the rest of the CRT is still usable.
250 extern "C" void* _crtheap = reinterpret_cast<void*>(1);
251
252 #endif // WIN32
253
254 #include "generic_allocators.cc"
255
256 } // extern C
OLDNEW
« no previous file with comments | « third_party/tcmalloc/README ('k') | third_party/tcmalloc/generic_allocators.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698