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

Side by Side Diff: third_party/tcmalloc/chromium/src/tcmalloc.cc

Issue 9323026: [NOT TO COMMIT!] r109: Diff of the current tcmalloc from the original google-perftools r109. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 8 years, 10 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
OLDNEW
1 // Copyright (c) 2005, Google Inc. 1 // Copyright (c) 2005, Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 #include <vector> // for vector 115 #include <vector> // for vector
116 116
117 #include <google/malloc_extension.h> 117 #include <google/malloc_extension.h>
118 #include <google/malloc_hook.h> // for MallocHook 118 #include <google/malloc_hook.h> // for MallocHook
119 #include "base/basictypes.h" // for int64 119 #include "base/basictypes.h" // for int64
120 #include "base/commandlineflags.h" // for RegisterFlagValidator, etc 120 #include "base/commandlineflags.h" // for RegisterFlagValidator, etc
121 #include "base/dynamic_annotations.h" // for RunningOnValgrind 121 #include "base/dynamic_annotations.h" // for RunningOnValgrind
122 #include "base/spinlock.h" // for SpinLockHolder 122 #include "base/spinlock.h" // for SpinLockHolder
123 #include "central_freelist.h" // for CentralFreeListPadded 123 #include "central_freelist.h" // for CentralFreeListPadded
124 #include "common.h" // for StackTrace, kPageShift, etc 124 #include "common.h" // for StackTrace, kPageShift, etc
125 #include "free_list.h" // for FL_Init
125 #include "internal_logging.h" // for ASSERT, TCMalloc_Printer, etc 126 #include "internal_logging.h" // for ASSERT, TCMalloc_Printer, etc
126 #include "linked_list.h" // for SLL_SetNext
127 #include "malloc_hook-inl.h" // for MallocHook::InvokeNewHook, etc 127 #include "malloc_hook-inl.h" // for MallocHook::InvokeNewHook, etc
128 #include "page_heap.h" // for PageHeap, PageHeap::Stats 128 #include "page_heap.h" // for PageHeap, PageHeap::Stats
129 #include "page_heap_allocator.h" // for PageHeapAllocator 129 #include "page_heap_allocator.h" // for PageHeapAllocator
130 #include "span.h" // for Span, DLL_Prepend, etc 130 #include "span.h" // for Span, DLL_Prepend, etc
131 #include "stack_trace_table.h" // for StackTraceTable 131 #include "stack_trace_table.h" // for StackTraceTable
132 #include "static_vars.h" // for Static 132 #include "static_vars.h" // for Static
133 #include "system-alloc.h" // for DumpSystemAllocatorStats, etc 133 #include "system-alloc.h" // for DumpSystemAllocatorStats, etc
134 #include "tcmalloc_guard.h" // for TCMallocGuard 134 #include "tcmalloc_guard.h" // for TCMallocGuard
135 #include "thread_cache.h" // for ThreadCache 135 #include "thread_cache.h" // for ThreadCache
136 136
137 // We only need malloc.h for struct mallinfo. 137 // We only need malloc.h for struct mallinfo.
138 #ifdef HAVE_STRUCT_MALLINFO 138 #ifdef HAVE_STRUCT_MALLINFO
139 // Malloc can be in several places on older versions of OS X. 139 // Malloc can be in several places on older versions of OS X.
140 # if defined(HAVE_MALLOC_H) 140 # if defined(HAVE_MALLOC_H)
141 # include <malloc.h> 141 # include <malloc.h>
142 # elif defined(HAVE_SYS_MALLOC_H) 142 # elif defined(HAVE_SYS_MALLOC_H)
143 # include <sys/malloc.h> 143 # include <sys/malloc.h>
144 # elif defined(HAVE_MALLOC_MALLOC_H) 144 # elif defined(HAVE_MALLOC_MALLOC_H)
145 # include <malloc/malloc.h> 145 # include <malloc/malloc.h>
146 # endif 146 # endif
147 #endif 147 #endif
148 148
149 #if (defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)) && !defi ned(WIN32_OVERRIDE_ALLOCATORS) 149 #if (defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)) && !defi ned(WIN32_OVERRIDE_ALLOCATORS)
150 # define WIN32_DO_PATCHING 1 150 # define WIN32_DO_PATCHING 1
151 #endif 151 #endif
152 152
153 // GLibc 2.14+ requires the hook functions be declared volatile, based on the
154 // value of the define __MALLOC_HOOK_VOLATILE. For compatibility with
155 // older/non-GLibc implementations, provide an empty definition.
156 #if !defined(__MALLOC_HOOK_VOLATILE)
157 #define __MALLOC_HOOK_VOLATILE
158 #endif
159
153 using STL_NAMESPACE::max; 160 using STL_NAMESPACE::max;
154 using STL_NAMESPACE::numeric_limits; 161 using STL_NAMESPACE::numeric_limits;
155 using STL_NAMESPACE::vector; 162 using STL_NAMESPACE::vector;
156 using tcmalloc::AlignmentForSize; 163 using tcmalloc::AlignmentForSize;
157 using tcmalloc::PageHeap; 164 using tcmalloc::PageHeap;
158 using tcmalloc::PageHeapAllocator; 165 using tcmalloc::PageHeapAllocator;
159 using tcmalloc::SizeMap; 166 using tcmalloc::SizeMap;
160 using tcmalloc::Span; 167 using tcmalloc::Span;
161 using tcmalloc::StackTrace; 168 using tcmalloc::StackTrace;
162 using tcmalloc::Static; 169 using tcmalloc::Static;
163 using tcmalloc::ThreadCache; 170 using tcmalloc::ThreadCache;
164 171
165 // __THROW is defined in glibc systems. It means, counter-intuitively, 172 // __THROW is defined in glibc systems. It means, counter-intuitively,
166 // "This function will never throw an exception." It's an optional 173 // "This function will never throw an exception." It's an optional
167 // optimization tool, but we may need to use it to match glibc prototypes. 174 // optimization tool, but we may need to use it to match glibc prototypes.
168 #ifndef __THROW // I guess we're not on a glibc system 175 #ifndef __THROW // I guess we're not on a glibc system
169 # define __THROW // __THROW is just an optimization, so ok to make it "" 176 # define __THROW // __THROW is just an optimization, so ok to make it ""
170 #endif 177 #endif
171 178
179 // ---- Double free debug declarations
180 static size_t ExcludeSpaceForMark(size_t size);
181 static void AddRoomForMark(size_t* size);
182 static void ExcludeMarkFromSize(size_t* new_size);
183 static void MarkAllocatedRegion(void* ptr);
184 static void ValidateAllocatedRegion(void* ptr, size_t cl);
185 // ---- End Double free debug declarations
186
172 DECLARE_int64(tcmalloc_sample_parameter); 187 DECLARE_int64(tcmalloc_sample_parameter);
173 DECLARE_double(tcmalloc_release_rate); 188 DECLARE_double(tcmalloc_release_rate);
174 189
175 // For windows, the printf we use to report large allocs is 190 // For windows, the printf we use to report large allocs is
176 // potentially dangerous: it could cause a malloc that would cause an 191 // potentially dangerous: it could cause a malloc that would cause an
177 // infinite loop. So by default we set the threshold to a huge number 192 // infinite loop. So by default we set the threshold to a huge number
178 // on windows, so this bad situation will never trigger. You can 193 // on windows, so this bad situation will never trigger. You can
179 // always set TCMALLOC_LARGE_ALLOC_REPORT_THRESHOLD manually if you 194 // always set TCMALLOC_LARGE_ALLOC_REPORT_THRESHOLD manually if you
180 // want this functionality. 195 // want this functionality.
181 #ifdef _WIN32 196 #ifdef _WIN32
(...skipping 14 matching lines...) Expand all
196 "is very large and therefore you should see no extra " 211 "is very large and therefore you should see no extra "
197 "logging unless the flag is overridden. Set to 0 to " 212 "logging unless the flag is overridden. Set to 0 to "
198 "disable reporting entirely."); 213 "disable reporting entirely.");
199 214
200 215
201 // We already declared these functions in tcmalloc.h, but we have to 216 // We already declared these functions in tcmalloc.h, but we have to
202 // declare them again to give them an ATTRIBUTE_SECTION: we want to 217 // declare them again to give them an ATTRIBUTE_SECTION: we want to
203 // put all callers of MallocHook::Invoke* in this module into 218 // put all callers of MallocHook::Invoke* in this module into
204 // ATTRIBUTE_SECTION(google_malloc) section, so that 219 // ATTRIBUTE_SECTION(google_malloc) section, so that
205 // MallocHook::GetCallerStackTrace can function accurately. 220 // MallocHook::GetCallerStackTrace can function accurately.
206 #ifndef _WIN32 // windows doesn't have attribute_section, so don't bother
207 extern "C" { 221 extern "C" {
208 void* tc_malloc(size_t size) __THROW 222 void* tc_malloc(size_t size) __THROW
209 ATTRIBUTE_SECTION(google_malloc); 223 ATTRIBUTE_SECTION(google_malloc);
210 void tc_free(void* ptr) __THROW 224 void tc_free(void* ptr) __THROW
211 ATTRIBUTE_SECTION(google_malloc); 225 ATTRIBUTE_SECTION(google_malloc);
212 void* tc_realloc(void* ptr, size_t size) __THROW 226 void* tc_realloc(void* ptr, size_t size) __THROW
213 ATTRIBUTE_SECTION(google_malloc); 227 ATTRIBUTE_SECTION(google_malloc);
214 void* tc_calloc(size_t nmemb, size_t size) __THROW 228 void* tc_calloc(size_t nmemb, size_t size) __THROW
215 ATTRIBUTE_SECTION(google_malloc); 229 ATTRIBUTE_SECTION(google_malloc);
216 void tc_cfree(void* ptr) __THROW 230 void tc_cfree(void* ptr) __THROW
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 272
259 // Some non-standard extensions that we support. 273 // Some non-standard extensions that we support.
260 274
261 // This is equivalent to 275 // This is equivalent to
262 // OS X: malloc_size() 276 // OS X: malloc_size()
263 // glibc: malloc_usable_size() 277 // glibc: malloc_usable_size()
264 // Windows: _msize() 278 // Windows: _msize()
265 size_t tc_malloc_size(void* p) __THROW 279 size_t tc_malloc_size(void* p) __THROW
266 ATTRIBUTE_SECTION(google_malloc); 280 ATTRIBUTE_SECTION(google_malloc);
267 } // extern "C" 281 } // extern "C"
268 #endif // #ifndef _WIN32
269 282
270 // Override the libc functions to prefer our own instead. This comes 283 // Override the libc functions to prefer our own instead. This comes
271 // first so code in tcmalloc.cc can use the overridden versions. One 284 // first so code in tcmalloc.cc can use the overridden versions. One
272 // exception: in windows, by default, we patch our code into these 285 // exception: in windows, by default, we patch our code into these
273 // functions (via src/windows/patch_function.cc) rather than override 286 // functions (via src/windows/patch_function.cc) rather than override
274 // them. In that case, we don't want to do this overriding here. 287 // them. In that case, we don't want to do this overriding here.
275 #if !defined(WIN32_DO_PATCHING) 288 #if !defined(WIN32_DO_PATCHING)
276 289
290 // TODO(mbelshe): Turn off TCMalloc's symbols for libc. We do that
291 // elsewhere.
292 #ifndef _WIN32
293
277 #if defined(__GNUC__) && !defined(__MACH__) 294 #if defined(__GNUC__) && !defined(__MACH__)
278 // Potentially faster variants that use the gcc alias extension. 295 // Potentially faster variants that use the gcc alias extension.
279 // FreeBSD does support aliases, but apparently not correctly. :-( 296 // FreeBSD does support aliases, but apparently not correctly. :-(
280 // NOTE: we make many of these symbols weak, but do so in the makefile 297 // NOTE: we make many of these symbols weak, but do so in the makefile
281 // (via objcopy -W) and not here. That ends up being more portable. 298 // (via objcopy -W) and not here. That ends up being more portable.
282 # define ALIAS(x) __attribute__ ((alias (x))) 299 # define ALIAS(x) __attribute__ ((alias (x)))
283 void* operator new(size_t size) throw (std::bad_alloc) ALIAS("tc_new"); 300 void* operator new(size_t size) throw (std::bad_alloc) ALIAS("tc_new");
284 void operator delete(void* p) __THROW ALIAS("tc_delete"); 301 void operator delete(void* p) __THROW ALIAS("tc_delete");
285 void* operator new[](size_t size) throw (std::bad_alloc) ALIAS("tc_newarray"); 302 void* operator new[](size_t size) throw (std::bad_alloc) ALIAS("tc_newarray");
286 void operator delete[](void* p) __THROW ALIAS("tc_deletearray"); 303 void operator delete[](void* p) __THROW ALIAS("tc_deletearray");
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 void* __libc_memalign(size_t align, size_t s) { return memalign(align, s); } 394 void* __libc_memalign(size_t align, size_t s) { return memalign(align, s); }
378 void* __libc_valloc(size_t size) { return valloc(size); } 395 void* __libc_valloc(size_t size) { return valloc(size); }
379 void* __libc_pvalloc(size_t size) { return pvalloc(size); } 396 void* __libc_pvalloc(size_t size) { return pvalloc(size); }
380 int __posix_memalign(void** r, size_t a, size_t s) { 397 int __posix_memalign(void** r, size_t a, size_t s) {
381 return posix_memalign(r, a, s); 398 return posix_memalign(r, a, s);
382 } 399 }
383 #endif // #ifdef ALIAS 400 #endif // #ifdef ALIAS
384 } // extern "C" 401 } // extern "C"
385 #endif // ifdef __GLIBC__ 402 #endif // ifdef __GLIBC__
386 403
404 #if defined(__GLIBC__) && defined(HAVE_MALLOC_H)
405 // If we're using glibc, then override glibc malloc hooks to make sure that even
406 // if calls fall through to ptmalloc (due to dlopen() with RTLD_DEEPBIND or what
407 // not), ptmalloc will use TCMalloc.
408
409 static void* tc_ptmalloc_malloc_hook(size_t size, const void* caller) {
410 return tc_malloc(size);
411 }
412
413 void* (*__MALLOC_HOOK_VOLATILE __malloc_hook)(
414 size_t size, const void* caller) = tc_ptmalloc_malloc_hook;
415
416 static void* tc_ptmalloc_realloc_hook(
417 void* ptr, size_t size, const void* caller) {
418 return tc_realloc(ptr, size);
419 }
420
421 void* (*__MALLOC_HOOK_VOLATILE __realloc_hook)(
422 void* ptr, size_t size, const void* caller) = tc_ptmalloc_realloc_hook;
423
424 static void tc_ptmalloc_free_hook(void* ptr, const void* caller) {
425 tc_free(ptr);
426 }
427
428 void (*__MALLOC_HOOK_VOLATILE __free_hook)(void* ptr, const void* caller) = tc_p tmalloc_free_hook;
429
430 #endif
431
432 #endif // #ifndef _WIN32
387 #undef ALIAS 433 #undef ALIAS
388 434
389 #endif // #ifndef(WIN32_DO_PATCHING) 435 #endif // #ifndef(WIN32_DO_PATCHING)
390 436
391 437
392 // ----------------------- IMPLEMENTATION ------------------------------- 438 // ----------------------- IMPLEMENTATION -------------------------------
393 439
394 static int tc_new_mode = 0; // See tc_set_new_mode(). 440 static int tc_new_mode = 0; // See tc_set_new_mode().
395 441
396 // Routines such as free() and realloc() catch some erroneous pointers 442 // Routines such as free() and realloc() catch some erroneous pointers
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 + stats.metadata_bytes); 505 + stats.metadata_bytes);
460 const uint64_t physical_memory_used = (virtual_memory_used 506 const uint64_t physical_memory_used = (virtual_memory_used
461 - stats.pageheap.unmapped_bytes); 507 - stats.pageheap.unmapped_bytes);
462 const uint64_t bytes_in_use_by_app = (physical_memory_used 508 const uint64_t bytes_in_use_by_app = (physical_memory_used
463 - stats.metadata_bytes 509 - stats.metadata_bytes
464 - stats.pageheap.free_bytes 510 - stats.pageheap.free_bytes
465 - stats.central_bytes 511 - stats.central_bytes
466 - stats.transfer_bytes 512 - stats.transfer_bytes
467 - stats.thread_bytes); 513 - stats.thread_bytes);
468 514
515 out->printf(
516 "WASTE: %7.1f MiB committed but not used\n"
517 "WASTE: %7.1f MiB bytes committed, %7.1f MiB bytes in use\n"
518 "WASTE: committed/used ratio of %f\n",
519 (stats.pageheap.committed_bytes - bytes_in_use_by_app) / MiB,
520 stats.pageheap.committed_bytes / MiB,
521 bytes_in_use_by_app / MiB,
522 stats.pageheap.committed_bytes / static_cast<double>(bytes_in_use_by_app)
523 );
469 #ifdef TCMALLOC_SMALL_BUT_SLOW 524 #ifdef TCMALLOC_SMALL_BUT_SLOW
470 out->printf( 525 out->printf(
471 "NOTE: SMALL MEMORY MODEL IS IN USE, PERFORMANCE MAY SUFFER.\n"); 526 "NOTE: SMALL MEMORY MODEL IS IN USE, PERFORMANCE MAY SUFFER.\n");
472 #endif 527 #endif
473 out->printf( 528 out->printf(
474 "------------------------------------------------\n" 529 "------------------------------------------------\n"
475 "MALLOC: %12" PRIu64 " (%7.1f MiB) Bytes in use by application\n" 530 "MALLOC: %12" PRIu64 " (%7.1f MiB) Bytes in use by application\n"
531 "MALLOC: %12" PRIu64 " (%7.1f MB) Bytes committed\n"
476 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in page heap freelist\n" 532 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in page heap freelist\n"
477 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in central cache freelist\n" 533 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in central cache freelist\n"
478 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in transfer cache freelist\n" 534 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in transfer cache freelist\n"
479 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in thread cache freelists\n" 535 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in thread cache freelists\n"
480 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in malloc metadata\n" 536 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in malloc metadata\n"
481 "MALLOC: ------------\n" 537 "MALLOC: ------------\n"
482 "MALLOC: = %12" PRIu64 " (%7.1f MiB) Actual memory used (physical + swap)\ n" 538 "MALLOC: = %12" PRIu64 " (%7.1f MiB) Actual memory used (physical + swap)\ n"
483 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes released to OS (aka unmapped)\n " 539 "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes released to OS (aka unmapped)\n "
484 "MALLOC: ------------\n" 540 "MALLOC: ------------\n"
485 "MALLOC: = %12" PRIu64 " (%7.1f MiB) Virtual address space used\n" 541 "MALLOC: = %12" PRIu64 " (%7.1f MiB) Virtual address space used\n"
486 "MALLOC:\n" 542 "MALLOC:\n"
487 "MALLOC: %12" PRIu64 " Spans in use\n" 543 "MALLOC: %12" PRIu64 " Spans in use\n"
488 "MALLOC: %12" PRIu64 " Thread heaps in use\n" 544 "MALLOC: %12" PRIu64 " Thread heaps in use\n"
489 "MALLOC: %12" PRIu64 " Tcmalloc page size\n" 545 "MALLOC: %12" PRIu64 " Tcmalloc page size\n"
490 "------------------------------------------------\n" 546 "------------------------------------------------\n"
491 "Call ReleaseFreeMemory() to release freelist memory to the OS" 547 "Call ReleaseFreeMemory() to release freelist memory to the OS"
492 " (via madvise()).\n" 548 " (via madvise()).\n"
493 "Bytes released to the OS take up virtual address space" 549 "Bytes released to the OS take up virtual address space"
494 " but no physical memory.\n", 550 " but no physical memory.\n",
495 bytes_in_use_by_app, bytes_in_use_by_app / MiB, 551 bytes_in_use_by_app, bytes_in_use_by_app / MiB,
552 stats.pageheap.committed_bytes, stats.pageheap.committed_bytes / MiB,
496 stats.pageheap.free_bytes, stats.pageheap.free_bytes / MiB, 553 stats.pageheap.free_bytes, stats.pageheap.free_bytes / MiB,
497 stats.central_bytes, stats.central_bytes / MiB, 554 stats.central_bytes, stats.central_bytes / MiB,
498 stats.transfer_bytes, stats.transfer_bytes / MiB, 555 stats.transfer_bytes, stats.transfer_bytes / MiB,
499 stats.thread_bytes, stats.thread_bytes / MiB, 556 stats.thread_bytes, stats.thread_bytes / MiB,
500 stats.metadata_bytes, stats.metadata_bytes / MiB, 557 stats.metadata_bytes, stats.metadata_bytes / MiB,
501 physical_memory_used, physical_memory_used / MiB, 558 physical_memory_used, physical_memory_used / MiB,
502 stats.pageheap.unmapped_bytes, stats.pageheap.unmapped_bytes / MiB, 559 stats.pageheap.unmapped_bytes, stats.pageheap.unmapped_bytes / MiB,
503 virtual_memory_used, virtual_memory_used / MiB, 560 virtual_memory_used, virtual_memory_used / MiB,
504 uint64_t(Static::span_allocator()->inuse()), 561 uint64_t(Static::span_allocator()->inuse()),
505 uint64_t(ThreadCache::HeapsInUse()), 562 uint64_t(ThreadCache::HeapsInUse()),
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
965 1022
966 static inline bool CheckCachedSizeClass(void *ptr) { 1023 static inline bool CheckCachedSizeClass(void *ptr) {
967 PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; 1024 PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
968 size_t cached_value = Static::pageheap()->GetSizeClassIfCached(p); 1025 size_t cached_value = Static::pageheap()->GetSizeClassIfCached(p);
969 return cached_value == 0 || 1026 return cached_value == 0 ||
970 cached_value == Static::pageheap()->GetDescriptor(p)->sizeclass; 1027 cached_value == Static::pageheap()->GetDescriptor(p)->sizeclass;
971 } 1028 }
972 1029
973 static inline void* CheckedMallocResult(void *result) { 1030 static inline void* CheckedMallocResult(void *result) {
974 ASSERT(result == NULL || CheckCachedSizeClass(result)); 1031 ASSERT(result == NULL || CheckCachedSizeClass(result));
1032 MarkAllocatedRegion(result);
975 return result; 1033 return result;
976 } 1034 }
977 1035
978 static inline void* SpanToMallocResult(Span *span) { 1036 static inline void* SpanToMallocResult(Span *span) {
979 Static::pageheap()->CacheSizeClass(span->start, 0); 1037 Static::pageheap()->CacheSizeClass(span->start, 0);
980 return 1038 return
981 CheckedMallocResult(reinterpret_cast<void*>(span->start << kPageShift)); 1039 CheckedMallocResult(reinterpret_cast<void*>(span->start << kPageShift));
982 } 1040 }
983 1041
984 static void* DoSampledAllocation(size_t size) { 1042 static void* DoSampledAllocation(size_t size) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 for (int i = 0; i < stack.depth; i++) { 1087 for (int i = 0; i < stack.depth; i++) {
1030 printer.printf(" %p", stack.stack[i]); 1088 printer.printf(" %p", stack.stack[i]);
1031 } 1089 }
1032 printer.printf("\n"); 1090 printer.printf("\n");
1033 write(STDERR_FILENO, buffer, strlen(buffer)); 1091 write(STDERR_FILENO, buffer, strlen(buffer));
1034 } 1092 }
1035 1093
1036 inline void* cpp_alloc(size_t size, bool nothrow); 1094 inline void* cpp_alloc(size_t size, bool nothrow);
1037 inline void* do_malloc(size_t size); 1095 inline void* do_malloc(size_t size);
1038 1096
1039 // TODO(willchan): Investigate whether or not lining this much is harmful to 1097 // TODO(willchan): Investigate whether or not inlining this much is harmful to
1040 // performance. 1098 // performance.
1041 // This is equivalent to do_malloc() except when tc_new_mode is set to true. 1099 // This is equivalent to do_malloc() except when tc_new_mode is set to true.
1042 // Otherwise, it will run the std::new_handler if set. 1100 // Otherwise, it will run the std::new_handler if set.
1043 inline void* do_malloc_or_cpp_alloc(size_t size) { 1101 inline void* do_malloc_or_cpp_alloc(size_t size) {
1044 return tc_new_mode ? cpp_alloc(size, true) : do_malloc(size); 1102 return tc_new_mode ? cpp_alloc(size, true) : do_malloc(size);
1045 } 1103 }
1046 1104
1047 void* cpp_memalign(size_t align, size_t size); 1105 void* cpp_memalign(size_t align, size_t size);
1048 void* do_memalign(size_t align, size_t size); 1106 void* do_memalign(size_t align, size_t size);
1049 1107
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 report_large = should_report_large(num_pages); 1142 report_large = should_report_large(num_pages);
1085 } 1143 }
1086 1144
1087 if (report_large) { 1145 if (report_large) {
1088 ReportLargeAlloc(num_pages, result); 1146 ReportLargeAlloc(num_pages, result);
1089 } 1147 }
1090 return result; 1148 return result;
1091 } 1149 }
1092 1150
1093 inline void* do_malloc(size_t size) { 1151 inline void* do_malloc(size_t size) {
1152 AddRoomForMark(&size);
1153
1094 void* ret = NULL; 1154 void* ret = NULL;
1095 1155
1096 // The following call forces module initialization 1156 // The following call forces module initialization
1097 ThreadCache* heap = ThreadCache::GetCache(); 1157 ThreadCache* heap = ThreadCache::GetCache();
1098 if (size <= kMaxSize) { 1158 if (size <= kMaxSize) {
1099 size_t cl = Static::sizemap()->SizeClass(size); 1159 size_t cl = Static::sizemap()->SizeClass(size);
1100 size = Static::sizemap()->class_to_size(cl); 1160 size = Static::sizemap()->class_to_size(cl);
1101 1161
1102 if ((FLAGS_tcmalloc_sample_parameter > 0) && heap->SampleAllocation(size)) { 1162 if ((FLAGS_tcmalloc_sample_parameter > 0) && heap->SampleAllocation(size)) {
1103 ret = DoSampledAllocation(size); 1163 ret = DoSampledAllocation(size);
1164 MarkAllocatedRegion(ret);
1104 } else { 1165 } else {
1105 // The common case, and also the simplest. This just pops the 1166 // The common case, and also the simplest. This just pops the
1106 // size-appropriate freelist, after replenishing it if it's empty. 1167 // size-appropriate freelist, after replenishing it if it's empty.
1107 ret = CheckedMallocResult(heap->Allocate(size, cl)); 1168 ret = CheckedMallocResult(heap->Allocate(size, cl));
1108 } 1169 }
1109 } else { 1170 } else {
1110 ret = do_malloc_pages(heap, size); 1171 ret = do_malloc_pages(heap, size);
1172 MarkAllocatedRegion(ret);
1111 } 1173 }
1112 if (ret == NULL) errno = ENOMEM; 1174 if (ret == NULL) errno = ENOMEM;
1113 return ret; 1175 return ret;
1114 } 1176 }
1115 1177
1116 inline void* do_calloc(size_t n, size_t elem_size) { 1178 inline void* do_calloc(size_t n, size_t elem_size) {
1117 // Overflow check 1179 // Overflow check
1118 const size_t size = n * elem_size; 1180 const size_t size = n * elem_size;
1119 if (elem_size != 0 && size / elem_size != n) return NULL; 1181 if (elem_size != 0 && size / elem_size != n) return NULL;
1120 1182
(...skipping 27 matching lines...) Expand all
1148 // tcmalloc. The latter can happen if tcmalloc is linked in via 1210 // tcmalloc. The latter can happen if tcmalloc is linked in via
1149 // a dynamic library, but is not listed last on the link line. 1211 // a dynamic library, but is not listed last on the link line.
1150 // In that case, libraries after it on the link line will 1212 // In that case, libraries after it on the link line will
1151 // allocate with libc malloc, but free with tcmalloc's free. 1213 // allocate with libc malloc, but free with tcmalloc's free.
1152 (*invalid_free_fn)(ptr); // Decide how to handle the bad free request 1214 (*invalid_free_fn)(ptr); // Decide how to handle the bad free request
1153 return; 1215 return;
1154 } 1216 }
1155 cl = span->sizeclass; 1217 cl = span->sizeclass;
1156 Static::pageheap()->CacheSizeClass(p, cl); 1218 Static::pageheap()->CacheSizeClass(p, cl);
1157 } 1219 }
1220
1221 ValidateAllocatedRegion(ptr, cl);
1222
1158 if (cl != 0) { 1223 if (cl != 0) {
1159 ASSERT(!Static::pageheap()->GetDescriptor(p)->sample); 1224 ASSERT(!Static::pageheap()->GetDescriptor(p)->sample);
1160 ThreadCache* heap = GetCacheIfPresent(); 1225 ThreadCache* heap = GetCacheIfPresent();
1161 if (heap != NULL) { 1226 if (heap != NULL) {
1162 heap->Deallocate(ptr, cl); 1227 heap->Deallocate(ptr, cl);
1163 } else { 1228 } else {
1164 // Delete directly into central cache 1229 // Delete directly into central cache
1165 tcmalloc::SLL_SetNext(ptr, NULL); 1230 tcmalloc::FL_Init(ptr);
1166 Static::central_cache()[cl].InsertRange(ptr, ptr, 1); 1231 Static::central_cache()[cl].InsertRange(ptr, ptr, 1);
1167 } 1232 }
1168 } else { 1233 } else {
1169 SpinLockHolder h(Static::pageheap_lock()); 1234 SpinLockHolder h(Static::pageheap_lock());
1170 ASSERT(reinterpret_cast<uintptr_t>(ptr) % kPageSize == 0); 1235 ASSERT(reinterpret_cast<uintptr_t>(ptr) % kPageSize == 0);
1171 ASSERT(span != NULL && span->start == p); 1236 ASSERT(span != NULL && span->start == p);
1172 if (span->sample) { 1237 if (span->sample) {
1173 StackTrace* st = reinterpret_cast<StackTrace*>(span->objects); 1238 StackTrace* st = reinterpret_cast<StackTrace*>(span->objects);
1174 tcmalloc::DLL_Remove(span); 1239 tcmalloc::DLL_Remove(span);
1175 Static::stacktrace_allocator()->Delete(st); 1240 Static::stacktrace_allocator()->Delete(st);
(...skipping 28 matching lines...) Expand all
1204 } 1269 }
1205 } 1270 }
1206 } 1271 }
1207 1272
1208 // This lets you call back to a given function pointer if ptr is invalid. 1273 // This lets you call back to a given function pointer if ptr is invalid.
1209 // It is used primarily by windows code which wants a specialized callback. 1274 // It is used primarily by windows code which wants a specialized callback.
1210 inline void* do_realloc_with_callback( 1275 inline void* do_realloc_with_callback(
1211 void* old_ptr, size_t new_size, 1276 void* old_ptr, size_t new_size,
1212 void (*invalid_free_fn)(void*), 1277 void (*invalid_free_fn)(void*),
1213 size_t (*invalid_get_size_fn)(void*)) { 1278 size_t (*invalid_get_size_fn)(void*)) {
1279 AddRoomForMark(&new_size);
1214 // Get the size of the old entry 1280 // Get the size of the old entry
1215 const size_t old_size = GetSizeWithCallback(old_ptr, invalid_get_size_fn); 1281 const size_t old_size = GetSizeWithCallback(old_ptr, invalid_get_size_fn);
1216 1282
1217 // Reallocate if the new size is larger than the old size, 1283 // Reallocate if the new size is larger than the old size,
1218 // or if the new size is significantly smaller than the old size. 1284 // or if the new size is significantly smaller than the old size.
1219 // We do hysteresis to avoid resizing ping-pongs: 1285 // We do hysteresis to avoid resizing ping-pongs:
1220 // . If we need to grow, grow to max(new_size, old_size * 1.X) 1286 // . If we need to grow, grow to max(new_size, old_size * 1.X)
1221 // . Don't shrink unless new_size < old_size * 0.Y 1287 // . Don't shrink unless new_size < old_size * 0.Y
1222 // X and Y trade-off time for wasted space. For now we do 1.25 and 0.5. 1288 // X and Y trade-off time for wasted space. For now we do 1.25 and 0.5.
1223 const int lower_bound_to_grow = old_size + old_size / 4; 1289 const int lower_bound_to_grow = old_size + old_size / 4;
1224 const int upper_bound_to_shrink = old_size / 2; 1290 const int upper_bound_to_shrink = old_size / 2;
1225 if ((new_size > old_size) || (new_size < upper_bound_to_shrink)) { 1291 if ((new_size > old_size) || (new_size < upper_bound_to_shrink)) {
1226 // Need to reallocate. 1292 // Need to reallocate.
1227 void* new_ptr = NULL; 1293 void* new_ptr = NULL;
1228 1294
1229 if (new_size > old_size && new_size < lower_bound_to_grow) { 1295 if (new_size > old_size && new_size < lower_bound_to_grow) {
1230 new_ptr = do_malloc_or_cpp_alloc(lower_bound_to_grow); 1296 new_ptr = do_malloc_or_cpp_alloc(lower_bound_to_grow);
1231 } 1297 }
1298 ExcludeMarkFromSize(&new_size); // do_malloc will add space if needed.
1232 if (new_ptr == NULL) { 1299 if (new_ptr == NULL) {
1233 // Either new_size is not a tiny increment, or last do_malloc failed. 1300 // Either new_size is not a tiny increment, or last do_malloc failed.
1234 new_ptr = do_malloc_or_cpp_alloc(new_size); 1301 new_ptr = do_malloc_or_cpp_alloc(new_size);
1235 } 1302 }
1236 if (new_ptr == NULL) { 1303 if (new_ptr == NULL) {
1237 return NULL; 1304 return NULL;
1238 } 1305 }
1239 MallocHook::InvokeNewHook(new_ptr, new_size); 1306 MallocHook::InvokeNewHook(new_ptr, new_size);
1240 memcpy(new_ptr, old_ptr, ((old_size < new_size) ? old_size : new_size)); 1307 memcpy(new_ptr, old_ptr, ((old_size < new_size) ? old_size : new_size));
1241 MallocHook::InvokeDeleteHook(old_ptr); 1308 MallocHook::InvokeDeleteHook(old_ptr);
1242 // We could use a variant of do_free() that leverages the fact 1309 // We could use a variant of do_free() that leverages the fact
1243 // that we already know the sizeclass of old_ptr. The benefit 1310 // that we already know the sizeclass of old_ptr. The benefit
1244 // would be small, so don't bother. 1311 // would be small, so don't bother.
1245 do_free_with_callback(old_ptr, invalid_free_fn); 1312 do_free_with_callback(old_ptr, invalid_free_fn);
1246 return new_ptr; 1313 return new_ptr;
1247 } else { 1314 } else {
1248 // We still need to call hooks to report the updated size: 1315 // We still need to call hooks to report the updated size:
1249 MallocHook::InvokeDeleteHook(old_ptr); 1316 MallocHook::InvokeDeleteHook(old_ptr);
1317 ExcludeMarkFromSize(&new_size);
1250 MallocHook::InvokeNewHook(old_ptr, new_size); 1318 MallocHook::InvokeNewHook(old_ptr, new_size);
1251 return old_ptr; 1319 return old_ptr;
1252 } 1320 }
1253 } 1321 }
1254 1322
1255 inline void* do_realloc(void* old_ptr, size_t new_size) { 1323 inline void* do_realloc(void* old_ptr, size_t new_size) {
1256 return do_realloc_with_callback(old_ptr, new_size, 1324 return do_realloc_with_callback(old_ptr, new_size,
1257 &InvalidFree, &InvalidGetSizeForRealloc); 1325 &InvalidFree, &InvalidGetSizeForRealloc);
1258 } 1326 }
1259 1327
1260 // For use by exported routines below that want specific alignments 1328 // For use by exported routines below that want specific alignments
1261 // 1329 //
1262 // Note: this code can be slow for alignments > 16, and can 1330 // Note: this code can be slow for alignments > 16, and can
1263 // significantly fragment memory. The expectation is that 1331 // significantly fragment memory. The expectation is that
1264 // memalign/posix_memalign/valloc/pvalloc will not be invoked very 1332 // memalign/posix_memalign/valloc/pvalloc will not be invoked very
1265 // often. This requirement simplifies our implementation and allows 1333 // often. This requirement simplifies our implementation and allows
1266 // us to tune for expected allocation patterns. 1334 // us to tune for expected allocation patterns.
1267 void* do_memalign(size_t align, size_t size) { 1335 void* do_memalign(size_t align, size_t size) {
1268 ASSERT((align & (align - 1)) == 0); 1336 ASSERT((align & (align - 1)) == 0);
1269 ASSERT(align > 0); 1337 ASSERT(align > 0);
1338 // Marked in CheckMallocResult(), which is also inside SpanToMallocResult().
1339 AddRoomForMark(&size);
1270 if (size + align < size) return NULL; // Overflow 1340 if (size + align < size) return NULL; // Overflow
1271 1341
1272 // Fall back to malloc if we would already align this memory access properly. 1342 // Fall back to malloc if we would already align this memory access properly.
1273 if (align <= AlignmentForSize(size)) { 1343 if (align <= AlignmentForSize(size)) {
1274 void* p = do_malloc(size); 1344 void* p = do_malloc(size);
1275 ASSERT((reinterpret_cast<uintptr_t>(p) % align) == 0); 1345 ASSERT((reinterpret_cast<uintptr_t>(p) % align) == 0);
1276 return p; 1346 return p;
1277 } 1347 }
1278 1348
1279 if (Static::pageheap() == NULL) ThreadCache::InitModule(); 1349 if (Static::pageheap() == NULL) ThreadCache::InitModule();
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 return p; 1539 return p;
1470 } 1540 }
1471 #endif // PREANSINEW 1541 #endif // PREANSINEW
1472 } 1542 }
1473 } 1543 }
1474 1544
1475 } // end unnamed namespace 1545 } // end unnamed namespace
1476 1546
1477 // As promised, the definition of this function, declared above. 1547 // As promised, the definition of this function, declared above.
1478 size_t TCMallocImplementation::GetAllocatedSize(void* ptr) { 1548 size_t TCMallocImplementation::GetAllocatedSize(void* ptr) {
1479 return GetSizeWithCallback(ptr, &InvalidGetAllocatedSize); 1549 return ExcludeSpaceForMark(
1550 GetSizeWithCallback(ptr, &InvalidGetAllocatedSize));
1480 } 1551 }
1481 1552
1482 void TCMallocImplementation::MarkThreadBusy() { 1553 void TCMallocImplementation::MarkThreadBusy() {
1483 // Allocate to force the creation of a thread cache, but avoid 1554 // Allocate to force the creation of a thread cache, but avoid
1484 // invoking any hooks. 1555 // invoking any hooks.
1485 do_free(do_malloc(0)); 1556 do_free(do_malloc(0));
1486 } 1557 }
1487 1558
1488 //------------------------------------------------------------------- 1559 //-------------------------------------------------------------------
1489 // Exported routines 1560 // Exported routines
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1686 // heap-checker handles this special case explicitly. 1757 // heap-checker handles this special case explicitly.
1687 static void *MemalignOverride(size_t align, size_t size, const void *caller) 1758 static void *MemalignOverride(size_t align, size_t size, const void *caller)
1688 __THROW ATTRIBUTE_SECTION(google_malloc); 1759 __THROW ATTRIBUTE_SECTION(google_malloc);
1689 1760
1690 static void *MemalignOverride(size_t align, size_t size, const void *caller) 1761 static void *MemalignOverride(size_t align, size_t size, const void *caller)
1691 __THROW { 1762 __THROW {
1692 void* result = do_memalign_or_cpp_memalign(align, size); 1763 void* result = do_memalign_or_cpp_memalign(align, size);
1693 MallocHook::InvokeNewHook(result, size); 1764 MallocHook::InvokeNewHook(result, size);
1694 return result; 1765 return result;
1695 } 1766 }
1696 void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride; 1767 void *(*__MALLOC_HOOK_VOLATILE __memalign_hook)(size_t, size_t, const void *) = MemalignOverride;
1768 #endif // TCMALLOC_USING_DEBUGALLOCATION
1697 1769
1698 #endif // TCMALLOC_USING_DEBUGALLOCATION 1770 // ---Double free() debugging implementation -----------------------------------
1771 // We will put a mark at the extreme end of each allocation block. We make
1772 // sure that we always allocate enough "extra memory" that we can fit in the
1773 // mark, and still provide the requested usable region. If ever that mark is
1774 // not as expected, then we know that the user is corrupting memory beyond their
1775 // request size, or that they have called free a second time without having
1776 // the memory allocated (again). This allows us to spot most double free()s,
1777 // but some can "slip by" or confuse our logic if the caller reallocates memory
1778 // (for a second use) before performing an evil double-free of a first
1779 // allocation
1780
1781 // This code can be optimized, but for now, it is written to be most easily
1782 // understood, and flexible (since it is evolving a bit). Potential
1783 // optimizations include using other calculated data, such as class size, or
1784 // allocation size, which is known in the code above, but then is recalculated
1785 // below. Another potential optimization would be careful manual inlining of
1786 // code, but I *think* that the compile will probably do this for me, and I've
1787 // been careful to avoid aliasing issues that might make a compiler back-off.
1788
1789 // Evolution includes experimenting with different marks, to minimize the chance
1790 // that a mark would be misunderstood (missed corruption). The marks are meant
1791 // to be hashed encoding of the location, so that they can't be copied over a
1792 // different region (by accident) without being detected (most of the time).
1793
1794 // Enable the following define to turn on all the TCMalloc checking.
1795 // It will cost about 2% in performance, but it will catch double frees (most of
1796 // the time), and will often catch allocated-buffer overrun errors. This
1797 // validation is only active when TCMalloc is used as the allocator.
1798 #ifndef NDEBUG
1799 #define TCMALLOC_VALIDATION
1800 #endif
1801
1802 #if !defined(TCMALLOC_VALIDATION)
1803
1804 static size_t ExcludeSpaceForMark(size_t size) { return size; }
1805 static void AddRoomForMark(size_t* size) {}
1806 static void ExcludeMarkFromSize(size_t* new_size) {}
1807 static void MarkAllocatedRegion(void* ptr) {}
1808 static void ValidateAllocatedRegion(void* ptr, size_t cl) {}
1809
1810 #else // TCMALLOC_VALIDATION
1811
1812 static void DieFromDoubleFree() {
1813 char* p = NULL;
1814 p++;
1815 *p += 1; // Segv.
1816 }
1817
1818 static size_t DieFromBadFreePointer(void* unused) {
1819 char* p = NULL;
1820 p += 2;
1821 *p += 2; // Segv.
1822 return 0;
1823 }
1824
1825 static void DieFromMemoryCorruption() {
1826 char* p = NULL;
1827 p += 3;
1828 *p += 3; // Segv.
1829 }
1830
1831 // We can either do byte marking, or whole word marking based on the following
1832 // define. char is as small as we can get, and word marking probably provides
1833 // more than enough bits that we won't miss a corruption. Any sized integral
1834 // type can be used, but we just define two examples.
1835
1836 // #define TCMALLOC_SMALL_VALIDATION
1837 #if defined (TCMALLOC_SMALL_VALIDATION)
1838
1839 typedef char MarkType; // char saves memory... int is more complete.
1840 static const MarkType kAllocationMarkMask = static_cast<MarkType>(0x36);
1841
1842 #else
1843
1844 typedef int MarkType; // char saves memory... int is more complete.
1845 static const MarkType kAllocationMarkMask = static_cast<MarkType>(0xE1AB9536);
1846
1847 #endif
1848
1849 // TODO(jar): See if use of reference rather than pointer gets better inlining,
1850 // or if macro is needed. My fear is that taking address map preclude register
1851 // allocation :-(.
1852 inline static void AddRoomForMark(size_t* size) {
1853 *size += sizeof(kAllocationMarkMask);
1854 }
1855
1856 inline static void ExcludeMarkFromSize(size_t* new_size) {
1857 *new_size -= sizeof(kAllocationMarkMask);
1858 }
1859
1860 inline static size_t ExcludeSpaceForMark(size_t size) {
1861 return size - sizeof(kAllocationMarkMask); // Lie about size when asked.
1862 }
1863
1864 inline static MarkType* GetMarkLocation(void* ptr) {
1865 size_t class_size = GetSizeWithCallback(ptr, DieFromBadFreePointer);
1866 ASSERT(class_size % sizeof(kAllocationMarkMask) == 0);
1867 size_t last_index = (class_size / sizeof(kAllocationMarkMask)) - 1;
1868 return static_cast<MarkType*>(ptr) + last_index;
1869 }
1870
1871 // We hash in the mark location plus the pointer so that we effectively mix in
1872 // the size of the block. This means that if a span is used for different sizes
1873 // that the mark will be different. It would be good to hash in the size (which
1874 // we effectively get by using both mark location and pointer), but even better
1875 // would be to also include the class, as it concisely contains the entropy
1876 // found in the size (when we don't have large allocation), and there is less
1877 // risk of losing those bits to truncation. It would probably be good to combine
1878 // the high bits of size (capturing info about large blocks) with the class
1879 // (which is a 6 bit number).
1880 inline static MarkType GetMarkValue(void* ptr, MarkType* mark) {
1881 void* ptr2 = static_cast<void*>(mark);
1882 size_t offset1 = static_cast<char*>(ptr) - static_cast<char*>(NULL);
1883 size_t offset2 = static_cast<char*>(ptr2) - static_cast<char*>(NULL);
1884 static const int kInvariantBits = 2;
1885 ASSERT((offset1 >> kInvariantBits) << kInvariantBits == offset1);
1886 // Note: low bits of both offsets are invariants due to alignment. High bits
1887 // of both offsets are the same (unless we have a large allocation). Avoid
1888 // XORing high bits together, as they will cancel for most small allocations.
1889
1890 MarkType ret = kAllocationMarkMask;
1891 // Using a little shift, we can safely XOR together both offsets.
1892 ret ^= static_cast<MarkType>(offset1 >> kInvariantBits) ^
1893 static_cast<MarkType>(offset2);
1894 if (sizeof(ret) == 1) {
1895 // Try to bring some high level bits into the mix.
1896 ret += static_cast<MarkType>(offset1 >> 8) ^
1897 static_cast<MarkType>(offset1 >> 16) ^
1898 static_cast<MarkType>(offset1 >> 24) ;
1899 }
1900 // Hash in high bits on a 64 bit architecture.
1901 if (sizeof(size_t) == 8 && sizeof(ret) == 4)
1902 ret += offset1 >> 16;
1903 if (ret == 0)
1904 ret = kAllocationMarkMask; // Avoid common pattern of all zeros.
1905 return ret;
1906 }
1907
1908 // TODO(jar): Use the passed in TCmalloc Class Index to calculate mark location
1909 // faster. The current implementation calls general functions, which have to
1910 // recalculate this in order to get the Class Size. This is a slow and wasteful
1911 // recomputation... but it is much more readable this way (for now).
1912 static void ValidateAllocatedRegion(void* ptr, size_t cl) {
1913 if (ptr == NULL) return;
1914 MarkType* mark = GetMarkLocation(ptr);
1915 MarkType allocated_mark = GetMarkValue(ptr, mark);
1916 MarkType current_mark = *mark;
1917
1918 if (current_mark == ~allocated_mark)
1919 DieFromDoubleFree();
1920 if (current_mark != allocated_mark)
1921 DieFromMemoryCorruption();
1922 #ifndef NDEBUG
1923 // In debug mode, copy the mark into all the free'd region.
1924 size_t class_size = static_cast<size_t>(reinterpret_cast<char*>(mark) -
1925 reinterpret_cast<char*>(ptr));
1926 memset(ptr, static_cast<char>(0x36), class_size);
1927 #endif
1928 *mark = ~allocated_mark; // Distinctively not allocated.
1929 }
1930
1931 static void MarkAllocatedRegion(void* ptr) {
1932 if (ptr == NULL) return;
1933 MarkType* mark = GetMarkLocation(ptr);
1934 *mark = GetMarkValue(ptr, mark);
1935 }
1936
1937 #endif // TCMALLOC_VALIDATION
OLDNEW
« no previous file with comments | « third_party/tcmalloc/chromium/src/system-alloc.cc ('k') | third_party/tcmalloc/chromium/src/tests/debugallocation_test.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698