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