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