v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
ptr-compr.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_COMMON_PTR_COMPR_H_
6#define V8_COMMON_PTR_COMPR_H_
7
8#include "src/base/memory.h"
10
11namespace v8::internal {
12
13class IsolateGroup;
14
15#ifdef V8_ENABLE_SANDBOX
16class Sandbox;
17#endif // V8_ENABLE_SANDBOX
18
19// This is just a collection of common compression scheme related functions.
20// Each pointer compression cage then has its own compression scheme, which
21// mainly differes in the cage base address they use.
22template <typename Cage>
24 public:
26 Address on_heap_addr);
27
29 PtrComprCageBase cage_base);
30
31 // Compresses full-pointer representation of a tagged value to on-heap
32 // representation.
33 // Must only be used for compressing object pointers since this function
34 // assumes that we deal with a valid address inside the pointer compression
35 // cage.
37 // Compress a potentially invalid pointer.
38 V8_INLINE static constexpr Tagged_t CompressAny(Address tagged);
39
40 // Decompresses smi value.
42
43 // Decompresses any tagged value, preserving both weak- and smi- tags.
44 template <typename TOnHeapAddress>
45 V8_INLINE static Address DecompressTagged(TOnHeapAddress on_heap_addr,
46 Tagged_t raw_value);
47
48 // Given a 64bit raw value, found on the stack, calls the callback function
49 // with all possible pointers that may be "contained" in compressed form in
50 // this value, either as complete compressed pointers or as intermediate
51 // (half-computed) results.
52 template <typename ProcessPointerCallback>
54 PtrComprCageBase cage_base, Address raw_value,
55 ProcessPointerCallback callback);
56
57 // Process-wide cage base value used for decompression.
60};
61
62// The main pointer compression cage, used for most objects.
63class MainCage : public AllStatic {
65
66 // These non-inlined accessors to base_ field are used in component builds
67 // where cross-component access to thread local variables is not allowed.
70
71#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
72 static V8_EXPORT_PRIVATE uintptr_t base_ V8_CONSTINIT;
73#else
74 static thread_local uintptr_t base_ V8_CONSTINIT;
75#endif // V8_COMPRESS_POINTERS_IN_SHARED_CAGE
76};
78
79#ifdef V8_ENABLE_SANDBOX
80// Compression scheme used for compressed pointers between trusted objects in
81// the trusted heap space, outside of the sandbox.
82class TrustedCage : public AllStatic {
83 friend class V8HeapCompressionSchemeImpl<TrustedCage>;
84
85 // Just to unify code with other cages in the multi-cage mode.
86 static V8_EXPORT_PRIVATE Address base_non_inlined();
87 static V8_EXPORT_PRIVATE void set_base_non_inlined(Address base);
88
89 static V8_EXPORT_PRIVATE uintptr_t base_ V8_CONSTINIT;
90};
91using TrustedSpaceCompressionScheme = V8HeapCompressionSchemeImpl<TrustedCage>;
92#else
93// The trusted cage does not exist in this case.
95#endif // V8_ENABLE_SANDBOX
96
97// A compression scheme which can be passed if the only objects we ever expect
98// to see are Smis (e.g. for {TaggedField<Smi, 0, SmiCompressionScheme>}).
100 public:
102 // For runtime code the upper 32-bits of the Smi value do not matter.
103 return static_cast<Address>(raw_value);
104 }
105
107 DCHECK(HAS_SMI_TAG(tagged));
108 return static_cast<Tagged_t>(tagged);
109 }
110};
111
112#ifdef V8_EXTERNAL_CODE_SPACE
113// Compression scheme used for fields containing InstructionStream objects
114// (namely for the Code::code field).
115// Unlike the V8HeapCompressionScheme this one allows the cage to cross 4GB
116// boundary at a price of making decompression slightly more complex.
117// The former outweighs the latter because it gives us more flexibility in
118// allocating the code range closer to .text section in the process address
119// space. At the same time decompression of the external code field happens
120// relatively rarely during GC.
121// The base can be any value such that [base, base + 4GB) contains the whole
122// code range.
123//
124// This scheme works as follows:
125// --|----------{---------|------}--------------|--
126// 4GB | 4GB | 4GB
127// +-- code range --+
128// |
129// cage base
130//
131// * Cage base value is OS page aligned for simplicity (although it's not
132// strictly necessary).
133// * Code range size is smaller than or equal to 4GB.
134// * Compression is just a truncation to 32-bits value.
135// * Decompression of a pointer:
136// - if "compressed" cage base is <= than compressed value then one just
137// needs to OR the upper 32-bits of the case base to get the decompressed
138// value.
139// - if compressed value is smaller than "compressed" cage base then ORing
140// the upper 32-bits of the cage base is not enough because the resulting
141// value will be off by 4GB, which has to be added to the result.
142// - note that decompression doesn't modify the lower 32-bits of the value.
143// * Decompression of Smi values is made a no-op for simplicity given that
144// on the hot paths of decompressing the Code pointers it's already known
145// that the value is not a Smi.
146//
147class ExternalCodeCompressionScheme {
148 public:
149 V8_INLINE static Address PrepareCageBaseAddress(Address on_heap_addr);
150
151 // Note that this compression scheme doesn't allow reconstruction of the cage
152 // base value from any arbitrary value, thus the cage base has to be passed
153 // explicitly to the decompression functions.
154 static Address GetPtrComprCageBaseAddress(Address on_heap_addr) = delete;
155
156 V8_INLINE static Address GetPtrComprCageBaseAddress(
157 PtrComprCageBase cage_base);
158
159 // Compresses full-pointer representation of a tagged value to on-heap
160 // representation.
161 // Must only be used for compressing object pointers (incl. SMI) since this
162 // function assumes pointers to be inside the pointer compression cage.
163 V8_INLINE static Tagged_t CompressObject(Address tagged);
164 // Compress anything that does not follow the above requirements (e.g. a maybe
165 // object, or a marker bit pattern).
166 V8_INLINE static constexpr Tagged_t CompressAny(Address tagged);
167
168 // Decompresses smi value.
169 V8_INLINE static Address DecompressTaggedSigned(Tagged_t raw_value);
170
171 // Decompresses any tagged value, preserving both weak- and smi- tags.
172 template <typename TOnHeapAddress>
173 V8_INLINE static Address DecompressTagged(TOnHeapAddress on_heap_addr,
174 Tagged_t raw_value);
175
176 // Process-wide cage base value used for decompression.
177 V8_INLINE static void InitBase(Address base);
178 V8_INLINE static Address base();
179
180 // Given a 64bit raw value, found on the stack, calls the callback function
181 // with all possible pointers that may be "contained" in compressed form in
182 // this value, either as complete compressed pointers or as intermediate
183 // (half-computed) results.
184 template <typename ProcessPointerCallback>
185 V8_INLINE static void ProcessIntermediatePointers(
186 PtrComprCageBase cage_base, Address raw_value,
187 ProcessPointerCallback callback);
188
189 private:
190 // These non-inlined accessors to base_ field are used in component builds
191 // where cross-component access to thread local variables is not allowed.
192 static V8_EXPORT_PRIVATE Address base_non_inlined();
193 static V8_EXPORT_PRIVATE void set_base_non_inlined(Address base);
194
195#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
196 static V8_EXPORT_PRIVATE uintptr_t base_ V8_CONSTINIT;
197#else
198 static thread_local uintptr_t base_ V8_CONSTINIT;
199#endif // V8_COMPRESS_POINTERS_IN_SHARED_CAGE
200};
201
202#endif // V8_EXTERNAL_CODE_SPACE
203
204// Accessors for fields that may be unaligned due to pointer compression.
205
206template <typename V>
208 // Pointer compression causes types larger than kTaggedSize to be unaligned.
209#ifdef V8_COMPRESS_POINTERS
210 constexpr bool v8_pointer_compression_unaligned = sizeof(V) > kTaggedSize;
211#else
212 constexpr bool v8_pointer_compression_unaligned = false;
213#endif
214 // Bug(v8:8875) Double fields may be unaligned.
215 constexpr bool unaligned_double_field =
216 std::is_same<V, double>::value && kDoubleSize > kTaggedSize;
217 if (unaligned_double_field || v8_pointer_compression_unaligned) {
219 } else {
220 return base::Memory<V>(p);
221 }
222}
223
224template <typename V>
225static inline void WriteMaybeUnalignedValue(Address p, V value) {
226 // Pointer compression causes types larger than kTaggedSize to be unaligned.
227#ifdef V8_COMPRESS_POINTERS
228 constexpr bool v8_pointer_compression_unaligned = sizeof(V) > kTaggedSize;
229#else
230 constexpr bool v8_pointer_compression_unaligned = false;
231#endif
232 // Bug(v8:8875) Double fields may be unaligned.
233 constexpr bool unaligned_double_field =
234 std::is_same<V, double>::value && kDoubleSize > kTaggedSize;
235 if (unaligned_double_field || v8_pointer_compression_unaligned) {
237 } else {
239 }
240}
241
242// When multi-cage pointer compression mode is enabled this scope object
243// saves current cage's base values and sets them according to given Isolate.
244// For all other configurations this scope object is a no-op.
245// Note: In most cases you want a full `SetCurrentIsolateScope` which also
246// updates TLS to make the isolate the "current" isolate.
247#ifdef V8_COMPRESS_POINTERS_IN_MULTIPLE_CAGES
248class V8_NODISCARD PtrComprCageAccessScope final {
249 public:
250 V8_INLINE explicit PtrComprCageAccessScope(Isolate* isolate);
251 V8_INLINE ~PtrComprCageAccessScope();
252
253 private:
254 const Address cage_base_;
255#ifdef V8_EXTERNAL_CODE_SPACE
256 const Address code_cage_base_;
257#endif // V8_EXTERNAL_CODE_SPACE
258 IsolateGroup* saved_current_isolate_group_;
259#ifdef V8_ENABLE_SANDBOX
260 Sandbox* saved_current_sandbox_;
261#endif // V8_COMPRESS_POINTERS_IN_MULTIPLE_CAGES
262};
263#else // V8_COMPRESS_POINTERS_IN_MULTIPLE_CAGES
265 public:
267};
268#endif // V8_COMPRESS_POINTERS_IN_MULTIPLE_CAGES
269
270V8_INLINE PtrComprCageBase GetPtrComprCageBase();
271
272} // namespace v8::internal
273
274#endif // V8_COMMON_PTR_COMPR_H_
static V8_EXPORT_PRIVATE void set_base_non_inlined(Address base)
static V8_EXPORT_PRIVATE Address base_non_inlined()
static thread_local uintptr_t base_ V8_CONSTINIT
Definition ptr-compr.h:74
V8_INLINE PtrComprCageAccessScope(Isolate *isolate)
Definition ptr-compr.h:266
static Tagged_t CompressObject(Address tagged)
Definition ptr-compr.h:106
static Address DecompressTaggedSigned(Tagged_t raw_value)
Definition ptr-compr.h:101
static V8_INLINE Address GetPtrComprCageBaseAddress(PtrComprCageBase cage_base)
static V8_INLINE constexpr Tagged_t CompressAny(Address tagged)
static V8_INLINE Address DecompressTaggedSigned(Tagged_t raw_value)
static V8_INLINE Tagged_t CompressObject(Address tagged)
static V8_INLINE void ProcessIntermediatePointers(PtrComprCageBase cage_base, Address raw_value, ProcessPointerCallback callback)
static V8_INLINE void InitBase(Address base)
static V8_INLINE Address DecompressTagged(TOnHeapAddress on_heap_addr, Tagged_t raw_value)
V8_CONST static V8_INLINE Address base()
static V8_INLINE constexpr Address GetPtrComprCageBaseAddress(Address on_heap_addr)
#define HAS_SMI_TAG(value)
Definition globals.h:1771
TNode< Object > callback
static V ReadUnalignedValue(Address p)
Definition memory.h:28
T & Memory(Address addr)
Definition memory.h:18
static void WriteUnalignedValue(Address p, V value)
Definition memory.h:41
constexpr int kTaggedSize
Definition globals.h:542
static void WriteMaybeUnalignedValue(Address p, V value)
Definition ptr-compr.h:225
Address Tagged_t
Definition globals.h:547
V8_INLINE PtrComprCageBase GetPtrComprCageBase()
return value
Definition map-inl.h:893
static V ReadMaybeUnalignedValue(Address p)
Definition ptr-compr.h:207
constexpr int kDoubleSize
Definition globals.h:407
V8HeapCompressionScheme TrustedSpaceCompressionScheme
Definition globals.h:1143
V8HeapCompressionSchemeImpl< MainCage > V8HeapCompressionScheme
Definition globals.h:1137
#define DCHECK(condition)
Definition logging.h:482
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_INLINE
Definition v8config.h:500
#define V8_CONSTINIT
Definition v8config.h:564
#define V8_CONST
Definition v8config.h:555
#define V8_NODISCARD
Definition v8config.h:693