v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
instruction-stream.h
Go to the documentation of this file.
1// Copyright 2023 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_OBJECTS_INSTRUCTION_STREAM_H_
6#define V8_OBJECTS_INSTRUCTION_STREAM_H_
7
8#ifdef DEBUG
9#include <set>
10#endif
11
14
15// Has to be the last include (doesn't have include guards):
17
18namespace v8 {
19namespace internal {
20
21class Code;
22class WritableJitAllocation;
23
24// InstructionStream contains the instruction stream for V8-generated code
25// objects.
26//
27// When V8_EXTERNAL_CODE_SPACE is enabled, InstructionStream objects are
28// allocated in a separate pointer compression cage instead of the cage where
29// all the other objects are allocated.
30//
31// An InstructionStream is a trusted object as it lives outside of the sandbox
32// and contains trusted content (machine code). However, it is special in that
33// it doesn't live in the trusted space but instead in the code space.
35 public:
37
38 // All InstructionStream objects have the following layout:
39 //
40 // +--------------------------+
41 // | header |
42 // +--------------------------+ <-- body_start()
43 // | instructions | == instruction_start()
44 // | ... |
45 // | padded to meta alignment | see kMetadataAlignment
46 // +--------------------------+ <-- instruction_end()
47 // | metadata | == metadata_start() (MS)
48 // | ... |
49 // | | <-- MS + handler_table_offset()
50 // | | <-- MS + constant_pool_offset()
51 // | | <-- MS + code_comments_offset()
52 // | | <-- MS + unwinding_info_offset()
53 // | padded to obj alignment |
54 // +--------------------------+ <-- metadata_end() == body_end()
55 // | padded to kCodeAlignmentMinusCodeHeader
56 // +--------------------------+
57 //
58 // In other words, the variable-size 'body' consists of 'instructions' and
59 // 'metadata'.
60
61 // Constants for use in static asserts, stating whether the body is adjacent,
62 // i.e. instructions and metadata areas are adjacent.
63 static constexpr bool kOnHeapBodyIsContiguous = true;
64 static constexpr bool kOffHeapBodyIsContiguous = false;
65 static constexpr bool kBodyIsContiguous =
67
68 inline Address instruction_start() const;
69
70 // The metadata section is aligned to this value.
71 static constexpr int kMetadataAlignment = kIntSize;
72
73 // [code]: The associated Code object.
74 //
75 // Set to Smi::zero() during initialization. Heap iterators may see
76 // InstructionStream objects in this state.
77 inline Tagged<Code> code(AcquireLoadTag tag) const;
78 inline Tagged<Object> raw_code(AcquireLoadTag tag) const;
79 // Use when the InstructionStream may be uninitialized:
80 inline bool TryGetCode(Tagged<Code>* code_out, AcquireLoadTag tag) const;
81 inline bool TryGetCodeUnchecked(Tagged<Code>* code_out,
82 AcquireLoadTag tag) const;
83
84 inline Address constant_pool() const;
85
86 // [relocation_info]: InstructionStream relocation information.
88 // Unchecked accessor to be used during GC.
90
91 inline uint8_t* relocation_start() const;
92 inline uint8_t* relocation_end() const;
93 inline int relocation_size() const;
94
95 // The size of the entire body section, containing instructions and inlined
96 // metadata.
97 DECL_PRIMITIVE_GETTER(body_size, uint32_t)
98 inline Address body_end() const;
99
100 static constexpr int TrailingPaddingSizeFor(uint32_t body_size) {
101 return RoundUp<kCodeAlignment>(kHeaderSize + body_size) - kHeaderSize -
102 body_size;
103 }
104 static constexpr int SizeFor(int body_size) {
105 return kHeaderSize + body_size + TrailingPaddingSizeFor(body_size);
106 }
107 inline int Size() const;
108
111 Address location_of_address);
112
113 // Relocate the code by delta bytes.
114 void Relocate(WritableJitAllocation& jit_allocation, intptr_t delta);
115
117 Tagged<HeapObject> self, Tagged<Map> map, uint32_t body_size,
118 int constant_pool_offset, Tagged<TrustedByteArray> reloc_info);
120 Tagged<TrustedByteArray> reloc_info, CodeDesc desc,
121 Heap* heap);
123
126
127 // Layout description.
128#define ISTREAM_FIELDS(V) \
129 V(kCodeOffset, kProtectedPointerSize) \
130 V(kRelocationInfoOffset, kProtectedPointerSize) \
131 /* Data or code not directly visited by GC directly starts here. */ \
132 V(kDataStart, 0) \
133 V(kBodySizeOffset, kUInt32Size) \
134 V(kConstantPoolOffsetOffset, V8_EMBEDDED_CONSTANT_POOL_BOOL ? kIntSize : 0) \
135 V(kUnalignedSize, OBJECT_POINTER_PADDING(kUnalignedSize)) \
136 V(kHeaderSize, 0)
138#undef ISTREAM_FIELDS
139
140 static_assert(kCodeAlignment >= kHeaderSize);
141 // We do two things to ensure kCodeAlignment of the entry address:
142 // 1) Add kCodeAlignmentMinusCodeHeader padding once in the beginning of every
143 // MemoryChunk.
144 // 2) Round up all IStream allocations to a multiple of kCodeAlignment, see
145 // TrailingPaddingSizeFor.
146 // Together, the IStream object itself will always start at offset
147 // kCodeAlignmentMinusCodeHeader, which aligns the entry to kCodeAlignment.
148 static constexpr int kCodeAlignmentMinusCodeHeader =
150
151 class BodyDescriptor;
152
153 private:
154 friend class Factory;
155
157 public:
161 WriteBarrierPromise& operator=(const WriteBarrierPromise&) = delete;
162
163#ifdef DEBUG
164 void RegisterAddress(Address address);
165 void ResolveAddress(Address address);
167
168 private:
169 std::set<Address> delayed_write_barriers_;
170#else
171 void RegisterAddress(Address address) {}
172 void ResolveAddress(Address address) {}
173#endif
174 };
175
176 // Migrate code from desc without flushing the instruction cache. This
177 // function will not trigger any write barriers and the caller needs to call
178 // RelocateFromDescWriteBarriers afterwards. This is split into two functions,
179 // since the former needs write access to executable memory and we need to
180 // keep this critical section minimal since any memory write poses attack
181 // surface for CFI and will require special validation.
182 WriteBarrierPromise RelocateFromDesc(WritableJitAllocation& jit_allocation,
183 Heap* heap, const CodeDesc& desc,
185 const DisallowGarbageCollection& no_gc);
188 WriteBarrierPromise& promise,
189 const DisallowGarbageCollection& no_gc);
190
191 // Must be used when loading any of InstructionStream's tagged fields.
192 static inline PtrComprCageBase main_cage_base();
193
195};
196
197} // namespace internal
198} // namespace v8
199
201
202#endif // V8_OBJECTS_INSTRUCTION_STREAM_H_
Address address() const
WriteBarrierPromise(WriteBarrierPromise &&) V8_NOEXCEPT=default
Tagged< Object > raw_code(AcquireLoadTag tag) const
static PtrComprCageBase main_cage_base()
static constexpr int kCodeAlignmentMinusCodeHeader
static NEVER_READ_ONLY_SPACE constexpr bool kOnHeapBodyIsContiguous
static constexpr bool kOffHeapBodyIsContiguous
void RelocateFromDescWriteBarriers(Heap *heap, const CodeDesc &desc, Address constant_pool, WriteBarrierPromise &promise, const DisallowGarbageCollection &no_gc)
bool TryGetCode(Tagged< Code > *code_out, AcquireLoadTag tag) const
OBJECT_CONSTRUCTORS(InstructionStream, TrustedObject)
static constexpr int kMetadataAlignment
static constexpr int TrailingPaddingSizeFor(uint32_t body_size)
static Tagged< InstructionStream > FromTargetAddress(Address address)
bool TryGetCodeUnchecked(Tagged< Code > *code_out, AcquireLoadTag tag) const
static Tagged< InstructionStream > FromEntryAddress(Address location_of_address)
V8_INLINE void Finalize(Tagged< Code > code, Tagged< TrustedByteArray > reloc_info, CodeDesc desc, Heap *heap)
static constexpr bool kBodyIsContiguous
void Relocate(WritableJitAllocation &jit_allocation, intptr_t delta)
WriteBarrierPromise RelocateFromDesc(WritableJitAllocation &jit_allocation, Heap *heap, const CodeDesc &desc, Address constant_pool, const DisallowGarbageCollection &no_gc)
static constexpr int SizeFor(int body_size)
Tagged< TrustedByteArray > relocation_info() const
Tagged< TrustedByteArray > unchecked_relocation_info() const
static V8_INLINE Tagged< InstructionStream > Initialize(Tagged< HeapObject > self, Tagged< Map > map, uint32_t body_size, int constant_pool_offset, Tagged< TrustedByteArray > reloc_info)
static constexpr int kHeaderSize
Handle< Code > code
#define ISTREAM_FIELDS(V)
constexpr int kIntSize
Definition globals.h:400
constexpr intptr_t kCodeAlignment
Definition globals.h:964
#define DECL_VERIFIER(Name)
#define NEVER_READ_ONLY_SPACE
#define DECL_PRIMITIVE_GETTER(name, type)
#define DECL_PRINTER(Name)
#define V8_NOEXCEPT
constexpr T RoundUp(T x, intptr_t m)
Definition macros.h:387
#define DEFINE_FIELD_OFFSET_CONSTANTS(StartOffset, LIST_MACRO)
Definition utils.h:242
#define V8_INLINE
Definition v8config.h:500
#define V8_NODISCARD
Definition v8config.h:693