[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:
jgruber 2017-08-28 16:12:55 +02:00 committed by Commit Bot
parent 47037bdc6c
commit 89b6ef0cdb
11 changed files with 105 additions and 23 deletions

View File

@ -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);

View File

@ -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());

View File

@ -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

View File

@ -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) {

View File

@ -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);
};

View File

@ -272,7 +272,7 @@ class SerializedData {
other.owns_data_ = false;
}
~SerializedData() {
virtual ~SerializedData() {
if (owns_data_) DeleteArray<byte>(data_);
}

View File

@ -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

View File

@ -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_; }

View File

@ -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);

View File

@ -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

View File

@ -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());