// Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_SNAPSHOT_CODE_SERIALIZER_H_ #define V8_SNAPSHOT_CODE_SERIALIZER_H_ #include "src/snapshot/serializer.h" namespace v8 { namespace internal { class ScriptData { public: ScriptData(const byte* data, int length); ~ScriptData() { if (owns_data_) DeleteArray(data_); } const byte* data() const { return data_; } int length() const { return length_; } bool rejected() const { return rejected_; } void Reject() { rejected_ = true; } void AcquireDataOwnership() { DCHECK(!owns_data_); owns_data_ = true; } void ReleaseDataOwnership() { DCHECK(owns_data_); owns_data_ = false; } private: bool owns_data_ : 1; bool rejected_ : 1; const byte* data_; int length_; DISALLOW_COPY_AND_ASSIGN(ScriptData); }; class CodeSerializer : public Serializer<> { public: static ScriptCompiler::CachedData* Serialize(Handle info); ScriptData* SerializeSharedFunctionInfo(Handle info); V8_WARN_UNUSED_RESULT static MaybeHandle Deserialize( Isolate* isolate, ScriptData* cached_data, Handle source, ScriptOriginOptions origin_options); const std::vector* stub_keys() const { return &stub_keys_; } uint32_t source_hash() const { return source_hash_; } protected: CodeSerializer(Isolate* isolate, uint32_t source_hash); ~CodeSerializer() override { OutputStatistics("CodeSerializer"); } virtual void SerializeCodeObject(Code* code_object, HowToCode how_to_code, WhereToPoint where_to_point) { UNREACHABLE(); } virtual bool ElideObject(Object* obj) { return false; } void SerializeGeneric(HeapObject* heap_object, HowToCode how_to_code, WhereToPoint where_to_point); private: void SerializeObject(HeapObject* o, HowToCode how_to_code, WhereToPoint where_to_point, int skip) override; void SerializeCodeStub(Code* code_stub, HowToCode how_to_code, WhereToPoint where_to_point); bool SerializeReadOnlyObject(HeapObject* obj, HowToCode how_to_code, WhereToPoint where_to_point, int skip); DisallowHeapAllocation no_gc_; uint32_t source_hash_; std::vector stub_keys_; DISALLOW_COPY_AND_ASSIGN(CodeSerializer); }; // Wrapper around ScriptData to provide code-serializer-specific functionality. class SerializedCodeData : public SerializedData { public: enum SanityCheckResult { CHECK_SUCCESS = 0, MAGIC_NUMBER_MISMATCH = 1, VERSION_MISMATCH = 2, SOURCE_MISMATCH = 3, CPU_FEATURES_MISMATCH = 4, FLAGS_MISMATCH = 5, CHECKSUM_MISMATCH = 6, INVALID_HEADER = 7, LENGTH_MISMATCH = 8 }; // The data header consists of uint32_t-sized entries: // [0] magic number and (internally provided) external reference count // [1] extra (API-provided) external reference count // [2] version hash // [3] source hash // [4] cpu features // [5] flag hash // [6] number of code stub keys // [7] number of reservation size entries // [8] payload length // [9] payload checksum part 1 // [10] payload checksum part 2 // ... reservations // ... code stub keys // ... serialized payload static const uint32_t kVersionHashOffset = kMagicNumberOffset + kUInt32Size; static const uint32_t kSourceHashOffset = kVersionHashOffset + kUInt32Size; static const uint32_t kCpuFeaturesOffset = kSourceHashOffset + kUInt32Size; static const uint32_t kFlagHashOffset = kCpuFeaturesOffset + kUInt32Size; static const uint32_t kNumReservationsOffset = kFlagHashOffset + kUInt32Size; static const uint32_t kNumCodeStubKeysOffset = kNumReservationsOffset + kUInt32Size; static const uint32_t kPayloadLengthOffset = kNumCodeStubKeysOffset + kUInt32Size; static const uint32_t kChecksum1Offset = kPayloadLengthOffset + kUInt32Size; static const uint32_t kChecksum2Offset = kChecksum1Offset + kUInt32Size; static const uint32_t kUnalignedHeaderSize = kChecksum2Offset + kUInt32Size; static const uint32_t kHeaderSize = POINTER_SIZE_ALIGN(kUnalignedHeaderSize); // Used when consuming. static SerializedCodeData FromCachedData(Isolate* isolate, ScriptData* cached_data, uint32_t expected_source_hash, SanityCheckResult* rejection_result); // Used when producing. SerializedCodeData(const std::vector* payload, const CodeSerializer* cs); // Return ScriptData object and relinquish ownership over it to the caller. ScriptData* GetScriptData(); std::vector Reservations() const; Vector Payload() const; Vector CodeStubKeys() const; static uint32_t SourceHash(Handle source, ScriptOriginOptions origin_options); private: explicit SerializedCodeData(ScriptData* data); SerializedCodeData(const byte* data, int size) : SerializedData(const_cast(data), size) {} Vector DataWithoutHeader() const { return Vector(data_ + kHeaderSize, size_ - kHeaderSize); } SanityCheckResult SanityCheck(Isolate* isolate, uint32_t expected_source_hash) const; }; } // namespace internal } // namespace v8 #endif // V8_SNAPSHOT_CODE_SERIALIZER_H_