xref: /third_party/node/deps/v8/src/heap/cppgc/memory.h (revision 1cb0ef41)
1// Copyright 2021 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_HEAP_CPPGC_MEMORY_H_
6#define V8_HEAP_CPPGC_MEMORY_H_
7
8#include <cstddef>
9#include <cstdint>
10#include <cstring>
11
12#include "src/base/macros.h"
13#include "src/base/sanitizer/asan.h"
14#include "src/base/sanitizer/msan.h"
15#include "src/heap/cppgc/globals.h"
16
17namespace cppgc {
18namespace internal {
19
20V8_NOINLINE DISABLE_ASAN void NoSanitizeMemset(void* address, char c,
21                                               size_t bytes);
22
23static constexpr uint8_t kZappedValue = 0xdc;
24
25V8_INLINE void ZapMemory(void* address, size_t size) {
26  // The lowest bit of the zapped value should be 0 so that zapped object are
27  // never viewed as fully constructed objects.
28  memset(address, kZappedValue, size);
29}
30
31V8_INLINE void CheckMemoryIsZapped(const void* address, size_t size) {
32  for (size_t i = 0; i < size; i++) {
33    CHECK_EQ(kZappedValue, reinterpret_cast<ConstAddress>(address)[i]);
34  }
35}
36
37V8_INLINE void CheckMemoryIsZero(const void* address, size_t size) {
38  for (size_t i = 0; i < size; i++) {
39    CHECK_EQ(0, reinterpret_cast<ConstAddress>(address)[i]);
40  }
41}
42
43// Together `SetMemoryAccessible()` and `SetMemoryInaccessible()` form the
44// memory access model for allocation and free.
45V8_INLINE void SetMemoryAccessible(void* address, size_t size) {
46#if defined(V8_USE_MEMORY_SANITIZER)
47
48  MSAN_MEMORY_IS_INITIALIZED(address, size);
49
50#elif defined(V8_USE_ADDRESS_SANITIZER)
51
52  ASAN_UNPOISON_MEMORY_REGION(address, size);
53
54#elif DEBUG
55
56  memset(address, 0, size);
57
58#else  // Release builds.
59
60  // Nothing to be done for release builds.
61
62#endif  // Release builds.
63}
64
65V8_INLINE void SetMemoryInaccessible(void* address, size_t size) {
66#if defined(V8_USE_MEMORY_SANITIZER)
67
68  memset(address, 0, size);
69  MSAN_ALLOCATED_UNINITIALIZED_MEMORY(address, size);
70
71#elif defined(V8_USE_ADDRESS_SANITIZER)
72
73  NoSanitizeMemset(address, 0, size);
74  ASAN_POISON_MEMORY_REGION(address, size);
75
76#elif DEBUG
77
78  ::cppgc::internal::ZapMemory(address, size);
79
80#else  // Release builds.
81
82  memset(address, 0, size);
83
84#endif  // Release builds.
85}
86
87constexpr bool CheckMemoryIsInaccessibleIsNoop() {
88#if defined(V8_USE_MEMORY_SANITIZER)
89
90  return true;
91
92#elif defined(V8_USE_ADDRESS_SANITIZER)
93
94  return false;
95
96#elif DEBUG
97
98  return false;
99
100#else  // Release builds.
101
102  return true;
103
104#endif  // Release builds.
105}
106
107V8_INLINE void CheckMemoryIsInaccessible(const void* address, size_t size) {
108#if defined(V8_USE_MEMORY_SANITIZER)
109
110  static_assert(CheckMemoryIsInaccessibleIsNoop(),
111                "CheckMemoryIsInaccessibleIsNoop() needs to reflect "
112                "CheckMemoryIsInaccessible().");
113  // Unable to check that memory is marked as uninitialized by MSAN.
114
115#elif defined(V8_USE_ADDRESS_SANITIZER)
116
117  static_assert(!CheckMemoryIsInaccessibleIsNoop(),
118                "CheckMemoryIsInaccessibleIsNoop() needs to reflect "
119                "CheckMemoryIsInaccessible().");
120  // Only check if memory is poisoned on 64 bit, since there we make sure that
121  // object sizes and alignments are multiple of shadow memory granularity.
122#if defined(V8_TARGET_ARCH_64_BIT)
123  ASAN_CHECK_WHOLE_MEMORY_REGION_IS_POISONED(address, size);
124#endif
125  ASAN_UNPOISON_MEMORY_REGION(address, size);
126  CheckMemoryIsZero(address, size);
127  ASAN_POISON_MEMORY_REGION(address, size);
128
129#elif DEBUG
130
131  static_assert(!CheckMemoryIsInaccessibleIsNoop(),
132                "CheckMemoryIsInaccessibleIsNoop() needs to reflect "
133                "CheckMemoryIsInaccessible().");
134  CheckMemoryIsZapped(address, size);
135
136#else  // Release builds.
137
138  static_assert(CheckMemoryIsInaccessibleIsNoop(),
139                "CheckMemoryIsInaccessibleIsNoop() needs to reflect "
140                "CheckMemoryIsInaccessible().");
141  // No check in release builds.
142
143#endif  // Release builds.
144}
145
146}  // namespace internal
147}  // namespace cppgc
148
149#endif  // V8_HEAP_CPPGC_MEMORY_H_
150