| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <stdio.h> | |
| 6 #include <stdlib.h> | 5 #include <stdlib.h> |
| 7 #include <new> | |
| 8 | 6 |
| 9 #include "base/process/memory.h" | 7 #include "base/process/memory.h" |
| 10 | 8 |
| 11 #include "third_party/skia/include/core/SkTypes.h" | 9 #include "third_party/skia/include/core/SkTypes.h" |
| 12 #include "third_party/skia/include/core/SkThread.h" | |
| 13 | 10 |
| 14 // This implementation of sk_malloc_flags() and friends is identical to | 11 // This implementation of sk_malloc_flags() and friends is similar to |
| 15 // SkMemory_malloc.cpp, except that it disables the CRT's new_handler during | 12 // SkMemory_malloc.cpp, except it uses base::UncheckedMalloc and friends |
| 16 // malloc() and calloc() when SK_MALLOC_THROW is not set (because our normal | 13 // for non-SK_MALLOC_THROW calls. |
| 17 // new_handler itself will crash on failure when using tcmalloc). | 14 // |
| 18 | 15 // The name of this file is historic: a previous implementation tried to |
| 19 SK_DECLARE_STATIC_MUTEX(gSkNewHandlerMutex); | 16 // use std::set_new_handler() for the same effect, but it didn't actually work. |
| 20 | 17 |
| 21 static inline void* throw_on_failure(size_t size, void* p) { | 18 static inline void* throw_on_failure(size_t size, void* p) { |
| 22 if (size > 0 && p == NULL) { | 19 if (size > 0 && p == NULL) { |
| 23 // If we've got a NULL here, the only reason we should have failed is ru
nning out of RAM. | 20 // If we've got a NULL here, the only reason we should have failed is ru
nning out of RAM. |
| 24 sk_out_of_memory(); | 21 sk_out_of_memory(); |
| 25 } | 22 } |
| 26 return p; | 23 return p; |
| 27 } | 24 } |
| 28 | 25 |
| 29 void sk_throw() { | 26 void sk_throw() { |
| 30 SkASSERT(!"sk_throw"); | 27 SkASSERT(!"sk_throw"); |
| 31 abort(); | 28 abort(); |
| 32 } | 29 } |
| 33 | 30 |
| 34 void sk_out_of_memory(void) { | 31 void sk_out_of_memory(void) { |
| 35 SkASSERT(!"sk_out_of_memory"); | 32 SkASSERT(!"sk_out_of_memory"); |
| 36 abort(); | 33 abort(); |
| 37 } | 34 } |
| 38 | 35 |
| 39 void* sk_realloc_throw(void* addr, size_t size) { | 36 void* sk_realloc_throw(void* addr, size_t size) { |
| 40 return throw_on_failure(size, realloc(addr, size)); | 37 return throw_on_failure(size, realloc(addr, size)); |
| 41 } | 38 } |
| 42 | 39 |
| 43 void sk_free(void* p) { | 40 void sk_free(void* p) { |
| 44 if (p) { | 41 if (p) { |
| 45 free(p); | 42 free(p); |
| 46 } | 43 } |
| 47 } | 44 } |
| 48 | 45 |
| 46 // We get lots of bugs filed on us that amount to overcommiting bitmap memory, |
| 47 // then some time later failing to back that VM with physical memory. |
| 48 // They're hard to track down, so in Debug mode we touch all memory right up fro
nt. |
| 49 // |
| 50 // For malloc, fill is an arbitrary byte and ideally not 0. For calloc, it's go
t to be 0. |
| 51 static void* prevent_overcommit(int fill, size_t size, void* p) { |
| 52 // We probably only need to touch one byte per page, but memset makes things
easy. |
| 53 SkDEBUGCODE(memset(p, fill, size)); |
| 54 return p; |
| 55 } |
| 56 |
| 49 void* sk_malloc_throw(size_t size) { | 57 void* sk_malloc_throw(size_t size) { |
| 50 return throw_on_failure(size, malloc(size)); | 58 return prevent_overcommit(0x42, size, throw_on_failure(size, malloc(size))); |
| 51 } | 59 } |
| 52 | 60 |
| 53 static void* sk_malloc_nothrow(size_t size) { | 61 static void* sk_malloc_nothrow(size_t size) { |
| 54 // TODO(b.kelemen): we should always use UncheckedMalloc but currently it | 62 // TODO(b.kelemen): we should always use UncheckedMalloc but currently it |
| 55 // doesn't work as intended everywhere. | 63 // doesn't work as intended everywhere. |
| 64 void* result; |
| 56 #if defined(OS_IOS) | 65 #if defined(OS_IOS) |
| 57 return malloc(size); | 66 result = malloc(size); |
| 58 #else | 67 #else |
| 59 void* result; | |
| 60 // It's the responsibility of the caller to check the return value. | 68 // It's the responsibility of the caller to check the return value. |
| 61 ignore_result(base::UncheckedMalloc(size, &result)); | 69 ignore_result(base::UncheckedMalloc(size, &result)); |
| 70 #endif |
| 71 if (result) { |
| 72 prevent_overcommit(0x47, size, result); |
| 73 } |
| 62 return result; | 74 return result; |
| 63 #endif | |
| 64 } | 75 } |
| 65 | 76 |
| 66 void* sk_malloc_flags(size_t size, unsigned flags) { | 77 void* sk_malloc_flags(size_t size, unsigned flags) { |
| 67 if (flags & SK_MALLOC_THROW) { | 78 if (flags & SK_MALLOC_THROW) { |
| 68 return sk_malloc_throw(size); | 79 return sk_malloc_throw(size); |
| 69 } | 80 } |
| 70 return sk_malloc_nothrow(size); | 81 return sk_malloc_nothrow(size); |
| 71 } | 82 } |
| 72 | 83 |
| 73 void* sk_calloc_throw(size_t size) { | 84 void* sk_calloc_throw(size_t size) { |
| 74 return throw_on_failure(size, calloc(size, 1)); | 85 return prevent_overcommit(0, size, throw_on_failure(size, calloc(size, 1))); |
| 75 } | 86 } |
| 76 | 87 |
| 77 void* sk_calloc(size_t size) { | 88 void* sk_calloc(size_t size) { |
| 78 // TODO(b.kelemen): we should always use UncheckedCalloc but currently it | 89 // TODO(b.kelemen): we should always use UncheckedCalloc but currently it |
| 79 // doesn't work as intended everywhere. | 90 // doesn't work as intended everywhere. |
| 91 void* result; |
| 80 #if defined(OS_IOS) | 92 #if defined(OS_IOS) |
| 81 return calloc(1, size); | 93 result = calloc(1, size); |
| 82 #else | 94 #else |
| 83 void* result; | |
| 84 // It's the responsibility of the caller to check the return value. | 95 // It's the responsibility of the caller to check the return value. |
| 85 ignore_result(base::UncheckedCalloc(size, 1, &result)); | 96 ignore_result(base::UncheckedCalloc(size, 1, &result)); |
| 97 #endif |
| 98 if (result) { |
| 99 prevent_overcommit(0, size, result); |
| 100 } |
| 86 return result; | 101 return result; |
| 87 #endif | |
| 88 } | 102 } |
| OLD | NEW |