v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
memory.h
Go to the documentation of this file.
1// Copyright 2022 the V8 project 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
5#ifndef V8_BASE_PLATFORM_MEMORY_H_
6#define V8_BASE_PLATFORM_MEMORY_H_
7
8#include <cstddef>
9#include <cstdlib>
10
11#include "include/v8config.h"
12#include "src/base/bits.h"
13#include "src/base/logging.h"
14#include "src/base/macros.h"
15
16#if V8_OS_STARBOARD
17#include "starboard/memory.h"
18#endif // V8_OS_STARBOARD
19
20#if V8_OS_DARWIN
21#include <malloc/malloc.h>
22#elif V8_OS_OPENBSD
23#include <sys/malloc.h>
24#elif V8_OS_ZOS
25#include <stdlib.h>
26#else
27#include <malloc.h>
28#endif
29
30#if (V8_OS_POSIX && !V8_OS_AIX && !V8_OS_SOLARIS && !V8_OS_ZOS && !V8_OS_OPENBSD) || V8_OS_WIN
31#define V8_HAS_MALLOC_USABLE_SIZE 1
32#endif
33
34namespace v8::base {
35
36inline void* Malloc(size_t size) {
37#if V8_OS_STARBOARD
38 return SbMemoryAllocate(size);
39#elif V8_OS_AIX && _LINUX_SOURCE_COMPAT
40 // Work around for GCC bug on AIX.
41 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
42 return __linux_malloc(size);
43#else
44 return malloc(size);
45#endif
46}
47
48inline void* Realloc(void* memory, size_t size) {
49 // The result of realloc with zero size is implementation dependent.
50 // Disallow it.
51 CHECK_NE(0, size);
52#if V8_OS_STARBOARD
53 return SbMemoryReallocate(memory, size);
54#elif V8_OS_AIX && _LINUX_SOURCE_COMPAT
55 // Work around for GCC bug on AIX, see Malloc().
56 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
57 return __linux_realloc(memory, size);
58#else
59 return realloc(memory, size);
60#endif
61}
62
63inline void Free(void* memory) {
64#if V8_OS_STARBOARD
65 return SbMemoryDeallocate(memory);
66#else // !V8_OS_STARBOARD
67 return free(memory);
68#endif // !V8_OS_STARBOARD
69}
70
71inline void* Calloc(size_t count, size_t size) {
72#if V8_OS_STARBOARD
73 return SbMemoryCalloc(count, size);
74#elif V8_OS_AIX && _LINUX_SOURCE_COMPAT
75 // Work around for GCC bug on AIX, see Malloc().
76 return __linux_calloc(count, size);
77#else
78 return calloc(count, size);
79#endif
80}
81
82// Aligned allocation. Memory must be freed with `AlignedFree()` as not all
83// platforms support using general free for aligned allocations.
84inline void* AlignedAlloc(size_t size, size_t alignment) {
85 DCHECK_LE(alignof(void*), alignment);
87#if V8_OS_WIN
88 return _aligned_malloc(size, alignment);
89#elif V8_LIBC_BIONIC
90 // posix_memalign is not exposed in some Android versions, so we fall back to
91 // memalign. See http://code.google.com/p/android/issues/detail?id=35391.
92 return memalign(alignment, size);
93#elif V8_OS_ZOS
94 return __aligned_malloc(size, alignment);
95#else // POSIX
96 void* ptr;
97 if (posix_memalign(&ptr, alignment, size)) ptr = nullptr;
98 return ptr;
99#endif // POSIX
100}
101
102inline void AlignedFree(void* ptr) {
103#if V8_OS_WIN
104 _aligned_free(ptr);
105#elif V8_OS_ZOS
106 __aligned_free(ptr);
107#else
108 // Using regular Free() is not correct in general. For most platforms,
109 // including V8_LIBC_BIONIC, it is though.
110 base::Free(ptr);
111#endif
112}
113
114#if V8_HAS_MALLOC_USABLE_SIZE
115
116// Note that the use of additional bytes that deviate from the original
117// `Malloc()` request returned by `MallocUsableSize()` is not UBSan-safe. Use
118// `AllocateAtLeast()` for a safe version.
119inline size_t MallocUsableSize(void* ptr) {
120#if V8_OS_WIN
121 // |_msize| cannot handle a null pointer.
122 if (!ptr) return 0;
123 return _msize(ptr);
124#elif V8_OS_DARWIN
125 return malloc_size(ptr);
126#else // POSIX.
127 return malloc_usable_size(ptr);
128#endif // POSIX.
129}
130
131#endif // V8_HAS_MALLOC_USABLE_SIZE
132
133// Mimics C++23 `allocation_result`.
134template <class Pointer>
136 Pointer ptr = nullptr;
137 size_t count = 0;
138};
139
140// Allocates at least `n * sizeof(T)` uninitialized storage but may allocate
141// more which is indicated by the return value. Mimics C++23
142// `allocate_at_least()`.
143template <typename T>
145 const size_t min_wanted_size = n * sizeof(T);
146 auto* memory = static_cast<T*>(Malloc(min_wanted_size));
147#if !V8_HAS_MALLOC_USABLE_SIZE
148 return {memory, min_wanted_size};
149#else // V8_HAS_MALLOC_USABLE_SIZE
150 const size_t usable_size = MallocUsableSize(memory);
151#if V8_USE_UNDEFINED_BEHAVIOR_SANITIZER
152 if (memory == nullptr)
153 return {nullptr, 0};
154 // UBSan (specifically, -fsanitize=bounds) assumes that any access outside
155 // of the requested size for malloc is UB and will trap in ud2 instructions.
156 // This can be worked around by using `Realloc()` on the specific memory
157 // region.
158 if (usable_size != min_wanted_size) {
159 memory = static_cast<T*>(Realloc(memory, usable_size));
160 }
161#endif // V8_USE_UNDEFINED_BEHAVIOR_SANITIZER
162 return {memory, usable_size};
163#endif // V8_HAS_MALLOC_USABLE_SIZE
164}
165
166} // namespace v8::base
167
168#undef V8_HAS_MALLOC_USABLE_SIZE
169
170#endif // V8_BASE_PLATFORM_MEMORY_H_
#define T
constexpr bool IsPowerOfTwo(T value)
Definition bits.h:187
V8_NODISCARD AllocationResult< T * > AllocateAtLeast(size_t n)
Definition memory.h:144
void * Realloc(void *memory, size_t size)
Definition memory.h:48
void * Calloc(size_t count, size_t size)
Definition memory.h:71
void * Malloc(size_t size)
Definition memory.h:36
void AlignedFree(void *ptr)
Definition memory.h:102
void * AlignedAlloc(size_t size, size_t alignment)
Definition memory.h:84
void Free(void *memory)
Definition memory.h:63
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK_NE(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define V8_NODISCARD
Definition v8config.h:693