• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
9 #include "src/builtins/builtins.h"
10 #include "src/common/globals.h"
11 #include "src/execution/isolate.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 class Code;
17 class Isolate;
18 
19 // Wraps an off-heap instruction stream.
20 // TODO(jgruber,v8:6666): Remove this class.
21 class InstructionStream final : public AllStatic {
22  public:
23   // Returns true, iff the given pc points into an off-heap instruction stream.
24   static bool PcIsOffHeap(Isolate* isolate, Address pc);
25 
26   // Returns the corresponding Code object if it exists, and nullptr otherwise.
27   static Code TryLookupCode(Isolate* isolate, Address address);
28 
29   // During snapshot creation, we first create an executable off-heap area
30   // containing all off-heap code. The area is guaranteed to be contiguous.
31   // Note that this only applies when building the snapshot, e.g. for
32   // mksnapshot. Otherwise, off-heap code is embedded directly into the binary.
33   static void CreateOffHeapInstructionStream(Isolate* isolate, uint8_t** code,
34                                              uint32_t* code_size,
35                                              uint8_t** data,
36                                              uint32_t* data_size);
37   static void FreeOffHeapInstructionStream(uint8_t* code, uint32_t code_size,
38                                            uint8_t* data, uint32_t data_size);
39 };
40 
41 class EmbeddedData final {
42  public:
43   static EmbeddedData FromIsolate(Isolate* isolate);
44 
FromBlob()45   static EmbeddedData FromBlob() {
46     return EmbeddedData(Isolate::CurrentEmbeddedBlobCode(),
47                         Isolate::CurrentEmbeddedBlobCodeSize(),
48                         Isolate::CurrentEmbeddedBlobData(),
49                         Isolate::CurrentEmbeddedBlobDataSize());
50   }
51 
FromBlob(Isolate * isolate)52   static EmbeddedData FromBlob(Isolate* isolate) {
53     return EmbeddedData(
54         isolate->embedded_blob_code(), isolate->embedded_blob_code_size(),
55         isolate->embedded_blob_data(), isolate->embedded_blob_data_size());
56   }
57 
code()58   const uint8_t* code() const { return code_; }
code_size()59   uint32_t code_size() const { return code_size_; }
data()60   const uint8_t* data() const { return data_; }
data_size()61   uint32_t data_size() const { return data_size_; }
62 
Dispose()63   void Dispose() {
64     delete[] code_;
65     code_ = nullptr;
66     delete[] data_;
67     data_ = nullptr;
68   }
69 
70   Address InstructionStartOfBuiltin(int i) const;
71   uint32_t InstructionSizeOfBuiltin(int i) const;
72 
73   Address InstructionStartOfBytecodeHandlers() const;
74   Address InstructionEndOfBytecodeHandlers() const;
75 
76   Address MetadataStartOfBuiltin(int i) const;
77   uint32_t MetadataSizeOfBuiltin(int i) const;
78 
AddressForHashing(Address addr)79   uint32_t AddressForHashing(Address addr) {
80     Address start = reinterpret_cast<Address>(code_);
81     DCHECK(base::IsInRange(addr, start, start + code_size_));
82     return static_cast<uint32_t>(addr - start);
83   }
84 
85   // Padded with kCodeAlignment.
86   // TODO(v8:11045): Consider removing code alignment.
PaddedInstructionSizeOfBuiltin(int i)87   uint32_t PaddedInstructionSizeOfBuiltin(int i) const {
88     uint32_t size = InstructionSizeOfBuiltin(i);
89     CHECK_NE(size, 0);
90     return PadAndAlignCode(size);
91   }
92 
93   size_t CreateEmbeddedBlobDataHash() const;
94   size_t CreateEmbeddedBlobCodeHash() const;
EmbeddedBlobDataHash()95   size_t EmbeddedBlobDataHash() const {
96     return *reinterpret_cast<const size_t*>(data_ +
97                                             EmbeddedBlobDataHashOffset());
98   }
EmbeddedBlobCodeHash()99   size_t EmbeddedBlobCodeHash() const {
100     return *reinterpret_cast<const size_t*>(data_ +
101                                             EmbeddedBlobCodeHashOffset());
102   }
103 
IsolateHash()104   size_t IsolateHash() const {
105     return *reinterpret_cast<const size_t*>(data_ + IsolateHashOffset());
106   }
107 
108   // Blob layout information for a single instruction stream. Corresponds
109   // roughly to Code object layout (see the instruction and metadata area).
110   struct LayoutDescription {
111     // The offset and (unpadded) length of this builtin's instruction area
112     // from the start of the embedded code section.
113     uint32_t instruction_offset;
114     uint32_t instruction_length;
115     // The offset and (unpadded) length of this builtin's metadata area
116     // from the start of the embedded code section.
117     uint32_t metadata_offset;
118     uint32_t metadata_length;
119   };
120   STATIC_ASSERT(offsetof(LayoutDescription, instruction_offset) ==
121                 0 * kUInt32Size);
122   STATIC_ASSERT(offsetof(LayoutDescription, instruction_length) ==
123                 1 * kUInt32Size);
124   STATIC_ASSERT(offsetof(LayoutDescription, metadata_offset) ==
125                 2 * kUInt32Size);
126   STATIC_ASSERT(offsetof(LayoutDescription, metadata_length) ==
127                 3 * kUInt32Size);
128   STATIC_ASSERT(sizeof(LayoutDescription) == 4 * kUInt32Size);
129 
130   // The layout of the blob is as follows:
131   //
132   // data:
133   // [0] hash of the data section
134   // [1] hash of the code section
135   // [2] hash of embedded-blob-relevant heap objects
136   // [3] layout description of instruction stream 0
137   // ... layout descriptions
138   // [x] metadata section of builtin 0
139   // ... metadata sections
140   //
141   // code:
142   // [0] instruction section of builtin 0
143   // ... instruction sections
144 
145   static constexpr uint32_t kTableSize = Builtins::builtin_count;
EmbeddedBlobDataHashOffset()146   static constexpr uint32_t EmbeddedBlobDataHashOffset() { return 0; }
EmbeddedBlobDataHashSize()147   static constexpr uint32_t EmbeddedBlobDataHashSize() { return kSizetSize; }
EmbeddedBlobCodeHashOffset()148   static constexpr uint32_t EmbeddedBlobCodeHashOffset() {
149     return EmbeddedBlobDataHashOffset() + EmbeddedBlobDataHashSize();
150   }
EmbeddedBlobCodeHashSize()151   static constexpr uint32_t EmbeddedBlobCodeHashSize() { return kSizetSize; }
IsolateHashOffset()152   static constexpr uint32_t IsolateHashOffset() {
153     return EmbeddedBlobCodeHashOffset() + EmbeddedBlobCodeHashSize();
154   }
IsolateHashSize()155   static constexpr uint32_t IsolateHashSize() { return kSizetSize; }
LayoutDescriptionTableOffset()156   static constexpr uint32_t LayoutDescriptionTableOffset() {
157     return IsolateHashOffset() + IsolateHashSize();
158   }
LayoutDescriptionTableSize()159   static constexpr uint32_t LayoutDescriptionTableSize() {
160     return sizeof(struct LayoutDescription) * kTableSize;
161   }
FixedDataSize()162   static constexpr uint32_t FixedDataSize() {
163     return LayoutDescriptionTableOffset() + LayoutDescriptionTableSize();
164   }
165   // The variable-size data section starts here.
RawMetadataOffset()166   static constexpr uint32_t RawMetadataOffset() { return FixedDataSize(); }
167 
168   // Code is in its own dedicated section.
RawCodeOffset()169   static constexpr uint32_t RawCodeOffset() { return 0; }
170 
171  private:
EmbeddedData(const uint8_t * code,uint32_t code_size,const uint8_t * data,uint32_t data_size)172   EmbeddedData(const uint8_t* code, uint32_t code_size, const uint8_t* data,
173                uint32_t data_size)
174       : code_(code), code_size_(code_size), data_(data), data_size_(data_size) {
175     DCHECK_NOT_NULL(code);
176     DCHECK_LT(0, code_size);
177     DCHECK_NOT_NULL(data);
178     DCHECK_LT(0, data_size);
179   }
180 
RawCode()181   const uint8_t* RawCode() const { return code_ + RawCodeOffset(); }
182 
LayoutDescription()183   const LayoutDescription* LayoutDescription() const {
184     return reinterpret_cast<const struct LayoutDescription*>(
185         data_ + LayoutDescriptionTableOffset());
186   }
RawMetadata()187   const uint8_t* RawMetadata() const { return data_ + RawMetadataOffset(); }
188 
PadAndAlignCode(int size)189   static constexpr int PadAndAlignCode(int size) {
190     // Ensure we have at least one byte trailing the actual builtin
191     // instructions which we can later fill with int3.
192     return RoundUp<kCodeAlignment>(size + 1);
193   }
PadAndAlignData(int size)194   static constexpr int PadAndAlignData(int size) {
195     // Ensure we have at least one byte trailing the actual builtin
196     // instructions which we can later fill with int3.
197     return RoundUp<Code::kMetadataAlignment>(size);
198   }
199 
200   void PrintStatistics() const;
201 
202   // The code section contains instruction streams. It is guaranteed to have
203   // execute permissions, and may have read permissions.
204   const uint8_t* code_;
205   uint32_t code_size_;
206 
207   // The data section contains both descriptions of the code section (hashes,
208   // offsets, sizes) and metadata describing Code objects (see
209   // Code::MetadataStart()). It is guaranteed to have read permissions.
210   const uint8_t* data_;
211   uint32_t data_size_;
212 };
213 
214 }  // namespace internal
215 }  // namespace v8
216 
217 #endif  // V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_
218