// Copyright 2006-2008 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_SNAPSHOT_H_
|
#define V8_SNAPSHOT_SNAPSHOT_H_
|
|
#include "src/snapshot/partial-serializer.h"
|
#include "src/snapshot/startup-serializer.h"
|
|
#include "src/utils.h"
|
|
namespace v8 {
|
namespace internal {
|
|
// Forward declarations.
|
class Isolate;
|
class BuiltinSerializer;
|
class PartialSerializer;
|
class StartupSerializer;
|
|
// Wrapper around reservation sizes and the serialization payload.
|
class SnapshotData : public SerializedData {
|
public:
|
// Used when producing.
|
template <class AllocatorT>
|
explicit SnapshotData(const Serializer<AllocatorT>* serializer);
|
|
// Used when consuming.
|
explicit SnapshotData(const Vector<const byte> snapshot)
|
: SerializedData(const_cast<byte*>(snapshot.begin()), snapshot.length()) {
|
}
|
|
std::vector<Reservation> Reservations() const;
|
virtual Vector<const byte> Payload() const;
|
|
Vector<const byte> RawData() const {
|
return Vector<const byte>(data_, size_);
|
}
|
|
protected:
|
// The data header consists of uint32_t-sized entries:
|
// [0] magic number and (internal) external reference count
|
// [1] number of reservation size entries
|
// [2] payload length
|
// ... reservations
|
// ... serialized payload
|
static const uint32_t kNumReservationsOffset =
|
kMagicNumberOffset + kUInt32Size;
|
static const uint32_t kPayloadLengthOffset =
|
kNumReservationsOffset + kUInt32Size;
|
static const uint32_t kHeaderSize = kPayloadLengthOffset + kUInt32Size;
|
};
|
|
class BuiltinSnapshotData final : public SnapshotData {
|
public:
|
// Used when producing.
|
// This simply forwards to the SnapshotData constructor.
|
// The BuiltinSerializer appends the builtin offset table to the payload.
|
explicit BuiltinSnapshotData(const BuiltinSerializer* serializer);
|
|
// Used when consuming.
|
explicit BuiltinSnapshotData(const Vector<const byte> snapshot)
|
: SnapshotData(snapshot) {
|
}
|
|
// Returns the serialized payload without the builtin offsets table.
|
Vector<const byte> Payload() const override;
|
|
// Returns only the builtin offsets table.
|
Vector<const uint32_t> BuiltinOffsets() const;
|
|
private:
|
// In addition to the format specified in SnapshotData, BuiltinsSnapshotData
|
// includes a list of builtin at the end of the serialized payload:
|
//
|
// ...
|
// ... serialized payload
|
// ... list of builtins offsets
|
};
|
|
class EmbeddedData final {
|
public:
|
static EmbeddedData FromIsolate(Isolate* isolate);
|
static EmbeddedData FromBlob();
|
|
const uint8_t* data() const { return data_; }
|
uint32_t size() const { return size_; }
|
|
void Dispose() { delete[] data_; }
|
|
Address InstructionStartOfBuiltin(int i) const;
|
uint32_t InstructionSizeOfBuiltin(int i) const;
|
|
bool ContainsBuiltin(int i) const { return InstructionSizeOfBuiltin(i) > 0; }
|
|
// Padded with kCodeAlignment.
|
uint32_t PaddedInstructionSizeOfBuiltin(int i) const {
|
return PadAndAlign(InstructionSizeOfBuiltin(i));
|
}
|
|
size_t CreateHash() const;
|
size_t Hash() const {
|
return *reinterpret_cast<const size_t*>(data_ + HashOffset());
|
}
|
|
struct Metadata {
|
// Blob layout information.
|
uint32_t instructions_offset;
|
uint32_t instructions_length;
|
};
|
STATIC_ASSERT(offsetof(Metadata, instructions_offset) == 0);
|
STATIC_ASSERT(offsetof(Metadata, instructions_length) == kUInt32Size);
|
STATIC_ASSERT(sizeof(Metadata) == kUInt32Size + kUInt32Size);
|
|
// The layout of the blob is as follows:
|
//
|
// [0] hash of the remaining blob
|
// [1] metadata of instruction stream 0
|
// ... metadata
|
// ... instruction streams
|
|
static constexpr uint32_t kTableSize = Builtins::builtin_count;
|
static constexpr uint32_t HashOffset() { return 0; }
|
static constexpr uint32_t HashSize() { return kSizetSize; }
|
static constexpr uint32_t MetadataOffset() {
|
return HashOffset() + HashSize();
|
}
|
static constexpr uint32_t MetadataSize() {
|
return sizeof(struct Metadata) * kTableSize;
|
}
|
static constexpr uint32_t RawDataOffset() {
|
return PadAndAlign(MetadataOffset() + MetadataSize());
|
}
|
|
private:
|
EmbeddedData(const uint8_t* data, uint32_t size) : data_(data), size_(size) {}
|
|
const Metadata* Metadata() const {
|
return reinterpret_cast<const struct Metadata*>(data_ + MetadataOffset());
|
}
|
const uint8_t* RawData() const { return data_ + RawDataOffset(); }
|
|
static constexpr int PadAndAlign(int size) {
|
// Ensure we have at least one byte trailing the actual builtin
|
// instructions which we can later fill with int3.
|
return RoundUp<kCodeAlignment>(size + 1);
|
}
|
|
void PrintStatistics() const;
|
|
const uint8_t* data_;
|
uint32_t size_;
|
};
|
|
class Snapshot : public AllStatic {
|
public:
|
// ---------------- Deserialization ----------------
|
|
// Initialize the Isolate from the internal snapshot. Returns false if no
|
// snapshot could be found.
|
static bool Initialize(Isolate* isolate);
|
|
// Create a new context using the internal partial snapshot.
|
static MaybeHandle<Context> NewContextFromSnapshot(
|
Isolate* isolate, Handle<JSGlobalProxy> global_proxy,
|
size_t context_index,
|
v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer);
|
|
// Deserializes a single given builtin code object. Intended to be called at
|
// runtime after the isolate (and the builtins table) has been fully
|
// initialized.
|
static Code* DeserializeBuiltin(Isolate* isolate, int builtin_id);
|
static void EnsureAllBuiltinsAreDeserialized(Isolate* isolate);
|
static Code* EnsureBuiltinIsDeserialized(Isolate* isolate,
|
Handle<SharedFunctionInfo> shared);
|
|
// Deserializes a single given handler code object. Intended to be called at
|
// runtime after the isolate has been fully initialized.
|
static Code* DeserializeHandler(Isolate* isolate,
|
interpreter::Bytecode bytecode,
|
interpreter::OperandScale operand_scale);
|
|
// ---------------- Helper methods ----------------
|
|
static bool HasContextSnapshot(Isolate* isolate, size_t index);
|
static bool EmbedsScript(Isolate* isolate);
|
|
// To be implemented by the snapshot source.
|
static const v8::StartupData* DefaultSnapshotBlob();
|
|
// ---------------- Serialization ----------------
|
|
static v8::StartupData CreateSnapshotBlob(
|
const SnapshotData* startup_snapshot,
|
const BuiltinSnapshotData* builtin_snapshot,
|
const std::vector<SnapshotData*>& context_snapshots,
|
bool can_be_rehashed);
|
|
#ifdef DEBUG
|
static bool SnapshotIsValid(const v8::StartupData* snapshot_blob);
|
#endif // DEBUG
|
|
private:
|
static uint32_t ExtractNumContexts(const v8::StartupData* data);
|
static uint32_t ExtractContextOffset(const v8::StartupData* data,
|
uint32_t index);
|
static bool ExtractRehashability(const v8::StartupData* data);
|
static Vector<const byte> ExtractStartupData(const v8::StartupData* data);
|
static Vector<const byte> ExtractBuiltinData(const v8::StartupData* data);
|
static Vector<const byte> ExtractContextData(const v8::StartupData* data,
|
uint32_t index);
|
|
static uint32_t GetHeaderValue(const v8::StartupData* data, uint32_t offset) {
|
return ReadLittleEndianValue<uint32_t>(
|
reinterpret_cast<Address>(data->data) + offset);
|
}
|
static void SetHeaderValue(char* data, uint32_t offset, uint32_t value) {
|
WriteLittleEndianValue(reinterpret_cast<Address>(data) + offset, value);
|
}
|
|
static void CheckVersion(const v8::StartupData* data);
|
|
// Snapshot blob layout:
|
// [0] number of contexts N
|
// [1] rehashability
|
// [2] (128 bytes) version string
|
// [3] offset to builtins
|
// [4] offset to context 0
|
// [5] offset to context 1
|
// ...
|
// ... offset to context N - 1
|
// ... startup snapshot data
|
// ... builtin snapshot data
|
// ... context 0 snapshot data
|
// ... context 1 snapshot data
|
|
static const uint32_t kNumberOfContextsOffset = 0;
|
// TODO(yangguo): generalize rehashing, and remove this flag.
|
static const uint32_t kRehashabilityOffset =
|
kNumberOfContextsOffset + kUInt32Size;
|
static const uint32_t kVersionStringOffset =
|
kRehashabilityOffset + kUInt32Size;
|
static const uint32_t kVersionStringLength = 64;
|
static const uint32_t kBuiltinOffsetOffset =
|
kVersionStringOffset + kVersionStringLength;
|
static const uint32_t kFirstContextOffsetOffset =
|
kBuiltinOffsetOffset + kUInt32Size;
|
|
static uint32_t StartupSnapshotOffset(int num_contexts) {
|
return kFirstContextOffsetOffset + num_contexts * kInt32Size;
|
}
|
|
static uint32_t ContextSnapshotOffsetOffset(int index) {
|
return kFirstContextOffsetOffset + index * kInt32Size;
|
}
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot);
|
};
|
|
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
|
void SetSnapshotFromFile(StartupData* snapshot_blob);
|
#endif
|
|
} // namespace internal
|
} // namespace v8
|
|
#endif // V8_SNAPSHOT_SNAPSHOT_H_
|