1 // Copyright 2016 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_CODE_SERIALIZER_H_ 6 #define V8_SNAPSHOT_CODE_SERIALIZER_H_ 7 8 #include "src/base/macros.h" 9 #include "src/snapshot/serializer.h" 10 #include "src/snapshot/snapshot-data.h" 11 12 namespace v8 { 13 namespace internal { 14 15 class PersistentHandles; 16 17 class V8_EXPORT_PRIVATE AlignedCachedData { 18 public: 19 AlignedCachedData(const byte* data, int length); ~AlignedCachedData()20 ~AlignedCachedData() { 21 if (owns_data_) DeleteArray(data_); 22 } 23 AlignedCachedData(const AlignedCachedData&) = delete; 24 AlignedCachedData& operator=(const AlignedCachedData&) = delete; 25 data()26 const byte* data() const { return data_; } length()27 int length() const { return length_; } rejected()28 bool rejected() const { return rejected_; } 29 Reject()30 void Reject() { rejected_ = true; } 31 HasDataOwnership()32 bool HasDataOwnership() const { return owns_data_; } 33 AcquireDataOwnership()34 void AcquireDataOwnership() { 35 DCHECK(!owns_data_); 36 owns_data_ = true; 37 } 38 ReleaseDataOwnership()39 void ReleaseDataOwnership() { 40 DCHECK(owns_data_); 41 owns_data_ = false; 42 } 43 44 private: 45 bool owns_data_ : 1; 46 bool rejected_ : 1; 47 const byte* data_; 48 int length_; 49 }; 50 51 enum class SerializedCodeSanityCheckResult { 52 kSuccess = 0, 53 kMagicNumberMismatch = 1, 54 kVersionMismatch = 2, 55 kSourceMismatch = 3, 56 kFlagsMismatch = 5, 57 kChecksumMismatch = 6, 58 kInvalidHeader = 7, 59 kLengthMismatch = 8 60 }; 61 62 class CodeSerializer : public Serializer { 63 public: 64 struct OffThreadDeserializeData { 65 private: 66 friend class CodeSerializer; 67 MaybeHandle<SharedFunctionInfo> maybe_result; 68 std::vector<Handle<Script>> scripts; 69 std::unique_ptr<PersistentHandles> persistent_handles; 70 SerializedCodeSanityCheckResult sanity_check_result; 71 }; 72 73 CodeSerializer(const CodeSerializer&) = delete; 74 CodeSerializer& operator=(const CodeSerializer&) = delete; 75 V8_EXPORT_PRIVATE static ScriptCompiler::CachedData* Serialize( 76 Handle<SharedFunctionInfo> info); 77 78 AlignedCachedData* SerializeSharedFunctionInfo( 79 Handle<SharedFunctionInfo> info); 80 81 V8_WARN_UNUSED_RESULT static MaybeHandle<SharedFunctionInfo> Deserialize( 82 Isolate* isolate, AlignedCachedData* cached_data, Handle<String> source, 83 ScriptOriginOptions origin_options); 84 85 V8_WARN_UNUSED_RESULT static OffThreadDeserializeData 86 StartDeserializeOffThread(LocalIsolate* isolate, 87 AlignedCachedData* cached_data); 88 89 V8_WARN_UNUSED_RESULT static MaybeHandle<SharedFunctionInfo> 90 FinishOffThreadDeserialize(Isolate* isolate, OffThreadDeserializeData&& data, 91 AlignedCachedData* cached_data, 92 Handle<String> source, 93 ScriptOriginOptions origin_options); 94 source_hash()95 uint32_t source_hash() const { return source_hash_; } 96 97 protected: 98 CodeSerializer(Isolate* isolate, uint32_t source_hash); ~CodeSerializer()99 ~CodeSerializer() override { OutputStatistics("CodeSerializer"); } 100 ElideObject(Object obj)101 virtual bool ElideObject(Object obj) { return false; } 102 void SerializeGeneric(Handle<HeapObject> heap_object); 103 104 private: 105 void SerializeObjectImpl(Handle<HeapObject> o) override; 106 107 bool SerializeReadOnlyObject(HeapObject obj, 108 const DisallowGarbageCollection& no_gc); 109 110 DISALLOW_GARBAGE_COLLECTION(no_gc_) 111 uint32_t source_hash_; 112 }; 113 114 // Wrapper around ScriptData to provide code-serializer-specific functionality. 115 class SerializedCodeData : public SerializedData { 116 public: 117 // The data header consists of uint32_t-sized entries: 118 // [0] magic number and (internally provided) external reference count 119 // [1] version hash 120 // [2] source hash 121 // [3] flag hash 122 // [4] payload length 123 // [5] payload checksum 124 // ... serialized payload 125 static const uint32_t kVersionHashOffset = kMagicNumberOffset + kUInt32Size; 126 static const uint32_t kSourceHashOffset = kVersionHashOffset + kUInt32Size; 127 static const uint32_t kFlagHashOffset = kSourceHashOffset + kUInt32Size; 128 static const uint32_t kPayloadLengthOffset = kFlagHashOffset + kUInt32Size; 129 static const uint32_t kChecksumOffset = kPayloadLengthOffset + kUInt32Size; 130 static const uint32_t kUnalignedHeaderSize = kChecksumOffset + kUInt32Size; 131 static const uint32_t kHeaderSize = POINTER_SIZE_ALIGN(kUnalignedHeaderSize); 132 133 // Used when consuming. 134 static SerializedCodeData FromCachedData( 135 AlignedCachedData* cached_data, uint32_t expected_source_hash, 136 SerializedCodeSanityCheckResult* rejection_result); 137 // For cached data which is consumed before the source is available (e.g. 138 // off-thread). 139 static SerializedCodeData FromCachedDataWithoutSource( 140 AlignedCachedData* cached_data, 141 SerializedCodeSanityCheckResult* rejection_result); 142 // For cached data which was previously already sanity checked by 143 // FromCachedDataWithoutSource. The rejection result from that call should be 144 // passed into this one. 145 static SerializedCodeData FromPartiallySanityCheckedCachedData( 146 AlignedCachedData* cached_data, uint32_t expected_source_hash, 147 SerializedCodeSanityCheckResult* rejection_result); 148 149 // Used when producing. 150 SerializedCodeData(const std::vector<byte>* payload, 151 const CodeSerializer* cs); 152 153 // Return ScriptData object and relinquish ownership over it to the caller. 154 AlignedCachedData* GetScriptData(); 155 156 base::Vector<const byte> Payload() const; 157 158 static uint32_t SourceHash(Handle<String> source, 159 ScriptOriginOptions origin_options); 160 161 private: 162 explicit SerializedCodeData(AlignedCachedData* data); 163 SerializedCodeData(const byte* data, int size) 164 : SerializedData(const_cast<byte*>(data), size) {} 165 166 base::Vector<const byte> ChecksummedContent() const { 167 return base::Vector<const byte>(data_ + kHeaderSize, size_ - kHeaderSize); 168 } 169 170 SerializedCodeSanityCheckResult SanityCheck( 171 uint32_t expected_source_hash) const; 172 SerializedCodeSanityCheckResult SanityCheckJustSource( 173 uint32_t expected_source_hash) const; 174 SerializedCodeSanityCheckResult SanityCheckWithoutSource() const; 175 }; 176 177 } // namespace internal 178 } // namespace v8 179 180 #endif // V8_SNAPSHOT_CODE_SERIALIZER_H_ 181