[snapshot] Store builtin offsets during serialization
To deserialize builtins individually, we need to preserve their starting offsets within the serialized data. Bug: v8:6624 Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng Change-Id: I48a48330aeb63de2c8cfcbea6fb94e1b2917495c Reviewed-on: https://chromium-review.googlesource.com/637774 Reviewed-by: Yang Guo <yangguo@chromium.org> Commit-Queue: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#47708}
This commit is contained in:
parent
47037bdc6c
commit
89b6ef0cdb
@ -740,7 +740,7 @@ StartupData SnapshotCreator::CreateBlob(
|
||||
can_be_rehashed = can_be_rehashed && startup_serializer.can_be_rehashed();
|
||||
|
||||
i::SnapshotData startup_snapshot(&startup_serializer);
|
||||
i::SnapshotData builtin_snapshot(&builtin_serializer);
|
||||
i::BuiltinSnapshotData builtin_snapshot(&builtin_serializer);
|
||||
StartupData result = i::Snapshot::CreateSnapshotBlob(
|
||||
&startup_snapshot, &builtin_snapshot, context_snapshots, can_be_rehashed);
|
||||
|
||||
|
@ -9,6 +9,12 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
BuiltinDeserializer::BuiltinDeserializer(const BuiltinSnapshotData* data)
|
||||
: Deserializer(data, false) {
|
||||
builtin_offsets_ = data->BuiltinOffsets();
|
||||
DCHECK(std::is_sorted(builtin_offsets_.begin(), builtin_offsets_.end()));
|
||||
}
|
||||
|
||||
void BuiltinDeserializer::DeserializeAllBuiltins() {
|
||||
DCHECK(!AllowHeapAllocation::IsAllowed());
|
||||
|
||||
|
@ -10,13 +10,12 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class SnapshotData;
|
||||
class BuiltinSnapshotData;
|
||||
|
||||
// Deserializes the builtins blob.
|
||||
class BuiltinDeserializer final : public Deserializer {
|
||||
public:
|
||||
explicit BuiltinDeserializer(const SnapshotData* data)
|
||||
: Deserializer(data, false) {}
|
||||
explicit BuiltinDeserializer(const BuiltinSnapshotData* data);
|
||||
|
||||
// Expose Deserializer::Initialize.
|
||||
using Deserializer::Initialize;
|
||||
@ -29,6 +28,11 @@ class BuiltinDeserializer final : public Deserializer {
|
||||
// pre-startup deserialization, and builtins must be deserialized at exactly
|
||||
// the right point during startup deserialization.
|
||||
void DeserializeAllBuiltins();
|
||||
|
||||
private:
|
||||
// The offsets of each builtin within the serialized data. Equivalent to
|
||||
// BuiltinSerializer::builtin_offsets_ but on the deserialization side.
|
||||
Vector<const uint32_t> builtin_offsets_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -19,16 +19,23 @@ BuiltinSerializer::~BuiltinSerializer() {
|
||||
}
|
||||
|
||||
void BuiltinSerializer::SerializeBuiltins() {
|
||||
isolate()->builtins()->IterateBuiltins(this);
|
||||
for (int i = 0; i < Builtins::builtin_count; i++) {
|
||||
Code* code = isolate()->builtins()->builtin(static_cast<Builtins::Name>(i));
|
||||
builtin_offsets_[i] = sink()->Position();
|
||||
SerializeBuiltin(code);
|
||||
}
|
||||
Pad(); // Pad with kNop since GetInt() might read too far.
|
||||
|
||||
// Append the offset table. During deserialization, the offset table is
|
||||
// extracted by BuiltinSnapshotData.
|
||||
const byte* data = reinterpret_cast<const byte*>(&builtin_offsets_[0]);
|
||||
int data_length = static_cast<int>(sizeof(builtin_offsets_));
|
||||
sink_.PutRaw(data, data_length, "BuiltinOffsets");
|
||||
}
|
||||
|
||||
void BuiltinSerializer::VisitRootPointers(Root root, Object** start,
|
||||
Object** end) {
|
||||
for (Object** current = start; current < end; current++) {
|
||||
Code* code = Code::cast(*current);
|
||||
SerializeBuiltin(code);
|
||||
}
|
||||
Pad(); // Pad with kNop since GetInt() might read too far.
|
||||
UNREACHABLE(); // We iterate manually in SerializeBuiltins.
|
||||
}
|
||||
|
||||
void BuiltinSerializer::SerializeBuiltin(Code* code) {
|
||||
|
@ -29,8 +29,15 @@ class BuiltinSerializer : public Serializer {
|
||||
void SerializeObject(HeapObject* o, HowToCode how_to_code,
|
||||
WhereToPoint where_to_point, int skip) override;
|
||||
|
||||
// The startup serializer is needed for access to the partial snapshot cache,
|
||||
// which is used to serialize things like embedded constants.
|
||||
StartupSerializer* startup_serializer_;
|
||||
|
||||
// Stores the starting offset, within the serialized data, of each builtin.
|
||||
// This is later packed into the builtin snapshot, and used by the builtin
|
||||
// deserializer to deserialize individual builtins.
|
||||
uint32_t builtin_offsets_[Builtins::builtin_count];
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BuiltinSerializer);
|
||||
};
|
||||
|
||||
|
@ -272,7 +272,7 @@ class SerializedData {
|
||||
other.owns_data_ = false;
|
||||
}
|
||||
|
||||
~SerializedData() {
|
||||
virtual ~SerializedData() {
|
||||
if (owns_data_) DeleteArray<byte>(data_);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "src/api.h"
|
||||
#include "src/base/platform/platform.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/snapshot/builtin-serializer.h"
|
||||
#include "src/snapshot/partial-deserializer.h"
|
||||
#include "src/snapshot/snapshot-source-sink.h"
|
||||
#include "src/snapshot/startup-deserializer.h"
|
||||
@ -42,7 +43,7 @@ bool Snapshot::Initialize(Isolate* isolate) {
|
||||
Vector<const byte> startup_data = ExtractStartupData(blob);
|
||||
SnapshotData startup_snapshot_data(startup_data);
|
||||
Vector<const byte> builtin_data = ExtractBuiltinData(blob);
|
||||
SnapshotData builtin_snapshot_data(builtin_data);
|
||||
BuiltinSnapshotData builtin_snapshot_data(builtin_data);
|
||||
StartupDeserializer deserializer(&startup_snapshot_data,
|
||||
&builtin_snapshot_data);
|
||||
deserializer.SetRehashability(ExtractRehashability(blob));
|
||||
@ -108,7 +109,8 @@ void ProfileDeserialization(
|
||||
}
|
||||
|
||||
v8::StartupData Snapshot::CreateSnapshotBlob(
|
||||
const SnapshotData* startup_snapshot, const SnapshotData* builtin_snapshot,
|
||||
const SnapshotData* startup_snapshot,
|
||||
const BuiltinSnapshotData* builtin_snapshot,
|
||||
const std::vector<SnapshotData*>& context_snapshots, bool can_be_rehashed) {
|
||||
uint32_t num_contexts = static_cast<uint32_t>(context_snapshots.size());
|
||||
uint32_t startup_snapshot_offset = StartupSnapshotOffset(num_contexts);
|
||||
@ -288,5 +290,32 @@ Vector<const byte> SnapshotData::Payload() const {
|
||||
return Vector<const byte>(payload, length);
|
||||
}
|
||||
|
||||
BuiltinSnapshotData::BuiltinSnapshotData(const BuiltinSerializer* serializer)
|
||||
: SnapshotData(serializer) {}
|
||||
|
||||
Vector<const byte> BuiltinSnapshotData::Payload() const {
|
||||
uint32_t reservations_size =
|
||||
GetHeaderValue(kNumReservationsOffset) * kUInt32Size;
|
||||
const byte* payload = data_ + kHeaderSize + reservations_size;
|
||||
int builtin_offsets_size = Builtins::builtin_count * kUInt32Size;
|
||||
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
|
||||
DCHECK_EQ(data_ + size_, payload + payload_length);
|
||||
DCHECK_GT(payload_length, builtin_offsets_size);
|
||||
return Vector<const byte>(payload, payload_length - builtin_offsets_size);
|
||||
}
|
||||
|
||||
Vector<const uint32_t> BuiltinSnapshotData::BuiltinOffsets() const {
|
||||
uint32_t reservations_size =
|
||||
GetHeaderValue(kNumReservationsOffset) * kUInt32Size;
|
||||
const byte* payload = data_ + kHeaderSize + reservations_size;
|
||||
int builtin_offsets_size = Builtins::builtin_count * kUInt32Size;
|
||||
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
|
||||
DCHECK_EQ(data_ + size_, payload + payload_length);
|
||||
DCHECK_GT(payload_length, builtin_offsets_size);
|
||||
const uint32_t* data = reinterpret_cast<const uint32_t*>(
|
||||
payload + payload_length - builtin_offsets_size);
|
||||
return Vector<const uint32_t>(data, Builtins::builtin_count);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -95,7 +95,7 @@ class SnapshotByteSink {
|
||||
|
||||
void PutInt(uintptr_t integer, const char* description);
|
||||
void PutRaw(const byte* data, int number_of_bytes, const char* description);
|
||||
int Position() { return static_cast<int>(data_.size()); }
|
||||
int Position() const { return static_cast<int>(data_.size()); }
|
||||
|
||||
const std::vector<byte>* data() const { return &data_; }
|
||||
|
||||
|
@ -15,6 +15,7 @@ namespace internal {
|
||||
|
||||
// Forward declarations.
|
||||
class Isolate;
|
||||
class BuiltinSerializer;
|
||||
class PartialSerializer;
|
||||
class StartupSerializer;
|
||||
|
||||
@ -31,13 +32,13 @@ class SnapshotData : public SerializedData {
|
||||
}
|
||||
|
||||
Vector<const Reservation> Reservations() const;
|
||||
Vector<const byte> Payload() const;
|
||||
virtual Vector<const byte> Payload() const;
|
||||
|
||||
Vector<const byte> RawData() const {
|
||||
return Vector<const byte>(data_, size_);
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool IsSane();
|
||||
|
||||
// The data header consists of uint32_t-sized entries:
|
||||
@ -55,6 +56,34 @@ class SnapshotData : public SerializedData {
|
||||
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) {
|
||||
CHECK(IsSane());
|
||||
}
|
||||
|
||||
// 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 Snapshot : public AllStatic {
|
||||
public:
|
||||
// Initialize the Isolate from the internal snapshot. Returns false if no
|
||||
@ -75,7 +104,7 @@ class Snapshot : public AllStatic {
|
||||
|
||||
static v8::StartupData CreateSnapshotBlob(
|
||||
const SnapshotData* startup_snapshot,
|
||||
const SnapshotData* builtin_snapshot,
|
||||
const BuiltinSnapshotData* builtin_snapshot,
|
||||
const std::vector<SnapshotData*>& context_snapshots,
|
||||
bool can_be_rehashed);
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace internal {
|
||||
class StartupDeserializer final : public Deserializer {
|
||||
public:
|
||||
StartupDeserializer(const SnapshotData* startup_data,
|
||||
const SnapshotData* builtin_data)
|
||||
const BuiltinSnapshotData* builtin_data)
|
||||
: Deserializer(startup_data, false), builtin_data_(builtin_data) {}
|
||||
|
||||
// Deserialize the snapshot into an empty heap.
|
||||
@ -28,7 +28,7 @@ class StartupDeserializer final : public Deserializer {
|
||||
// Rehash after deserializing an isolate.
|
||||
void Rehash();
|
||||
|
||||
const SnapshotData* builtin_data_;
|
||||
const BuiltinSnapshotData* builtin_data_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -132,7 +132,7 @@ static StartupBlobs Serialize(v8::Isolate* isolate) {
|
||||
|
||||
ser.SerializeWeakReferencesAndDeferred();
|
||||
SnapshotData startup_snapshot(&ser);
|
||||
SnapshotData builtin_snapshot(&builtin_serializer);
|
||||
BuiltinSnapshotData builtin_snapshot(&builtin_serializer);
|
||||
return {WritePayload(startup_snapshot.RawData()),
|
||||
WritePayload(builtin_snapshot.RawData())};
|
||||
}
|
||||
@ -158,7 +158,7 @@ v8::Isolate* InitializeFromBlob(StartupBlobs& blobs) {
|
||||
v8::Isolate* v8_isolate = NULL;
|
||||
{
|
||||
SnapshotData startup_snapshot(blobs.startup);
|
||||
SnapshotData builtin_snapshot(blobs.builtin);
|
||||
BuiltinSnapshotData builtin_snapshot(blobs.builtin);
|
||||
StartupDeserializer deserializer(&startup_snapshot, &builtin_snapshot);
|
||||
TestIsolate* isolate = new TestIsolate(false);
|
||||
v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
|
||||
@ -372,7 +372,7 @@ static void PartiallySerializeContext(Vector<const byte>* startup_blob_out,
|
||||
startup_serializer.SerializeWeakReferencesAndDeferred();
|
||||
|
||||
SnapshotData startup_snapshot(&startup_serializer);
|
||||
SnapshotData builtin_snapshot(&builtin_serializer);
|
||||
BuiltinSnapshotData builtin_snapshot(&builtin_serializer);
|
||||
SnapshotData partial_snapshot(&partial_serializer);
|
||||
|
||||
*partial_blob_out = WritePayload(partial_snapshot.RawData());
|
||||
@ -496,7 +496,7 @@ static void PartiallySerializeCustomContext(
|
||||
startup_serializer.SerializeWeakReferencesAndDeferred();
|
||||
|
||||
SnapshotData startup_snapshot(&startup_serializer);
|
||||
SnapshotData builtin_snapshot(&builtin_serializer);
|
||||
BuiltinSnapshotData builtin_snapshot(&builtin_serializer);
|
||||
SnapshotData partial_snapshot(&partial_serializer);
|
||||
|
||||
*partial_blob_out = WritePayload(partial_snapshot.RawData());
|
||||
|
Loading…
Reference in New Issue
Block a user