Reland "[snapshot] include version string in the startup snapshot."

This is a reland of 629406d1e9
Original change's description:
> [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/684295
> Reviewed-by: Michael Achenbach <machenbach@chromium.org>
> Commit-Queue: Yang Guo <yangguo@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#48161}

Bug: chromium:764327
Change-Id: I3721689824e0a6909eede86d0829dc258ae40c4d
Reviewed-on: https://chromium-review.googlesource.com/684494
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48164}
This commit is contained in:
Yang Guo 2017-09-26 12:41:20 +02:00 committed by Commit Bot
parent 8f2977a3c6
commit dc7b2b2ba7
6 changed files with 43 additions and 45 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -27,19 +27,11 @@ const char* Version::version_string_ = V8_VERSION_STRING;
// Calculate the V8 version string.
void Version::GetString(Vector<char> str) {
const char* candidate = IsCandidate() ? " (candidate)" : "";
#ifdef USE_SIMULATOR
const char* is_simulator = " SIMULATOR";
#else
const char* is_simulator = "";
#endif // USE_SIMULATOR
if (GetPatch() > 0) {
SNPrintF(str, "%d.%d.%d.%d%s%s",
GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate,
is_simulator);
SNPrintF(str, "%d.%d.%d.%d%s", GetMajor(), GetMinor(), GetBuild(),
GetPatch(), candidate);
} else {
SNPrintF(str, "%d.%d.%d%s%s",
GetMajor(), GetMinor(), GetBuild(), candidate,
is_simulator);
SNPrintF(str, "%d.%d.%d%s", GetMajor(), GetMinor(), GetBuild(), candidate);
}
}

View File

@ -69,20 +69,6 @@ static void CheckVersion(int major, int minor, int build,
TEST(VersionString) {
#ifdef USE_SIMULATOR
CheckVersion(0, 0, 0, 0, false, "0.0.0 SIMULATOR", "libv8-0.0.0.so");
CheckVersion(0, 0, 0, 0, true,
"0.0.0 (candidate) SIMULATOR", "libv8-0.0.0-candidate.so");
CheckVersion(1, 0, 0, 0, false, "1.0.0 SIMULATOR", "libv8-1.0.0.so");
CheckVersion(1, 0, 0, 0, true,
"1.0.0 (candidate) SIMULATOR", "libv8-1.0.0-candidate.so");
CheckVersion(1, 0, 0, 1, false, "1.0.0.1 SIMULATOR", "libv8-1.0.0.1.so");
CheckVersion(1, 0, 0, 1, true,
"1.0.0.1 (candidate) SIMULATOR", "libv8-1.0.0.1-candidate.so");
CheckVersion(2, 5, 10, 7, false, "2.5.10.7 SIMULATOR", "libv8-2.5.10.7.so");
CheckVersion(2, 5, 10, 7, true,
"2.5.10.7 (candidate) SIMULATOR", "libv8-2.5.10.7-candidate.so");
#else
CheckVersion(0, 0, 0, 0, false, "0.0.0", "libv8-0.0.0.so");
CheckVersion(0, 0, 0, 0, true,
"0.0.0 (candidate)", "libv8-0.0.0-candidate.so");
@ -95,7 +81,6 @@ TEST(VersionString) {
CheckVersion(2, 5, 10, 7, false, "2.5.10.7", "libv8-2.5.10.7.so");
CheckVersion(2, 5, 10, 7, true,
"2.5.10.7 (candidate)", "libv8-2.5.10.7-candidate.so");
#endif
}
} // namespace internal