Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
fx_memory.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "core/fxcrt/fx_memory.h"
8
9#include <stdint.h> // For uintptr_t.
10#include <stdlib.h> // For abort().
11
12#include <iterator>
13#include <limits>
14#include <type_traits>
15
16#include "build/build_config.h"
17#include "core/fxcrt/check_op.h"
18#include "core/fxcrt/debug/alias.h"
19
20#if BUILDFLAG(IS_WIN)
21#include <windows.h>
22#endif
23
24#if BUILDFLAG(IS_ANDROID)
25#include <malloc.h>
26#endif
27
28namespace {
29
30#if DCHECK_IS_ON()
31// TODO(thestig): When C++20 is required, replace with std::has_single_bit().
32// Returns true iff |value| is a power of 2.
33template <typename T, typename = std::enable_if<std::is_integral<T>::value>>
34constexpr inline bool IsPowerOfTwo(T value) {
35 // From "Hacker's Delight": Section 2.1 Manipulating Rightmost Bits.
36 //
37 // Only positive integers with a single bit set are powers of two. If only one
38 // bit is set in x (e.g. 0b00000100000000) then |x-1| will have that bit set
39 // to zero and all bits to its right set to 1 (e.g. 0b00000011111111). Hence
40 // |x & (x-1)| is 0 iff x is a power of two.
41 return value > 0 && (value & (value - 1)) == 0;
42}
43
44#ifdef __has_builtin
45#define SUPPORTS_BUILTIN_IS_ALIGNED (__has_builtin(__builtin_is_aligned))
46#else
47#define SUPPORTS_BUILTIN_IS_ALIGNED 0
48#endif
49
50inline bool IsAligned(void* val, size_t alignment) {
51 // If the compiler supports builtin alignment checks prefer them.
52#if SUPPORTS_BUILTIN_IS_ALIGNED
53 return __builtin_is_aligned(reinterpret_cast<uintptr_t>(val), alignment);
54#else
55 DCHECK(IsPowerOfTwo(alignment));
56 return (reinterpret_cast<uintptr_t>(val) & (alignment - 1)) == 0;
57#endif
58}
59
60#undef SUPPORTS_BUILTIN_IS_ALIGNED
61
62#endif // DCHECK_IS_ON()
63
64} // namespace
65
66void* FXMEM_DefaultAlloc(size_t byte_size) {
67 return pdfium::internal::Alloc(byte_size, 1);
68}
69
70void* FXMEM_DefaultCalloc(size_t num_elems, size_t byte_size) {
71 return pdfium::internal::Calloc(num_elems, byte_size);
72}
73
74void* FXMEM_DefaultRealloc(void* pointer, size_t new_size) {
75 return pdfium::internal::Realloc(pointer, new_size, 1);
76}
77
78void FXMEM_DefaultFree(void* pointer) {
79 FX_Free(pointer);
80}
81
83 // Convince the linker this should not be folded with similar functions using
84 // Identical Code Folding.
85 static int make_this_function_aliased = 0xbd;
86 pdfium::Alias(&make_this_function_aliased);
87
88#if BUILDFLAG(IS_WIN)
89 // The same custom Windows exception code used in Chromium and Breakpad.
90 constexpr DWORD kOomExceptionCode = 0xe0000008;
91 ULONG_PTR exception_args[] = {size};
92 ::RaiseException(kOomExceptionCode, EXCEPTION_NONCONTINUABLE,
93 std::size(exception_args), exception_args);
94#endif
95
96 // Terminate cleanly.
97 abort();
98}
99
100void* FX_AlignedAlloc(size_t size, size_t alignment) {
101 DCHECK_GT(size, 0u);
102 DCHECK(IsPowerOfTwo(alignment));
103 DCHECK_EQ(alignment % sizeof(void*), 0u);
104 void* ptr = nullptr;
105#if BUILDFLAG(IS_WIN)
106 ptr = _aligned_malloc(size, alignment);
107#elif BUILDFLAG(IS_ANDROID)
108 // Android technically supports posix_memalign(), but does not expose it in
109 // the current version of the library headers used by Chrome. Luckily,
110 // memalign() on Android returns pointers which can safely be used with
111 // free(), so we can use it instead. Issue filed to document this:
112 // http://code.google.com/p/android/issues/detail?id=35391
113 ptr = memalign(alignment, size);
114#else
115 int ret = posix_memalign(&ptr, alignment, size);
116 if (ret != 0) {
117 ptr = nullptr;
118 }
119#endif
120
121 // Since aligned allocations may fail for non-memory related reasons, force a
122 // crash if we encounter a failed allocation; maintaining consistent behavior
123 // with a normal allocation failure in Chrome.
124 if (!ptr) {
125 CHECK(false);
126 }
127 // Sanity check alignment just to be safe.
128 DCHECK(IsAligned(ptr, alignment));
129 return ptr;
130}
131
132namespace pdfium::internal {
133
134void* Alloc2D(size_t w, size_t h, size_t member_size) {
135 if (w >= std::numeric_limits<size_t>::max() / h) {
136 return nullptr;
137 }
138
139 return Alloc(w * h, member_size);
140}
141
142void* AllocOrDie(size_t num_members, size_t member_size) {
143 void* result = Alloc(num_members, member_size);
144 if (!result)
145 FX_OutOfMemoryTerminate(0); // Never returns.
146
147 return result;
148}
149
150void* AllocOrDie2D(size_t w, size_t h, size_t member_size) {
151 if (w >= std::numeric_limits<size_t>::max() / h)
152 FX_OutOfMemoryTerminate(0); // Never returns.
153
154 return AllocOrDie(w * h, member_size);
155}
156void* CallocOrDie(size_t num_members, size_t member_size) {
157 void* result = Calloc(num_members, member_size);
158 if (!result)
159 FX_OutOfMemoryTerminate(0); // Never returns.
160
161 return result;
162}
163
164void* CallocOrDie2D(size_t w, size_t h, size_t member_size) {
165 if (w >= std::numeric_limits<size_t>::max() / h)
166 FX_OutOfMemoryTerminate(0); // Never returns.
167
168 return CallocOrDie(w * h, member_size);
169}
170
171void* ReallocOrDie(void* ptr, size_t num_members, size_t member_size) {
172 void* result = Realloc(ptr, num_members, member_size);
173 if (!result)
174 FX_OutOfMemoryTerminate(0); // Never returns.
175
176 return result;
177}
178
179void* StringAllocOrDie(size_t num_members, size_t member_size) {
180 void* result = StringAlloc(num_members, member_size);
181 if (!result)
182 FX_OutOfMemoryTerminate(0); // Never returns.
183
184 return result;
185}
186
187} // namespace pdfium::internal
#define DCHECK_IS_ON()
Definition check.h:24
#define DCHECK
Definition check.h:33
#define DCHECK_GT(x, y)
Definition check_op.h:20
#define DCHECK_EQ(x, y)
Definition check_op.h:17
#define NOINLINE
NOINLINE void FX_OutOfMemoryTerminate(size_t size)
Definition fx_memory.cpp:82
void * FXMEM_DefaultAlloc(size_t byte_size)
Definition fx_memory.cpp:66
void * FXMEM_DefaultCalloc(size_t num_elems, size_t byte_size)
Definition fx_memory.cpp:70
void * FX_AlignedAlloc(size_t size, size_t alignment)
void * FXMEM_DefaultRealloc(void *pointer, size_t new_size)
Definition fx_memory.cpp:74
void FXMEM_DefaultFree(void *pointer)
Definition fx_memory.cpp:78
void * CallocOrDie2D(size_t w, size_t h, size_t member_size)
void * AllocOrDie2D(size_t w, size_t h, size_t member_size)
void * StringAllocOrDie(size_t num_members, size_t member_size)
void * ReallocOrDie(void *ptr, size_t num_members, size_t member_size)
void * AllocOrDie(size_t num_members, size_t member_size)
void * Alloc2D(size_t w, size_t h, size_t member_size)
void * CallocOrDie(size_t num_members, size_t member_size)
void Alias(const void *var)
Definition alias.cc:17
#define CHECK(cvref)
#define __has_builtin(x)