Commit 629406d1 authored by Yang Guo's avatar Yang Guo Committed by Commit Bot

[snapshot] include version string in the startup snapshot.

This is to easier diagnose build issues involving the snapshot.
Sample error message for mismatching snapshot:

#
# Fatal error in ../../src/snapshot/snapshot-common.cc, line 286
# Version mismatch between V8 binary and snapshot.
#   V8 binary version: 6.3.1 (candidate)
#    Snapshot version: 6.3.0 (candidate)
# The snapshot consists of 2820444 bytes and contains 1 contexts.
#


R=machenbach@chromium.org

Bug: chromium:764327
Change-Id: Icdc7aeac77819b113985b424feda814a072d5406
Reviewed-on: https://chromium-review.googlesource.com/684295Reviewed-by: 's avatarMichael Achenbach <machenbach@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48161}
parent 7f9de3dc
......@@ -102,6 +102,7 @@ class SerializedCodeData : public SerializedData {
// ... 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;
......
......@@ -290,7 +290,6 @@ class SerializedData {
}
static const uint32_t kMagicNumberOffset = 0;
static const uint32_t kVersionHashOffset = kMagicNumberOffset + kUInt32Size;
protected:
void SetHeaderValue(uint32_t offset, uint32_t value) {
......
......@@ -41,6 +41,7 @@ bool Snapshot::Initialize(Isolate* isolate) {
if (FLAG_profile_deserialization) timer.Start();
const v8::StartupData* blob = isolate->snapshot_blob();
CheckVersion(blob);
Vector<const byte> startup_data = ExtractStartupData(blob);
SnapshotData startup_snapshot_data(startup_data);
Vector<const byte> builtin_data = ExtractBuiltinData(blob);
......@@ -155,6 +156,11 @@ v8::StartupData Snapshot::CreateSnapshotBlob(
SetHeaderValue(data, kNumberOfContextsOffset, num_contexts);
SetHeaderValue(data, kRehashabilityOffset, can_be_rehashed ? 1 : 0);
// Write version string into snapshot data.
memset(data + kVersionStringOffset, 0, kVersionStringLength);
Version::GetString(
Vector<char>(data + kVersionStringOffset, kVersionStringLength));
// Startup snapshot (isolate-specific data).
uint32_t payload_offset = startup_snapshot_offset;
uint32_t payload_length =
......@@ -269,6 +275,25 @@ Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data,
return Vector<const byte>(context_data, context_length);
}
void Snapshot::CheckVersion(const v8::StartupData* data) {
char version[kVersionStringLength];
memset(version, 0, kVersionStringLength);
CHECK_LT(kVersionStringOffset + kVersionStringLength,
static_cast<uint32_t>(data->raw_size));
Version::GetString(Vector<char>(version, kVersionStringLength));
if (memcmp(version, data->data + kVersionStringOffset,
kVersionStringLength) != 0) {
V8_Fatal(__FILE__, __LINE__,
"Version mismatch between V8 binary and snapshot.\n"
"# V8 binary version: %.*s\n"
"# Snapshot version: %.*s\n"
"# The snapshot consists of %d bytes and contains %d context(s).",
kVersionStringLength, version, kVersionStringLength,
data->data + kVersionStringOffset, data->raw_size,
ExtractNumContexts(data));
}
}
template <class AllocatorT>
SnapshotData::SnapshotData(const Serializer<AllocatorT>* serializer) {
DisallowHeapAllocation no_gc;
......@@ -286,7 +311,6 @@ SnapshotData::SnapshotData(const Serializer<AllocatorT>* serializer) {
// Set header values.
SetMagicNumber(serializer->isolate());
SetHeaderValue(kVersionHashOffset, Version::Hash());
SetHeaderValue(kNumReservationsOffset, static_cast<int>(reservations.size()));
SetHeaderValue(kPayloadLengthOffset, static_cast<int>(payload->size()));
......@@ -303,10 +327,6 @@ SnapshotData::SnapshotData(const Serializer<AllocatorT>* serializer) {
template SnapshotData::SnapshotData(
const Serializer<DefaultSerializerAllocator>* serializer);
bool SnapshotData::IsSane() {
return GetHeaderValue(kVersionHashOffset) == Version::Hash();
}
Vector<const SerializedData::Reservation> SnapshotData::Reservations() const {
return Vector<const Reservation>(
reinterpret_cast<const Reservation*>(data_ + kHeaderSize),
......
......@@ -29,7 +29,6 @@ class SnapshotData : public SerializedData {
// Used when consuming.
explicit SnapshotData(const Vector<const byte> snapshot)
: SerializedData(const_cast<byte*>(snapshot.begin()), snapshot.length()) {
CHECK(IsSane());
}
Vector<const Reservation> Reservations() const;
......@@ -40,18 +39,14 @@ class SnapshotData : public SerializedData {
}
protected:
bool IsSane();
// The data header consists of uint32_t-sized entries:
// [0] magic number and (internal) external reference count
// [1] API-provided external reference count
// [2] version hash
// [3] number of reservation size entries
// [4] payload length
// [1] number of reservation size entries
// [2] payload length
// ... reservations
// ... serialized payload
static const uint32_t kNumReservationsOffset =
kVersionHashOffset + kUInt32Size;
kMagicNumberOffset + kUInt32Size;
static const uint32_t kPayloadLengthOffset =
kNumReservationsOffset + kUInt32Size;
static const uint32_t kHeaderSize = kPayloadLengthOffset + kUInt32Size;
......@@ -67,7 +62,6 @@ class BuiltinSnapshotData final : public SnapshotData {
// Used when consuming.
explicit BuiltinSnapshotData(const Vector<const byte> snapshot)
: SnapshotData(snapshot) {
CHECK(IsSane());
}
// Returns the serialized payload without the builtin offsets table.
......@@ -141,12 +135,15 @@ class Snapshot : public AllStatic {
WriteLittleEndianValue(data + offset, value);
}
static void CheckVersion(const v8::StartupData* data);
// Snapshot blob layout:
// [0] number of contexts N
// [1] rehashability
// [2] offset to builtins
// [3] offset to context 0
// [4] offset to context 1
// [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
......@@ -158,7 +155,11 @@ class Snapshot : public AllStatic {
// TODO(yangguo): generalize rehashing, and remove this flag.
static const uint32_t kRehashabilityOffset =
kNumberOfContextsOffset + kUInt32Size;
static const int kBuiltinOffsetOffset = kRehashabilityOffset + 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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment