mirrored from https://skia.googlesource.com/skia
/
SkMemory_malloc.cpp
138 lines (123 loc) · 4.07 KB
/
SkMemory_malloc.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkFeatures.h"
#include "include/private/base/SkMalloc.h"
#include <algorithm>
#include <cstdlib>
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
#include <malloc/malloc.h>
#elif defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX)
#include <malloc.h>
#elif defined(SK_BUILD_FOR_WIN)
#include <malloc.h>
#endif
#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN)
#include <intrin.h>
// This is a super stable value and setting it here avoids pulling in all of windows.h.
#ifndef FAST_FAIL_FATAL_APP_EXIT
#define FAST_FAIL_FATAL_APP_EXIT 7
#endif
#endif
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
#define SK_DEBUGFAILF(fmt, ...) SK_ABORT(fmt"\n", __VA_ARGS__)
#else
#define SK_DEBUGFAILF(fmt, ...) SkASSERT((SkDebugf(fmt"\n", __VA_ARGS__), false))
#endif
static inline void sk_out_of_memory(size_t size) {
SK_DEBUGFAILF("sk_out_of_memory (asked for %zu bytes)",
size);
#if defined(SK_BUILD_FOR_AFL_FUZZ)
exit(1);
#else
abort();
#endif
}
static inline void* throw_on_failure(size_t size, void* p) {
if (size > 0 && p == nullptr) {
// If we've got a nullptr here, the only reason we should have failed is running out of RAM.
sk_out_of_memory(size);
}
return p;
}
void sk_abort_no_print() {
#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN)
__fastfail(FAST_FAIL_FATAL_APP_EXIT);
#elif defined(__clang__)
__builtin_trap();
#else
abort();
#endif
}
void sk_out_of_memory(void) {
SkDEBUGFAIL("sk_out_of_memory");
#if defined(SK_BUILD_FOR_AFL_FUZZ)
exit(1);
#else
abort();
#endif
}
void* sk_realloc_throw(void* addr, size_t size) {
if (size == 0) {
sk_free(addr);
return nullptr;
}
return throw_on_failure(size, realloc(addr, size));
}
void sk_free(void* p) {
// The guard here produces a performance improvement across many tests, and many platforms.
// Removing the check was tried in skia cl 588037.
if (p != nullptr) {
free(p);
}
}
void* sk_malloc_flags(size_t size, unsigned flags) {
void* p;
if (flags & SK_MALLOC_ZERO_INITIALIZE) {
p = calloc(size, 1);
} else {
#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && defined(__BIONIC__)
/* TODO: After b/169449588 is fixed, we will want to change this to restore
* original behavior instead of always disabling the flag.
* TODO: After b/158870657 is fixed and scudo is used globally, we can assert when an
* an error is returned.
*/
// malloc() generally doesn't initialize its memory and that's a huge security hole,
// so Android has replaced its malloc() with one that zeros memory,
// but that's a huge performance hit for HWUI, so turn it back off again.
(void)mallopt(M_THREAD_DISABLE_MEM_INIT, 1);
#endif
p = malloc(size);
#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && defined(__BIONIC__)
(void)mallopt(M_THREAD_DISABLE_MEM_INIT, 0);
#endif
}
if (flags & SK_MALLOC_THROW) {
return throw_on_failure(size, p);
} else {
return p;
}
}
size_t sk_malloc_size(void* addr, size_t size) {
size_t completeSize = size;
// Use the OS specific calls to find the actual capacity.
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
// TODO: remove the max, when the chrome implementation of malloc_size doesn't return 0.
completeSize = std::max(malloc_size(addr), size);
#elif defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 17
completeSize = malloc_usable_size(addr);
SkASSERT(completeSize >= size);
#elif defined(SK_BUILD_FOR_UNIX)
completeSize = malloc_usable_size(addr);
SkASSERT(completeSize >= size);
#elif defined(SK_BUILD_FOR_WIN)
completeSize = _msize(addr);
SkASSERT(completeSize >= size);
#endif
return completeSize;
}