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/parsing/preparse-data.h" 9#include "src/snapshot/serializer.h" 10 11namespace v8 { 12namespace internal { 13 14class CodeSerializer : public Serializer { 15 public: 16 static ScriptData* Serialize(Isolate* isolate, 17 Handle<SharedFunctionInfo> info, 18 Handle<String> source); 19 20 ScriptData* Serialize(Handle<HeapObject> obj); 21 22 MUST_USE_RESULT static MaybeHandle<SharedFunctionInfo> Deserialize( 23 Isolate* isolate, ScriptData* cached_data, Handle<String> source); 24 25 const List<uint32_t>* stub_keys() const { return &stub_keys_; } 26 27 uint32_t source_hash() const { return source_hash_; } 28 29 protected: 30 explicit CodeSerializer(Isolate* isolate, uint32_t source_hash) 31 : Serializer(isolate), source_hash_(source_hash) {} 32 ~CodeSerializer() override { OutputStatistics("CodeSerializer"); } 33 34 virtual void SerializeCodeObject(Code* code_object, HowToCode how_to_code, 35 WhereToPoint where_to_point) { 36 UNREACHABLE(); 37 } 38 39 virtual bool ElideObject(Object* obj) { return false; } 40 void SerializeGeneric(HeapObject* heap_object, HowToCode how_to_code, 41 WhereToPoint where_to_point); 42 43 private: 44 void SerializeObject(HeapObject* o, HowToCode how_to_code, 45 WhereToPoint where_to_point, int skip) override; 46 47 void SerializeBuiltin(int builtin_index, HowToCode how_to_code, 48 WhereToPoint where_to_point); 49 void SerializeCodeStub(Code* code_stub, HowToCode how_to_code, 50 WhereToPoint where_to_point); 51 52 DisallowHeapAllocation no_gc_; 53 uint32_t source_hash_; 54 List<uint32_t> stub_keys_; 55 DISALLOW_COPY_AND_ASSIGN(CodeSerializer); 56}; 57 58class WasmCompiledModuleSerializer : public CodeSerializer { 59 public: 60 static std::unique_ptr<ScriptData> SerializeWasmModule( 61 Isolate* isolate, Handle<FixedArray> compiled_module); 62 static MaybeHandle<FixedArray> DeserializeWasmModule( 63 Isolate* isolate, ScriptData* data, Vector<const byte> wire_bytes); 64 65 protected: 66 void SerializeCodeObject(Code* code_object, HowToCode how_to_code, 67 WhereToPoint where_to_point) override { 68 Code::Kind kind = code_object->kind(); 69 if (kind == Code::WASM_FUNCTION || kind == Code::WASM_TO_JS_FUNCTION || 70 kind == Code::JS_TO_WASM_FUNCTION) { 71 SerializeGeneric(code_object, how_to_code, where_to_point); 72 } else { 73 UNREACHABLE(); 74 } 75 } 76 77 bool ElideObject(Object* obj) override { 78 return obj->IsWeakCell() || obj->IsForeign(); 79 }; 80 81 private: 82 WasmCompiledModuleSerializer(Isolate* isolate, uint32_t source_hash) 83 : CodeSerializer(isolate, source_hash) {} 84 DISALLOW_COPY_AND_ASSIGN(WasmCompiledModuleSerializer); 85}; 86 87// Wrapper around ScriptData to provide code-serializer-specific functionality. 88class SerializedCodeData : public SerializedData { 89 public: 90 enum SanityCheckResult { 91 CHECK_SUCCESS = 0, 92 MAGIC_NUMBER_MISMATCH = 1, 93 VERSION_MISMATCH = 2, 94 SOURCE_MISMATCH = 3, 95 CPU_FEATURES_MISMATCH = 4, 96 FLAGS_MISMATCH = 5, 97 CHECKSUM_MISMATCH = 6, 98 INVALID_HEADER = 7 99 }; 100 101 // The data header consists of uint32_t-sized entries: 102 // [0] magic number and external reference count 103 // [1] version hash 104 // [2] source hash 105 // [3] cpu features 106 // [4] flag hash 107 // [5] number of code stub keys 108 // [6] number of reservation size entries 109 // [7] payload length 110 // [8] payload checksum part 1 111 // [9] payload checksum part 2 112 // ... reservations 113 // ... code stub keys 114 // ... serialized payload 115 static const int kVersionHashOffset = kMagicNumberOffset + kInt32Size; 116 static const int kSourceHashOffset = kVersionHashOffset + kInt32Size; 117 static const int kCpuFeaturesOffset = kSourceHashOffset + kInt32Size; 118 static const int kFlagHashOffset = kCpuFeaturesOffset + kInt32Size; 119 static const int kNumReservationsOffset = kFlagHashOffset + kInt32Size; 120 static const int kNumCodeStubKeysOffset = kNumReservationsOffset + kInt32Size; 121 static const int kPayloadLengthOffset = kNumCodeStubKeysOffset + kInt32Size; 122 static const int kChecksum1Offset = kPayloadLengthOffset + kInt32Size; 123 static const int kChecksum2Offset = kChecksum1Offset + kInt32Size; 124 static const int kHeaderSize = kChecksum2Offset + kInt32Size; 125 126 // Used when consuming. 127 static const SerializedCodeData FromCachedData( 128 Isolate* isolate, ScriptData* cached_data, uint32_t expected_source_hash, 129 SanityCheckResult* rejection_result); 130 131 // Used when producing. 132 SerializedCodeData(const List<byte>* payload, const CodeSerializer* cs); 133 134 // Return ScriptData object and relinquish ownership over it to the caller. 135 ScriptData* GetScriptData(); 136 137 Vector<const Reservation> Reservations() const; 138 Vector<const byte> Payload() const; 139 140 Vector<const uint32_t> CodeStubKeys() const; 141 142 static uint32_t SourceHash(Handle<String> source); 143 144 private: 145 explicit SerializedCodeData(ScriptData* data); 146 SerializedCodeData(const byte* data, int size) 147 : SerializedData(const_cast<byte*>(data), size) {} 148 149 Vector<const byte> DataWithoutHeader() const { 150 return Vector<const byte>(data_ + kHeaderSize, size_ - kHeaderSize); 151 } 152 153 SanityCheckResult SanityCheck(Isolate* isolate, 154 uint32_t expected_source_hash) const; 155}; 156 157} // namespace internal 158} // namespace v8 159 160#endif // V8_SNAPSHOT_CODE_SERIALIZER_H_ 161