SkMemory_new_handler.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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
  3. // found in the LICENSE file.
  4. #include <stddef.h>
  5. #include <stdlib.h>
  6. #include <tuple>
  7. #include "base/debug/alias.h"
  8. #include "base/process/memory.h"
  9. #include "build/build_config.h"
  10. #include "third_party/skia/include/core/SkTypes.h"
  11. #include "third_party/skia/include/private/SkMalloc.h"
  12. #if BUILDFLAG(IS_WIN)
  13. #include <windows.h>
  14. #endif
  15. // This implementation of sk_malloc_flags() and friends is similar to
  16. // SkMemory_malloc.cpp, except it uses base::UncheckedMalloc and friends
  17. // for non-SK_MALLOC_THROW calls.
  18. //
  19. // The name of this file is historic: a previous implementation tried to
  20. // use std::set_new_handler() for the same effect, but it didn't actually work.
  21. static inline void* throw_on_failure(size_t size, void* p) {
  22. if (size > 0 && p == NULL) {
  23. // If we've got a NULL here, the only reason we should have failed is running out of RAM.
  24. sk_out_of_memory();
  25. }
  26. return p;
  27. }
  28. void sk_abort_no_print() {
  29. // Linker's ICF feature may merge this function with other functions with
  30. // the same definition (e.g. any function whose sole job is to call abort())
  31. // and it may confuse the crash report processing system.
  32. // http://crbug.com/860850
  33. static int static_variable_to_make_this_function_unique = 0x736b; // "sk"
  34. base::debug::Alias(&static_variable_to_make_this_function_unique);
  35. abort();
  36. }
  37. void sk_out_of_memory(void) {
  38. SkASSERT(!"sk_out_of_memory");
  39. base::TerminateBecauseOutOfMemory(0);
  40. // Extra safety abort().
  41. abort();
  42. }
  43. void* sk_realloc_throw(void* addr, size_t size) {
  44. return throw_on_failure(size, realloc(addr, size));
  45. }
  46. void sk_free(void* p) {
  47. if (p) {
  48. free(p);
  49. }
  50. }
  51. // We get lots of bugs filed on us that amount to overcommiting bitmap memory,
  52. // then some time later failing to back that VM with physical memory.
  53. // They're hard to track down, so in Debug mode we touch all memory right up front.
  54. //
  55. // For malloc, fill is an arbitrary byte and ideally not 0. For calloc, it's got to be 0.
  56. static void* prevent_overcommit(int fill, size_t size, void* p) {
  57. // We probably only need to touch one byte per page, but memset makes things easy.
  58. SkDEBUGCODE(memset(p, fill, size));
  59. return p;
  60. }
  61. static void* malloc_throw(size_t size) {
  62. return prevent_overcommit(0x42, size, throw_on_failure(size, malloc(size)));
  63. }
  64. static void* malloc_nothrow(size_t size) {
  65. // TODO(b.kelemen): we should always use UncheckedMalloc but currently it
  66. // doesn't work as intended everywhere.
  67. void* result;
  68. #if BUILDFLAG(IS_IOS)
  69. result = malloc(size);
  70. #else
  71. // It's the responsibility of the caller to check the return value.
  72. std::ignore = base::UncheckedMalloc(size, &result);
  73. #endif
  74. if (result) {
  75. prevent_overcommit(0x47, size, result);
  76. }
  77. return result;
  78. }
  79. static void* calloc_throw(size_t size) {
  80. return prevent_overcommit(0, size, throw_on_failure(size, calloc(size, 1)));
  81. }
  82. static void* calloc_nothrow(size_t size) {
  83. // TODO(b.kelemen): we should always use UncheckedCalloc but currently it
  84. // doesn't work as intended everywhere.
  85. void* result;
  86. #if BUILDFLAG(IS_IOS)
  87. result = calloc(1, size);
  88. #else
  89. // It's the responsibility of the caller to check the return value.
  90. std::ignore = base::UncheckedCalloc(size, 1, &result);
  91. #endif
  92. if (result) {
  93. prevent_overcommit(0, size, result);
  94. }
  95. return result;
  96. }
  97. void* sk_malloc_flags(size_t size, unsigned flags) {
  98. if (flags & SK_MALLOC_ZERO_INITIALIZE) {
  99. if (flags & SK_MALLOC_THROW) {
  100. return calloc_throw(size);
  101. } else {
  102. return calloc_nothrow(size);
  103. }
  104. } else {
  105. if (flags & SK_MALLOC_THROW) {
  106. return malloc_throw(size);
  107. } else {
  108. return malloc_nothrow(size);
  109. }
  110. }
  111. }