Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 29 matching lines...) Expand all Loading... | |
| 40 #include <inttypes.h> | 40 #include <inttypes.h> |
| 41 #else | 41 #else |
| 42 #include <sys/types.h> | 42 #include <sys/types.h> |
| 43 #endif | 43 #endif |
| 44 #ifdef HAVE_MMAP | 44 #ifdef HAVE_MMAP |
| 45 #include <sys/mman.h> // for munmap, mmap, MADV_DONTNEED, etc | 45 #include <sys/mman.h> // for munmap, mmap, MADV_DONTNEED, etc |
| 46 #endif | 46 #endif |
| 47 #ifdef HAVE_UNISTD_H | 47 #ifdef HAVE_UNISTD_H |
| 48 #include <unistd.h> // for sbrk, getpagesize, off_t | 48 #include <unistd.h> // for sbrk, getpagesize, off_t |
| 49 #endif | 49 #endif |
| 50 #include <limits> | |
| 50 #include <new> // for operator new | 51 #include <new> // for operator new |
| 51 #include <gperftools/malloc_extension.h> | 52 #include <gperftools/malloc_extension.h> |
| 52 #include "base/basictypes.h" | 53 #include "base/basictypes.h" |
| 53 #include "base/commandlineflags.h" | 54 #include "base/commandlineflags.h" |
| 54 #include "base/spinlock.h" // for SpinLockHolder, SpinLock, etc | 55 #include "base/spinlock.h" // for SpinLockHolder, SpinLock, etc |
| 55 #include "common.h" | 56 #include "common.h" |
| 56 #include "internal_logging.h" | 57 #include "internal_logging.h" |
| 57 | 58 |
| 58 // On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old | 59 // On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old |
| 59 // form of the name instead. | 60 // form of the name instead. |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 // Check if we should use sbrk allocation. | 202 // Check if we should use sbrk allocation. |
| 202 // FLAGS_malloc_skip_sbrk starts out as false (its uninitialized | 203 // FLAGS_malloc_skip_sbrk starts out as false (its uninitialized |
| 203 // state) and eventually gets initialized to the specified value. Note | 204 // state) and eventually gets initialized to the specified value. Note |
| 204 // that this code runs for a while before the flags are initialized. | 205 // that this code runs for a while before the flags are initialized. |
| 205 // That means that even if this flag is set to true, some (initial) | 206 // That means that even if this flag is set to true, some (initial) |
| 206 // memory will be allocated with sbrk before the flag takes effect. | 207 // memory will be allocated with sbrk before the flag takes effect. |
| 207 if (FLAGS_malloc_skip_sbrk) { | 208 if (FLAGS_malloc_skip_sbrk) { |
| 208 return NULL; | 209 return NULL; |
| 209 } | 210 } |
| 210 | 211 |
| 212 // The first time we call into the allocator, record the current pointer | |
| 213 // to the break. This will be used to calculate the total size. | |
| 214 static const char* initial_brk_address = static_cast<char*>(sbrk(0)); | |
| 215 | |
| 211 // sbrk will release memory if passed a negative number, so we do | 216 // sbrk will release memory if passed a negative number, so we do |
| 212 // a strict check here | 217 // a strict check here |
| 213 if (static_cast<ptrdiff_t>(size + alignment) < 0) return NULL; | 218 if (static_cast<ptrdiff_t>(size + alignment) < 0) return NULL; |
| 214 | 219 |
| 215 // This doesn't overflow because TCMalloc_SystemAlloc has already | 220 // This doesn't overflow because TCMalloc_SystemAlloc has already |
| 216 // tested for overflow at the alignment boundary. | 221 // tested for overflow at the alignment boundary. |
| 217 size = ((size + alignment - 1) / alignment) * alignment; | 222 size = ((size + alignment - 1) / alignment) * alignment; |
| 218 | 223 |
| 219 // "actual_size" indicates that the bytes from the returned pointer | 224 // "actual_size" indicates that the bytes from the returned pointer |
| 220 // p up to and including (p + actual_size - 1) have been allocated. | 225 // p up to and including (p + actual_size - 1) have been allocated. |
| 221 if (actual_size) { | 226 if (actual_size) { |
| 222 *actual_size = size; | 227 *actual_size = size; |
| 223 } | 228 } |
| 224 | 229 |
| 225 // Check that we we're not asking for so much more memory that we'd | 230 // Check that we we're not asking for so much more memory that we'd |
| 226 // wrap around the end of the virtual address space. (This seems | 231 // wrap around the end of the virtual address space. (This seems |
| 227 // like something sbrk() should check for us, and indeed opensolaris | 232 // like something sbrk() should check for us, and indeed opensolaris |
| 228 // does, but glibc does not: | 233 // does, but glibc does not: |
| 229 // http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/p ort/sys/sbrk.c?a=true | 234 // http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/p ort/sys/sbrk.c?a=true |
| 230 // http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/libc/misc/sbrk.c?rev =1.1.2.1&content-type=text/plain&cvsroot=glibc | 235 // http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/libc/misc/sbrk.c?rev =1.1.2.1&content-type=text/plain&cvsroot=glibc |
| 231 // Without this check, sbrk may succeed when it ought to fail.) | 236 // Without this check, sbrk may succeed when it ought to fail.) |
| 232 if (reinterpret_cast<intptr_t>(sbrk(0)) + size < size) { | 237 const char* current_brk_address = static_cast<char*>(sbrk(0)); |
| 238 if (reinterpret_cast<intptr_t>(current_brk_address) + size < size) { | |
| 233 return NULL; | 239 return NULL; |
| 234 } | 240 } |
| 235 | 241 |
| 242 ASSERT(current_brk_address >= initial_brk_address); | |
| 243 const size_t current_alloc_size = | |
| 244 static_cast<size_t>(current_brk_address - initial_brk_address); | |
| 245 ASSERT(current_alloc_size <= | |
| 246 std::numeric_limits<std::size_t>::max() - size); | |
| 247 | |
| 248 if (!tcmalloc::IsContiguousAllocSizePermitted(current_alloc_size + size)) | |
| 249 return NULL; | |
| 250 | |
| 236 void* result = sbrk(size); | 251 void* result = sbrk(size); |
| 237 if (result == reinterpret_cast<void*>(-1)) { | 252 if (result == reinterpret_cast<void*>(-1)) { |
| 238 return NULL; | 253 return NULL; |
| 239 } | 254 } |
| 240 | 255 |
| 241 // Is it aligned? | 256 // Is it aligned? |
| 242 uintptr_t ptr = reinterpret_cast<uintptr_t>(result); | 257 uintptr_t ptr = reinterpret_cast<uintptr_t>(result); |
| 243 if ((ptr & (alignment-1)) == 0) return result; | 258 if ((ptr & (alignment-1)) == 0) return result; |
| 244 | 259 |
| 245 // Try to get more memory for alignment | 260 // Try to get more memory for alignment |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 470 | 485 |
| 471 SpinLockHolder lock_holder(&spinlock); | 486 SpinLockHolder lock_holder(&spinlock); |
| 472 | 487 |
| 473 if (!system_alloc_inited) { | 488 if (!system_alloc_inited) { |
| 474 InitSystemAllocators(); | 489 InitSystemAllocators(); |
| 475 system_alloc_inited = true; | 490 system_alloc_inited = true; |
| 476 } | 491 } |
| 477 | 492 |
| 478 // Enforce minimum alignment | 493 // Enforce minimum alignment |
| 479 if (alignment < sizeof(MemoryAligner)) alignment = sizeof(MemoryAligner); | 494 if (alignment < sizeof(MemoryAligner)) alignment = sizeof(MemoryAligner); |
| 480 | 495 |
|
jln (very slow on Chromium)
2013/01/11 06:02:29
We could also add the limit check here, instead of
| |
| 481 void* result = sys_alloc->Alloc(size, actual_size, alignment); | 496 void* result = sys_alloc->Alloc(size, actual_size, alignment); |
| 482 if (result != NULL) { | 497 if (result != NULL) { |
| 483 if (actual_size) { | 498 if (actual_size) { |
| 484 CheckAddressBits<kAddressBits>( | 499 CheckAddressBits<kAddressBits>( |
| 485 reinterpret_cast<uintptr_t>(result) + *actual_size - 1); | 500 reinterpret_cast<uintptr_t>(result) + *actual_size - 1); |
| 486 } else { | 501 } else { |
| 487 CheckAddressBits<kAddressBits>( | 502 CheckAddressBits<kAddressBits>( |
| 488 reinterpret_cast<uintptr_t>(result) + size - 1); | 503 reinterpret_cast<uintptr_t>(result) + size - 1); |
| 489 } | 504 } |
| 490 } | 505 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 540 } | 555 } |
| 541 } | 556 } |
| 542 #endif | 557 #endif |
| 543 } | 558 } |
| 544 | 559 |
| 545 void TCMalloc_SystemCommit(void* start, size_t length) { | 560 void TCMalloc_SystemCommit(void* start, size_t length) { |
| 546 // Nothing to do here. TCMalloc_SystemRelease does not alter pages | 561 // Nothing to do here. TCMalloc_SystemRelease does not alter pages |
| 547 // such that they need to be re-committed before they can be used by the | 562 // such that they need to be re-committed before they can be used by the |
| 548 // application. | 563 // application. |
| 549 } | 564 } |
| OLD | NEW |