v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
embedded-data.h
Go to the documentation of this file.
1// Copyright 2018 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_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_
6#define V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_
7
8#include "src/base/macros.h"
10#include "src/common/globals.h"
12#include "src/heap/code-range.h"
14
15namespace v8 {
16namespace internal {
17
18class InstructionStream;
19class Isolate;
20
21using ReorderedBuiltinIndex = uint32_t;
22
23// Wraps an off-heap instruction stream.
24// TODO(jgruber,v8:6666): Remove this class.
25class OffHeapInstructionStream final : public AllStatic {
26 public:
27 // Returns true, iff the given pc points into an off-heap instruction stream.
28 static bool PcIsOffHeap(Isolate* isolate, Address pc);
29
30 // If the address belongs to the embedded code blob, predictably converts it
31 // to uint32 by calculating offset from the embedded code blob start and
32 // returns true, and false otherwise.
33 static bool TryGetAddressForHashing(Isolate* isolate, Address address,
34 uint32_t* hashable_address);
35
36 // Returns the corresponding builtin ID if lookup succeeds, and kNoBuiltinId
37 // otherwise.
38 static Builtin TryLookupCode(Isolate* isolate, Address address);
39
40 // During snapshot creation, we first create an executable off-heap area
41 // containing all off-heap code. The area is guaranteed to be contiguous.
42 // Note that this only applies when building the snapshot, e.g. for
43 // mksnapshot. Otherwise, off-heap code is embedded directly into the binary.
45 uint8_t** code,
46 uint32_t* code_size,
47 uint8_t** data,
48 uint32_t* data_size);
49 static void FreeOffHeapOffHeapInstructionStream(uint8_t* code,
50 uint32_t code_size,
51 uint8_t* data,
52 uint32_t data_size);
53};
54
55class EmbeddedData final {
56 public:
57 // Create the embedded blob from the given Isolate's heap state.
58 static EmbeddedData NewFromIsolate(Isolate* isolate);
59
60 // Returns the global embedded blob (usually physically located in .text and
61 // .rodata).
68
69 // Returns a potentially remapped embedded blob (see also
70 // MaybeRemapEmbeddedBuiltinsIntoCodeRange).
71 static EmbeddedData FromBlob(Isolate* isolate) {
72 return EmbeddedData(
73 isolate->embedded_blob_code(), isolate->embedded_blob_code_size(),
74 isolate->embedded_blob_data(), isolate->embedded_blob_data_size());
75 }
76
77 // Returns a potentially remapped embedded blob (see also
78 // MaybeRemapEmbeddedBuiltinsIntoCodeRange).
85
86 // When short builtin calls optimization is enabled for the Isolate, there
87 // will be two builtins instruction streams executed: the embedded one and
88 // the one un-embedded into the per-Isolate code range. In most of the cases,
89 // the per-Isolate instructions will be used but in some cases (like builtin
90 // calls from Wasm) the embedded instruction stream could be used. If the
91 // requested PC belongs to the embedded code blob - it'll be returned, and
92 // the per-Isolate blob otherwise.
93 // See http://crbug.com/v8/11527 for details.
95 Address maybe_builtin_pc) {
97 if (d.IsInCodeRange(maybe_builtin_pc)) return d;
98 if (isolate->is_short_builtin_calls_enabled()) {
100 // If the pc does not belong to the embedded code blob we should be using
101 // the un-embedded one.
102 if (global_d.IsInCodeRange(maybe_builtin_pc)) return global_d;
103 }
104#if defined(V8_COMPRESS_POINTERS_IN_SHARED_CAGE) && \
105 defined(V8_SHORT_BUILTIN_CALLS)
106 // When shared pointer compression cage is enabled and it has the embedded
107 // code blob copy then it could have been used regardless of whether the
108 // isolate uses it or knows about it or not (see
109 // InstructionStream::OffHeapInstructionStart()).
110 // So, this blob has to be checked too.
112 if (code_range && code_range->embedded_blob_code_copy() != nullptr) {
113 EmbeddedData remapped_d = EmbeddedData::FromBlob(code_range);
114 // If the pc does not belong to the embedded code blob we should be
115 // using the un-embedded one.
116 if (remapped_d.IsInCodeRange(maybe_builtin_pc)) return remapped_d;
117 }
118#endif // defined(V8_COMPRESS_POINTERS_IN_SHARED_CAGE) &&
119 // defined(V8_SHORT_BUILTIN_CALLS)
120 return d;
121 }
122
123 const uint8_t* code() const { return code_; }
124 uint32_t code_size() const { return code_size_; }
125 const uint8_t* data() const { return data_; }
126 uint32_t data_size() const { return data_size_; }
127
129 Address start = reinterpret_cast<Address>(code_);
130 return (start <= pc) && (pc < start + code_size_);
131 }
132
133 void Dispose() {
134 delete[] code_;
135 code_ = nullptr;
136 delete[] data_;
137 data_ = nullptr;
138 }
139
140 inline Address InstructionStartOf(Builtin builtin) const;
141 inline Address InstructionEndOf(Builtin builtin) const;
142 inline uint32_t InstructionSizeOf(Builtin builtin) const;
145 inline Address MetadataStartOf(Builtin builtin) const;
146
147 uint32_t AddressForHashing(Address addr) {
148 DCHECK(IsInCodeRange(addr));
149 Address start = reinterpret_cast<Address>(code_);
150 return static_cast<uint32_t>(addr - start);
151 }
152
153 // Padded with kCodeAlignment.
154 inline uint32_t PaddedInstructionSizeOf(Builtin builtin) const;
155
156 size_t CreateEmbeddedBlobDataHash() const;
157 size_t CreateEmbeddedBlobCodeHash() const;
158 size_t EmbeddedBlobDataHash() const {
159 return *reinterpret_cast<const size_t*>(data_ +
161 }
162 size_t EmbeddedBlobCodeHash() const {
163 return *reinterpret_cast<const size_t*>(data_ +
165 }
166
167 size_t IsolateHash() const {
168 return *reinterpret_cast<const size_t*>(data_ + IsolateHashOffset());
169 }
170
171 Builtin TryLookupCode(Address address) const;
172
173 // Blob layout information for a single instruction stream.
175 // The offset and (unpadded) length of this builtin's instruction area
176 // from the start of the embedded code section.
179 // The offset of this builtin's metadata area from the start of the
180 // embedded data section.
182 };
183 static_assert(offsetof(LayoutDescription, instruction_offset) ==
184 0 * kUInt32Size);
185 static_assert(offsetof(LayoutDescription, instruction_length) ==
186 1 * kUInt32Size);
187 static_assert(offsetof(LayoutDescription, metadata_offset) ==
188 2 * kUInt32Size);
189
190 // The embedded code section stores builtins in the so-called
191 // 'embedded snapshot order' which is usually different from the order
192 // as defined by the Builtins enum ('builtin id order'), and determined
193 // through an algorithm based on collected execution profiles. The
194 // BuiltinLookupEntry struct maps from the 'embedded snapshot order' to
195 // the 'builtin id order' and additionally keeps a copy of instruction_end for
196 // each builtin since it is convenient for binary search.
198 // The end offset (including padding) of builtin, the end_offset field
199 // should be in ascending order in the array in snapshot, because we will
200 // use it in TryLookupCode. It should be equal to
201 // LayoutDescription[builtin_id].instruction_offset +
202 // PadAndAlignCode(length)
203 uint32_t end_offset;
204 // The id of builtin.
205 uint32_t builtin_id;
206 };
207 static_assert(offsetof(BuiltinLookupEntry, end_offset) == 0 * kUInt32Size);
208 static_assert(offsetof(BuiltinLookupEntry, builtin_id) == 1 * kUInt32Size);
209
210 Builtin GetBuiltinId(ReorderedBuiltinIndex embedded_index) const;
211
212 // The layout of the blob is as follows:
213 //
214 // data:
215 // [0] hash of the data section
216 // [1] hash of the code section
217 // [2] hash of embedded-blob-relevant heap objects
218 // [3] layout description of builtin 0
219 // ... layout descriptions (builtin id order)
220 // [n] builtin lookup table where entries are sorted by offset_end in
221 // ascending order. (embedded snapshot order)
222 // [x] metadata section of builtin 0
223 // ... metadata sections (builtin id order)
224 //
225 // code:
226 // [0] instruction section of builtin 0
227 // ... instruction sections (embedded snapshot order)
228
229 static constexpr uint32_t kTableSize = Builtins::kBuiltinCount;
230 static constexpr uint32_t EmbeddedBlobDataHashOffset() { return 0; }
231 static constexpr uint32_t EmbeddedBlobDataHashSize() { return kSizetSize; }
232 static constexpr uint32_t EmbeddedBlobCodeHashOffset() {
234 }
235 static constexpr uint32_t EmbeddedBlobCodeHashSize() { return kSizetSize; }
236 static constexpr uint32_t IsolateHashOffset() {
238 }
239 static constexpr uint32_t IsolateHashSize() { return kSizetSize; }
240 static constexpr uint32_t LayoutDescriptionTableOffset() {
242 }
243 static constexpr uint32_t LayoutDescriptionTableSize() {
244 return sizeof(struct LayoutDescription) * kTableSize;
245 }
246 static constexpr uint32_t BuiltinLookupEntryTableOffset() {
248 }
249 static constexpr uint32_t BuiltinLookupEntryTableSize() {
250 return sizeof(struct BuiltinLookupEntry) * kTableSize;
251 }
252 static constexpr uint32_t FixedDataSize() {
254 }
255 // The variable-size data section starts here.
256 static constexpr uint32_t RawMetadataOffset() { return FixedDataSize(); }
257
258 // Code is in its own dedicated section.
259 static constexpr uint32_t RawCodeOffset() { return 0; }
260
261 private:
262 EmbeddedData(const uint8_t* code, uint32_t code_size, const uint8_t* data,
263 uint32_t data_size)
265 DCHECK_NOT_NULL(code);
267 DCHECK_NOT_NULL(data);
269 }
270
271 const uint8_t* RawCode() const { return code_ + RawCodeOffset(); }
272
274 const struct LayoutDescription* descs =
275 reinterpret_cast<const struct LayoutDescription*>(
277 return descs[static_cast<int>(builtin)];
278 }
279
281 ReorderedBuiltinIndex index) const {
282 const struct BuiltinLookupEntry* entries =
283 reinterpret_cast<const struct BuiltinLookupEntry*>(
285 return entries + index;
286 }
287
288 const uint8_t* RawMetadata() const { return data_ + RawMetadataOffset(); }
289
290 static constexpr int PadAndAlignCode(int size) {
291 // Ensure we have at least one byte trailing the actual builtin
292 // instructions which we can later fill with int3.
293 return RoundUp<kCodeAlignment>(size + 1);
294 }
295 static constexpr int PadAndAlignData(int size) {
296 // Ensure we have at least one byte trailing the actual builtin
297 // instructions which we can later fill with int3.
299 }
300
301 void PrintStatistics() const;
302
303 // The code section contains instruction streams. It is guaranteed to have
304 // execute permissions, and may have read permissions.
305 const uint8_t* code_;
306 uint32_t code_size_;
307
308 // The data section contains both descriptions of the code section (hashes,
309 // offsets, sizes) and metadata describing InstructionStream objects (see
310 // InstructionStream::MetadataStart()). It is guaranteed to have read
311 // permissions.
312 const uint8_t* data_;
313 uint32_t data_size_;
314};
315
316} // namespace internal
317} // namespace v8
318
319#endif // V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_
static constexpr int kBuiltinCount
Definition builtins.h:105
uint8_t * embedded_blob_code_copy() const
Definition code-range.h:83
Address InstructionEndOf(Builtin builtin) const
const uint8_t * code() const
const LayoutDescription & LayoutDescription(Builtin builtin) const
static constexpr uint32_t FixedDataSize()
static EmbeddedData NewFromIsolate(Isolate *isolate)
EmbeddedData(const uint8_t *code, uint32_t code_size, const uint8_t *data, uint32_t data_size)
bool IsInCodeRange(Address pc) const
const BuiltinLookupEntry * BuiltinLookupEntry(ReorderedBuiltinIndex index) const
Address InstructionStartOf(Builtin builtin) const
static constexpr uint32_t BuiltinLookupEntryTableOffset()
Address MetadataStartOf(Builtin builtin) const
size_t EmbeddedBlobCodeHash() const
uint32_t InstructionSizeOf(Builtin builtin) const
uint32_t PaddedInstructionSizeOf(Builtin builtin) const
size_t EmbeddedBlobDataHash() const
static EmbeddedData FromBlob()
static constexpr uint32_t LayoutDescriptionTableSize()
static constexpr uint32_t EmbeddedBlobDataHashOffset()
static constexpr uint32_t EmbeddedBlobCodeHashOffset()
const uint8_t * data() const
static EmbeddedData FromBlob(Isolate *isolate)
size_t CreateEmbeddedBlobDataHash() const
Address InstructionEndOfBytecodeHandlers() const
static constexpr uint32_t IsolateHashOffset()
static constexpr uint32_t LayoutDescriptionTableOffset()
static EmbeddedData FromBlobForPc(Isolate *isolate, Address maybe_builtin_pc)
size_t CreateEmbeddedBlobCodeHash() const
Address InstructionStartOfBytecodeHandlers() const
static constexpr uint32_t RawMetadataOffset()
uint32_t AddressForHashing(Address addr)
static constexpr int PadAndAlignCode(int size)
static constexpr uint32_t BuiltinLookupEntryTableSize()
const uint8_t * RawCode() const
static EmbeddedData FromBlob(CodeRange *code_range)
Builtin TryLookupCode(Address address) const
Builtin GetBuiltinId(ReorderedBuiltinIndex embedded_index) const
static constexpr uint32_t kTableSize
static constexpr uint32_t IsolateHashSize()
static constexpr uint32_t EmbeddedBlobCodeHashSize()
const uint8_t * RawMetadata() const
static constexpr uint32_t EmbeddedBlobDataHashSize()
static constexpr int PadAndAlignData(int size)
static constexpr uint32_t RawCodeOffset()
static IsolateGroup * current()
CodeRange * GetCodeRange() const
static const uint8_t * CurrentEmbeddedBlobCode()
Definition isolate.cc:395
static uint32_t CurrentEmbeddedBlobCodeSize()
Definition isolate.cc:400
static const uint8_t * CurrentEmbeddedBlobData()
Definition isolate.cc:405
static uint32_t CurrentEmbeddedBlobDataSize()
Definition isolate.cc:410
static void FreeOffHeapOffHeapInstructionStream(uint8_t *code, uint32_t code_size, uint8_t *data, uint32_t data_size)
static bool TryGetAddressForHashing(Isolate *isolate, Address address, uint32_t *hashable_address)
static void CreateOffHeapOffHeapInstructionStream(Isolate *isolate, uint8_t **code, uint32_t *code_size, uint8_t **data, uint32_t *data_size)
static Builtin TryLookupCode(Isolate *isolate, Address address)
static bool PcIsOffHeap(Isolate *isolate, Address pc)
int start
Builtin builtin
ZoneVector< Entry > entries
uint32_t ReorderedBuiltinIndex
constexpr int kUInt32Size
Definition globals.h:403
constexpr int kSizetSize
Definition globals.h:404
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
constexpr T RoundUp(T x, intptr_t m)
Definition macros.h:387