Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2005, 2007, Google Inc. | 1 // Copyright (c) 2005, 2007, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserv ed. | 3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserv ed. |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 #if OS(DARWIN) | 85 #if OS(DARWIN) |
| 86 #include <AvailabilityMacros.h> | 86 #include <AvailabilityMacros.h> |
| 87 #endif | 87 #endif |
| 88 | 88 |
| 89 #include <limits> | 89 #include <limits> |
| 90 #if OS(WINDOWS) | 90 #if OS(WINDOWS) |
| 91 #include <windows.h> | 91 #include <windows.h> |
| 92 #else | 92 #else |
| 93 #include <pthread.h> | 93 #include <pthread.h> |
| 94 #endif | 94 #endif |
| 95 #include <stdlib.h> | |
| 95 #include <string.h> | 96 #include <string.h> |
| 96 | 97 |
| 97 #ifndef NO_TCMALLOC_SAMPLES | 98 #ifndef NO_TCMALLOC_SAMPLES |
| 98 #define NO_TCMALLOC_SAMPLES | 99 #define NO_TCMALLOC_SAMPLES |
| 99 #endif | 100 #endif |
| 100 | 101 |
| 101 #if !USE(SYSTEM_MALLOC) && defined(NDEBUG) | 102 #if !USE(SYSTEM_MALLOC) && defined(NDEBUG) |
| 102 #define FORCE_SYSTEM_MALLOC 0 | 103 #define FORCE_SYSTEM_MALLOC 0 |
| 103 #else | 104 #else |
| 104 #define FORCE_SYSTEM_MALLOC 1 | 105 #define FORCE_SYSTEM_MALLOC 1 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey); | 179 pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey); |
| 179 pthread_setspecific(isForbiddenKey, 0); | 180 pthread_setspecific(isForbiddenKey, 0); |
| 180 } | 181 } |
| 181 #endif // OS(WINDOWS) | 182 #endif // OS(WINDOWS) |
| 182 | 183 |
| 183 } // namespace WTF | 184 } // namespace WTF |
| 184 #endif // NDEBUG | 185 #endif // NDEBUG |
| 185 | 186 |
| 186 namespace WTF { | 187 namespace WTF { |
| 187 | 188 |
| 188 | |
| 189 namespace Internal { | |
| 190 #if !ENABLE(WTF_MALLOC_VALIDATION) | |
| 191 void fastMallocMatchFailed(void*); | |
| 192 #else | |
| 193 COMPILE_ASSERT(((sizeof(ValidationHeader) % sizeof(AllocAlignmentInteger)) == 0) , ValidationHeader_must_produce_correct_alignment); | |
| 194 #endif | |
| 195 | |
| 196 NO_RETURN_DUE_TO_CRASH void fastMallocMatchFailed(void*) | |
| 197 { | |
| 198 CRASH(); | |
| 199 } | |
| 200 | |
| 201 } // namespace Internal | |
| 202 | |
| 203 | |
| 204 void* fastZeroedMalloc(size_t n) | 189 void* fastZeroedMalloc(size_t n) |
| 205 { | 190 { |
| 206 void* result = fastMalloc(n); | 191 void* result = fastMalloc(n); |
| 207 memset(result, 0, n); | 192 memset(result, 0, n); |
| 208 return result; | 193 return result; |
| 209 } | 194 } |
| 210 | 195 |
| 211 char* fastStrDup(const char* src) | 196 char* fastStrDup(const char* src) |
| 212 { | 197 { |
| 213 size_t len = strlen(src) + 1; | 198 size_t len = strlen(src) + 1; |
| 214 char* dup = static_cast<char*>(fastMalloc(len)); | 199 char* dup = static_cast<char*>(fastMalloc(len)); |
| 215 memcpy(dup, src, len); | 200 memcpy(dup, src, len); |
| 216 return dup; | 201 return dup; |
| 217 } | 202 } |
| 218 | 203 |
| 219 TryMallocReturnValue tryFastZeroedMalloc(size_t n) | |
| 220 { | |
| 221 void* result; | |
| 222 if (!tryFastMalloc(n).getValue(result)) | |
| 223 return 0; | |
| 224 memset(result, 0, n); | |
| 225 return result; | |
| 226 } | |
| 227 | |
| 228 } // namespace WTF | 204 } // namespace WTF |
| 229 | 205 |
| 230 #if FORCE_SYSTEM_MALLOC | 206 #if FORCE_SYSTEM_MALLOC |
| 231 | 207 |
| 232 #if OS(DARWIN) | 208 #if OS(DARWIN) |
| 233 #include <malloc/malloc.h> | 209 #include <malloc/malloc.h> |
| 234 #elif OS(WINDOWS) | 210 #elif OS(WINDOWS) |
| 235 #include <malloc.h> | 211 #include <malloc.h> |
| 236 #endif | 212 #endif |
| 237 | 213 |
| 238 namespace WTF { | 214 namespace WTF { |
| 239 | 215 |
| 240 size_t fastMallocGoodSize(size_t bytes) | 216 size_t fastMallocGoodSize(size_t bytes) |
| 241 { | 217 { |
| 242 #if OS(DARWIN) | 218 #if OS(DARWIN) |
| 243 return malloc_good_size(bytes); | 219 return malloc_good_size(bytes); |
| 244 #else | 220 #else |
| 245 return bytes; | 221 return bytes; |
| 246 #endif | 222 #endif |
| 247 } | 223 } |
| 248 | 224 |
| 249 TryMallocReturnValue tryFastMalloc(size_t n) | |
| 250 { | |
| 251 ASSERT(!isForbidden()); | |
| 252 | |
| 253 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 254 if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= n ) // If overflow would occur... | |
| 255 return 0; | |
| 256 | |
| 257 void* result = malloc(n + Internal::ValidationBufferSize); | |
| 258 if (!result) | |
| 259 return 0; | |
| 260 Internal::ValidationHeader* header = static_cast<Internal::ValidationHeader* >(result); | |
| 261 header->m_size = n; | |
| 262 header->m_type = Internal::AllocTypeMalloc; | |
| 263 header->m_prefix = static_cast<unsigned>(Internal::ValidationPrefix); | |
| 264 result = header + 1; | |
| 265 *Internal::fastMallocValidationSuffix(result) = Internal::ValidationSuffix; | |
| 266 fastMallocValidate(result); | |
| 267 return result; | |
| 268 #else | |
| 269 return malloc(n); | |
| 270 #endif | |
| 271 } | |
| 272 | |
| 273 void* fastMalloc(size_t n) | 225 void* fastMalloc(size_t n) |
| 274 { | 226 { |
| 275 ASSERT(!isForbidden()); | 227 ASSERT(!isForbidden()); |
| 276 | 228 |
| 277 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 278 TryMallocReturnValue returnValue = tryFastMalloc(n); | |
| 279 void* result; | |
| 280 if (!returnValue.getValue(result)) | |
| 281 CRASH(); | |
| 282 #else | |
| 283 void* result = malloc(n); | 229 void* result = malloc(n); |
| 284 #endif | |
| 285 | |
| 286 ASSERT(result); // We expect tcmalloc underneath, which would crash instead of getting here. | 230 ASSERT(result); // We expect tcmalloc underneath, which would crash instead of getting here. |
| 287 | 231 |
| 288 return result; | 232 return result; |
| 289 } | 233 } |
| 290 | 234 |
| 291 TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size) | |
| 292 { | |
| 293 ASSERT(!isForbidden()); | |
| 294 | |
| 295 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 296 size_t totalBytes = n_elements * element_size; | |
| 297 if (n_elements > 1 && element_size && (totalBytes / element_size) != n_eleme nts) | |
| 298 return 0; | |
| 299 | |
| 300 TryMallocReturnValue returnValue = tryFastMalloc(totalBytes); | |
| 301 void* result; | |
| 302 if (!returnValue.getValue(result)) | |
| 303 return 0; | |
| 304 memset(result, 0, totalBytes); | |
| 305 fastMallocValidate(result); | |
| 306 return result; | |
| 307 #else | |
| 308 return calloc(n_elements, element_size); | |
| 309 #endif | |
| 310 } | |
| 311 | |
| 312 void* fastCalloc(size_t n_elements, size_t element_size) | 235 void* fastCalloc(size_t n_elements, size_t element_size) |
| 313 { | 236 { |
| 314 ASSERT(!isForbidden()); | 237 ASSERT(!isForbidden()); |
| 315 | 238 |
| 316 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 317 TryMallocReturnValue returnValue = tryFastCalloc(n_elements, element_size); | |
| 318 void* result; | |
| 319 if (!returnValue.getValue(result)) | |
| 320 CRASH(); | |
| 321 #else | |
| 322 void* result = calloc(n_elements, element_size); | 239 void* result = calloc(n_elements, element_size); |
| 323 #endif | |
| 324 | |
| 325 ASSERT(result); // We expect tcmalloc underneath, which would crash instead of getting here. | 240 ASSERT(result); // We expect tcmalloc underneath, which would crash instead of getting here. |
| 326 | 241 |
| 327 return result; | 242 return result; |
| 328 } | 243 } |
| 329 | 244 |
| 330 void fastFree(void* p) | 245 void fastFree(void* p) |
| 331 { | 246 { |
| 332 ASSERT(!isForbidden()); | 247 ASSERT(!isForbidden()); |
| 333 | 248 |
| 334 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 335 if (!p) | |
| 336 return; | |
| 337 | |
| 338 fastMallocMatchValidateFree(p, Internal::AllocTypeMalloc); | |
| 339 Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p) ; | |
| 340 memset(p, 0xCC, header->m_size); | |
| 341 free(header); | |
| 342 #else | |
| 343 free(p); | 249 free(p); |
| 344 #endif | |
| 345 } | |
| 346 | |
| 347 TryMallocReturnValue tryFastRealloc(void* p, size_t n) | |
| 348 { | |
| 349 ASSERT(!isForbidden()); | |
| 350 | |
| 351 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 352 if (p) { | |
| 353 if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= n) // If overflow would occur... | |
| 354 return 0; | |
| 355 fastMallocValidate(p); | |
| 356 Internal::ValidationHeader* result = static_cast<Internal::ValidationHea der*>(realloc(Internal::fastMallocValidationHeader(p), n + Internal::ValidationB ufferSize)); | |
| 357 if (!result) | |
| 358 return 0; | |
| 359 result->m_size = n; | |
| 360 result = result + 1; | |
| 361 *fastMallocValidationSuffix(result) = Internal::ValidationSuffix; | |
| 362 fastMallocValidate(result); | |
| 363 return result; | |
| 364 } else { | |
| 365 return fastMalloc(n); | |
| 366 } | |
| 367 #else | |
| 368 return realloc(p, n); | |
| 369 #endif | |
| 370 } | 250 } |
| 371 | 251 |
| 372 void* fastRealloc(void* p, size_t n) | 252 void* fastRealloc(void* p, size_t n) |
| 373 { | 253 { |
| 374 ASSERT(!isForbidden()); | 254 ASSERT(!isForbidden()); |
| 375 | 255 |
| 376 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 377 TryMallocReturnValue returnValue = tryFastRealloc(p, n); | |
| 378 void* result; | |
| 379 if (!returnValue.getValue(result)) | |
| 380 CRASH(); | |
| 381 #else | |
| 382 void* result = realloc(p, n); | 256 void* result = realloc(p, n); |
| 383 #endif | |
| 384 | |
| 385 ASSERT(result); // We expect tcmalloc underneath, which would crash instead of getting here. | 257 ASSERT(result); // We expect tcmalloc underneath, which would crash instead of getting here. |
| 386 | 258 |
| 387 return result; | 259 return result; |
| 388 } | 260 } |
| 389 | 261 |
| 390 void releaseFastMallocFreeMemory() { } | 262 void releaseFastMallocFreeMemory() { } |
| 391 | 263 |
| 392 FastMallocStatistics fastMallocStatistics() | 264 FastMallocStatistics fastMallocStatistics() |
| 393 { | 265 { |
| 394 FastMallocStatistics statistics = { 0, 0, 0 }; | 266 FastMallocStatistics statistics = { 0, 0, 0 }; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 407 | 279 |
| 408 #include "Compiler.h" | 280 #include "Compiler.h" |
| 409 #include "TCPackedCache.h" | 281 #include "TCPackedCache.h" |
| 410 #include "TCPageMap.h" | 282 #include "TCPageMap.h" |
| 411 #include "TCSpinLock.h" | 283 #include "TCSpinLock.h" |
| 412 #include "TCSystemAlloc.h" | 284 #include "TCSystemAlloc.h" |
| 413 #include <algorithm> | 285 #include <algorithm> |
| 414 #include <pthread.h> | 286 #include <pthread.h> |
| 415 #include <stdarg.h> | 287 #include <stdarg.h> |
| 416 #include <stddef.h> | 288 #include <stddef.h> |
| 417 #include <stdint.h> | |
| 418 #include <stdio.h> | 289 #include <stdio.h> |
| 419 #if HAVE(ERRNO_H) | 290 #if HAVE(ERRNO_H) |
| 420 #include <errno.h> | 291 #include <errno.h> |
| 421 #endif | 292 #endif |
| 422 #if OS(UNIX) | 293 #if OS(UNIX) |
| 423 #include <unistd.h> | 294 #include <unistd.h> |
| 424 #endif | 295 #endif |
| 425 #if OS(WINDOWS) | 296 #if OS(WINDOWS) |
| 426 #ifndef WIN32_LEAN_AND_MEAN | 297 #ifndef WIN32_LEAN_AND_MEAN |
| 427 #define WIN32_LEAN_AND_MEAN | 298 #define WIN32_LEAN_AND_MEAN |
| 428 #endif | 299 #endif |
| 429 #include <windows.h> | 300 #include <windows.h> |
| 430 #endif | 301 #endif |
| 431 | 302 |
| 432 #if OS(DARWIN) | 303 #if OS(DARWIN) |
| 433 #include "MallocZoneSupport.h" | 304 #include "MallocZoneSupport.h" |
| 434 #include "wtf/HashSet.h" | 305 #include "wtf/HashSet.h" |
| 435 #include "wtf/Vector.h" | 306 #include "wtf/Vector.h" |
| 307 #else | |
| 308 #include "wtf/CurrentTime.h" | |
| 436 #endif | 309 #endif |
| 437 | 310 |
| 438 #if HAVE(DISPATCH_H) | 311 #if HAVE(DISPATCH_H) |
| 439 #include <dispatch/dispatch.h> | 312 #include <dispatch/dispatch.h> |
| 440 #endif | 313 #endif |
| 441 | 314 |
| 442 #ifdef __has_include | 315 #ifdef __has_include |
| 443 #if __has_include(<System/pthread_machdep.h>) | 316 #if __has_include(<System/pthread_machdep.h>) |
| 444 | 317 |
| 445 #include <System/pthread_machdep.h> | 318 #include <System/pthread_machdep.h> |
| (...skipping 3037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3483 } | 3356 } |
| 3484 | 3357 |
| 3485 static inline void* SpanToMallocResult(Span *span) { | 3358 static inline void* SpanToMallocResult(Span *span) { |
| 3486 ASSERT_SPAN_COMMITTED(span); | 3359 ASSERT_SPAN_COMMITTED(span); |
| 3487 pageheap->CacheSizeClass(span->start, 0); | 3360 pageheap->CacheSizeClass(span->start, 0); |
| 3488 void* result = reinterpret_cast<void*>(span->start << kPageShift); | 3361 void* result = reinterpret_cast<void*>(span->start << kPageShift); |
| 3489 POISON_ALLOCATION(result, span->length << kPageShift); | 3362 POISON_ALLOCATION(result, span->length << kPageShift); |
| 3490 return CheckedMallocResult(result); | 3363 return CheckedMallocResult(result); |
| 3491 } | 3364 } |
| 3492 | 3365 |
| 3493 template <bool crashOnFailure> | |
| 3494 static ALWAYS_INLINE void* do_malloc(size_t size) { | 3366 static ALWAYS_INLINE void* do_malloc(size_t size) { |
| 3495 void* ret = NULL; | 3367 void* ret = 0; |
| 3496 | 3368 |
| 3497 ASSERT(!isForbidden()); | 3369 ASSERT(!isForbidden()); |
| 3498 | 3370 |
| 3499 // The following call forces module initialization | 3371 // The following call forces module initialization |
| 3500 TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCache(); | 3372 TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCache(); |
| 3501 if (size > kMaxSize) { | 3373 if (size > kMaxSize) { |
| 3502 // Use page-level allocator | 3374 // Use page-level allocator |
| 3503 SpinLockHolder h(&pageheap_lock); | 3375 SpinLockHolder h(&pageheap_lock); |
| 3504 Span* span = pageheap->New(pages(size)); | 3376 Span* span = pageheap->New(pages(size)); |
| 3505 if (span != NULL) { | 3377 if (span) |
| 3506 ret = SpanToMallocResult(span); | 3378 ret = SpanToMallocResult(span); |
| 3379 } else { | |
| 3380 // The common case, and also the simplest. This just pops the | |
| 3381 // size-appropriate freelist, afer replenishing it if it's empty. | |
| 3382 ret = CheckedMallocResult(heap->Allocate(size)); | |
| 3507 } | 3383 } |
| 3508 } else { | 3384 if (!ret) |
| 3509 // The common case, and also the simplest. This just pops the | 3385 IMMEDIATE_CRASH(); |
|
abarth-chromium
2013/08/04 19:21:31
How is IMMEDIATE_CRASH different from CRASH?
Chris Evans
2013/08/04 20:31:27
It gets the job done with the minimum number of op
| |
| 3510 // size-appropriate freelist, afer replenishing it if it's empty. | 3386 return ret; |
| 3511 ret = CheckedMallocResult(heap->Allocate(size)); | |
| 3512 } | |
| 3513 if (!ret) { | |
| 3514 if (crashOnFailure) // This branch should be optimized out by the compiler. | |
| 3515 CRASH(); | |
| 3516 } | |
| 3517 return ret; | |
| 3518 } | 3387 } |
| 3519 | 3388 |
| 3520 static ALWAYS_INLINE void do_free(void* ptr) { | 3389 static ALWAYS_INLINE void do_free(void* ptr) { |
| 3521 if (ptr == NULL) return; | 3390 if (ptr == NULL) return; |
| 3522 ASSERT(pageheap != NULL); // Should not call free() before malloc() | 3391 ASSERT(pageheap != NULL); // Should not call free() before malloc() |
| 3523 const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; | 3392 const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; |
| 3524 Span* span = NULL; | 3393 Span* span = NULL; |
| 3525 size_t cl = pageheap->GetSizeClassIfCached(p); | 3394 size_t cl = pageheap->GetSizeClassIfCached(p); |
| 3526 | 3395 |
| 3527 if (cl == 0) { | 3396 if (cl == 0) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3594 | 3463 |
| 3595 //------------------------------------------------------------------- | 3464 //------------------------------------------------------------------- |
| 3596 // Exported routines | 3465 // Exported routines |
| 3597 //------------------------------------------------------------------- | 3466 //------------------------------------------------------------------- |
| 3598 | 3467 |
| 3599 // CAVEAT: The code structure below ensures that MallocHook methods are always | 3468 // CAVEAT: The code structure below ensures that MallocHook methods are always |
| 3600 // called from the stack frame of the invoked allocation function. | 3469 // called from the stack frame of the invoked allocation function. |
| 3601 // heap-checker.cc depends on this to start a stack trace from | 3470 // heap-checker.cc depends on this to start a stack trace from |
| 3602 // the call to the (de)allocation function. | 3471 // the call to the (de)allocation function. |
| 3603 | 3472 |
| 3604 #define do_malloc do_malloc<crashOnFailure> | |
| 3605 | |
| 3606 template <bool crashOnFailure> | |
| 3607 ALWAYS_INLINE void* malloc(size_t); | |
| 3608 | |
| 3609 void* fastMalloc(size_t size) | 3473 void* fastMalloc(size_t size) |
| 3610 { | 3474 { |
| 3611 return malloc<true>(size); | 3475 return do_malloc(size); |
| 3612 } | 3476 } |
| 3613 | 3477 |
| 3614 TryMallocReturnValue tryFastMalloc(size_t size) | 3478 void fastFree(void* ptr) |
| 3615 { | 3479 { |
| 3616 return malloc<false>(size); | 3480 do_free(ptr); |
| 3617 } | 3481 } |
| 3618 | 3482 |
| 3619 template <bool crashOnFailure> | |
| 3620 ALWAYS_INLINE | |
| 3621 void* malloc(size_t size) { | |
| 3622 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3623 if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= s ize) // If overflow would occur... | |
| 3624 return 0; | |
| 3625 void* result = do_malloc(size + Internal::ValidationBufferSize); | |
| 3626 if (!result) | |
| 3627 return 0; | |
| 3628 | |
| 3629 Internal::ValidationHeader* header = static_cast<Internal::ValidationHeader* >(result); | |
| 3630 header->m_size = size; | |
| 3631 header->m_type = Internal::AllocTypeMalloc; | |
| 3632 header->m_prefix = static_cast<unsigned>(Internal::ValidationPrefix); | |
| 3633 result = header + 1; | |
| 3634 *Internal::fastMallocValidationSuffix(result) = Internal::ValidationSuffix; | |
| 3635 fastMallocValidate(result); | |
| 3636 #else | |
| 3637 void* result = do_malloc(size); | |
| 3638 #endif | |
| 3639 | |
| 3640 return result; | |
| 3641 } | |
| 3642 | |
| 3643 void free(void* ptr) { | |
| 3644 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3645 if (!ptr) | |
| 3646 return; | |
| 3647 | |
| 3648 fastMallocValidate(ptr); | |
| 3649 Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(pt r); | |
| 3650 memset(ptr, 0xCC, header->m_size); | |
| 3651 do_free(header); | |
| 3652 #else | |
| 3653 do_free(ptr); | |
| 3654 #endif | |
| 3655 } | |
| 3656 | |
| 3657 template <bool crashOnFailure> | |
| 3658 ALWAYS_INLINE void* calloc(size_t, size_t); | |
| 3659 | |
| 3660 void* fastCalloc(size_t n, size_t elem_size) | 3483 void* fastCalloc(size_t n, size_t elem_size) |
| 3661 { | 3484 { |
| 3662 void* result = calloc<true>(n, elem_size); | |
| 3663 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3664 fastMallocValidate(result); | |
| 3665 #endif | |
| 3666 return result; | |
| 3667 } | |
| 3668 | |
| 3669 TryMallocReturnValue tryFastCalloc(size_t n, size_t elem_size) | |
| 3670 { | |
| 3671 void* result = calloc<false>(n, elem_size); | |
| 3672 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3673 fastMallocValidate(result); | |
| 3674 #endif | |
| 3675 return result; | |
| 3676 } | |
| 3677 | |
| 3678 template <bool crashOnFailure> | |
| 3679 ALWAYS_INLINE | |
| 3680 void* calloc(size_t n, size_t elem_size) { | |
| 3681 size_t totalBytes = n * elem_size; | 3485 size_t totalBytes = n * elem_size; |
| 3682 | 3486 |
| 3683 // Protect against overflow | 3487 // Protect against overflow |
| 3684 if (n > 1 && elem_size && (totalBytes / elem_size) != n) | 3488 if (n > 1 && elem_size && (totalBytes / elem_size) != n) |
| 3685 return 0; | 3489 return 0; |
| 3686 | 3490 |
| 3687 #if ENABLE(WTF_MALLOC_VALIDATION) | 3491 void* result = do_malloc(totalBytes); |
| 3688 void* result = malloc<crashOnFailure>(totalBytes); | |
| 3689 if (!result) | |
| 3690 return 0; | |
| 3691 | |
| 3692 memset(result, 0, totalBytes); | 3492 memset(result, 0, totalBytes); |
| 3693 fastMallocValidate(result); | |
| 3694 #else | |
| 3695 void* result = do_malloc(totalBytes); | |
| 3696 if (result != NULL) { | |
| 3697 memset(result, 0, totalBytes); | |
| 3698 } | |
| 3699 #endif | |
| 3700 | 3493 |
| 3701 return result; | 3494 return result; |
| 3702 } | 3495 } |
| 3703 | 3496 |
| 3704 // Since cfree isn't used anywhere, we don't compile it in. | |
| 3705 template <bool crashOnFailure> | |
| 3706 ALWAYS_INLINE void* realloc(void*, size_t); | |
| 3707 | |
| 3708 void* fastRealloc(void* old_ptr, size_t new_size) | 3497 void* fastRealloc(void* old_ptr, size_t new_size) |
| 3709 { | 3498 { |
| 3710 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3711 fastMallocValidate(old_ptr); | |
| 3712 #endif | |
| 3713 void* result = realloc<true>(old_ptr, new_size); | |
| 3714 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3715 fastMallocValidate(result); | |
| 3716 #endif | |
| 3717 return result; | |
| 3718 } | |
| 3719 | |
| 3720 TryMallocReturnValue tryFastRealloc(void* old_ptr, size_t new_size) | |
| 3721 { | |
| 3722 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3723 fastMallocValidate(old_ptr); | |
| 3724 #endif | |
| 3725 void* result = realloc<false>(old_ptr, new_size); | |
| 3726 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3727 fastMallocValidate(result); | |
| 3728 #endif | |
| 3729 return result; | |
| 3730 } | |
| 3731 | |
| 3732 template <bool crashOnFailure> | |
| 3733 ALWAYS_INLINE | |
| 3734 void* realloc(void* old_ptr, size_t new_size) { | |
| 3735 if (old_ptr == NULL) { | 3499 if (old_ptr == NULL) { |
| 3736 #if ENABLE(WTF_MALLOC_VALIDATION) | 3500 return do_malloc(new_size); |
| 3737 void* result = malloc<crashOnFailure>(new_size); | |
| 3738 #else | |
| 3739 void* result = do_malloc(new_size); | |
| 3740 #endif | |
| 3741 return result; | |
| 3742 } | 3501 } |
| 3743 if (new_size == 0) { | 3502 if (new_size == 0) { |
| 3744 free(old_ptr); | 3503 free(old_ptr); |
| 3745 return NULL; | 3504 return NULL; |
| 3746 } | 3505 } |
| 3747 | 3506 |
| 3748 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3749 if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= n ew_size) // If overflow would occur... | |
| 3750 return 0; | |
| 3751 Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(ol d_ptr); | |
| 3752 fastMallocValidate(old_ptr); | |
| 3753 old_ptr = header; | |
| 3754 header->m_size = new_size; | |
| 3755 new_size += Internal::ValidationBufferSize; | |
| 3756 #endif | |
| 3757 | |
| 3758 // Get the size of the old entry | 3507 // Get the size of the old entry |
| 3759 const PageID p = reinterpret_cast<uintptr_t>(old_ptr) >> kPageShift; | 3508 const PageID p = reinterpret_cast<uintptr_t>(old_ptr) >> kPageShift; |
| 3760 size_t cl = pageheap->GetSizeClassIfCached(p); | 3509 size_t cl = pageheap->GetSizeClassIfCached(p); |
| 3761 Span *span = NULL; | 3510 Span *span = NULL; |
| 3762 size_t old_size; | 3511 size_t old_size; |
| 3763 if (cl == 0) { | 3512 if (cl == 0) { |
| 3764 span = pageheap->GetDescriptor(p); | 3513 span = pageheap->GetDescriptor(p); |
| 3765 cl = span->sizeclass; | 3514 cl = span->sizeclass; |
| 3766 pageheap->CacheSizeClass(p, cl); | 3515 pageheap->CacheSizeClass(p, cl); |
| 3767 } | 3516 } |
| 3768 if (cl != 0) { | 3517 if (cl != 0) { |
| 3769 old_size = ByteSizeForClass(cl); | 3518 old_size = ByteSizeForClass(cl); |
| 3770 } else { | 3519 } else { |
| 3771 ASSERT(span != NULL); | 3520 ASSERT(span != NULL); |
| 3772 old_size = span->length << kPageShift; | 3521 old_size = span->length << kPageShift; |
| 3773 } | 3522 } |
| 3774 | 3523 |
| 3775 // Reallocate if the new size is larger than the old size, | 3524 // Reallocate if the new size is larger than the old size, |
| 3776 // or if the new size is significantly smaller than the old size. | 3525 // or if the new size is significantly smaller than the old size. |
| 3777 if ((new_size > old_size) || (AllocationSize(new_size) < old_size)) { | 3526 if ((new_size > old_size) || (AllocationSize(new_size) < old_size)) { |
| 3778 // Need to reallocate | 3527 // Need to reallocate |
| 3779 void* new_ptr = do_malloc(new_size); | 3528 void* new_ptr = do_malloc(new_size); |
| 3780 if (new_ptr == NULL) { | |
| 3781 return NULL; | |
| 3782 } | |
| 3783 memcpy(new_ptr, old_ptr, ((old_size < new_size) ? old_size : new_size)); | 3529 memcpy(new_ptr, old_ptr, ((old_size < new_size) ? old_size : new_size)); |
| 3784 // We could use a variant of do_free() that leverages the fact | 3530 // We could use a variant of do_free() that leverages the fact |
| 3785 // that we already know the sizeclass of old_ptr. The benefit | 3531 // that we already know the sizeclass of old_ptr. The benefit |
| 3786 // would be small, so don't bother. | 3532 // would be small, so don't bother. |
| 3787 do_free(old_ptr); | 3533 do_free(old_ptr); |
| 3788 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3789 new_ptr = static_cast<Internal::ValidationHeader*>(new_ptr) + 1; | |
| 3790 *Internal::fastMallocValidationSuffix(new_ptr) = Internal::ValidationSuffix; | |
| 3791 #endif | |
| 3792 return new_ptr; | 3534 return new_ptr; |
| 3793 } else { | 3535 } else { |
| 3794 #if ENABLE(WTF_MALLOC_VALIDATION) | |
| 3795 old_ptr = static_cast<Internal::ValidationHeader*>(old_ptr) + 1; // Set old_ ptr back to the user pointer. | |
| 3796 *Internal::fastMallocValidationSuffix(old_ptr) = Internal::ValidationSuffix; | |
| 3797 #endif | |
| 3798 return old_ptr; | 3536 return old_ptr; |
| 3799 } | 3537 } |
| 3800 } | 3538 } |
| 3801 | 3539 |
| 3802 #undef do_malloc | |
| 3803 | |
| 3804 void releaseFastMallocFreeMemory() | 3540 void releaseFastMallocFreeMemory() |
| 3805 { | 3541 { |
| 3806 // Flush free pages in the current thread cache back to the page heap. | 3542 // Flush free pages in the current thread cache back to the page heap. |
| 3807 if (TCMalloc_ThreadCache* threadCache = TCMalloc_ThreadCache::GetCacheIfPres ent()) | 3543 if (TCMalloc_ThreadCache* threadCache = TCMalloc_ThreadCache::GetCacheIfPres ent()) |
| 3808 threadCache->Cleanup(); | 3544 threadCache->Cleanup(); |
| 3809 | 3545 |
| 3810 SpinLockHolder h(&pageheap_lock); | 3546 SpinLockHolder h(&pageheap_lock); |
| 3811 pageheap->ReleaseFreePages(); | 3547 pageheap->ReleaseFreePages(); |
| 3812 } | 3548 } |
| 3813 | 3549 |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4160 void FastMallocZone::init() | 3896 void FastMallocZone::init() |
| 4161 { | 3897 { |
| 4162 static FastMallocZone zone(pageheap, &thread_heaps, static_cast<TCMalloc_Cen tral_FreeListPadded*>(central_cache), &span_allocator, &threadheap_allocator); | 3898 static FastMallocZone zone(pageheap, &thread_heaps, static_cast<TCMalloc_Cen tral_FreeListPadded*>(central_cache), &span_allocator, &threadheap_allocator); |
| 4163 } | 3899 } |
| 4164 | 3900 |
| 4165 #endif // OS(DARWIN) | 3901 #endif // OS(DARWIN) |
| 4166 | 3902 |
| 4167 } // namespace WTF | 3903 } // namespace WTF |
| 4168 | 3904 |
| 4169 #endif // FORCE_SYSTEM_MALLOC | 3905 #endif // FORCE_SYSTEM_MALLOC |
| OLD | NEW |