Changing checksum implementation to use zlib's adler32
adler32 is strictly faster than the old checksum - see this doc: https://docs.google.com/document/d/1fFhuShavlUwf0FqTc-6L3XLYbAVe0DhpmHSv4oenZL8/edit?pli=1#heading=h.ojvfq6akbz5f adler32 also no longer requires alignment to be maintained. Bug: chromium:833361 Change-Id: I3dbfa699b712aa908c87e6f8261756a4a1209df4 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1925562 Commit-Queue: Sam Maier <smaier@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#65160}
This commit is contained in:
parent
5f14396489
commit
082e56fe5a
2
BUILD.gn
2
BUILD.gn
@ -3301,6 +3301,8 @@ v8_source_set("v8_base_without_compiler") {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deps += [ "//third_party/zlib" ]
|
||||||
|
|
||||||
if (v8_postmortem_support) {
|
if (v8_postmortem_support) {
|
||||||
sources += [ "$target_gen_dir/debug-support.cc" ]
|
sources += [ "$target_gen_dir/debug-support.cc" ]
|
||||||
deps += [ ":postmortem-metadata" ]
|
deps += [ ":postmortem-metadata" ]
|
||||||
|
2
DEPS
2
DEPS
@ -256,6 +256,8 @@ deps = {
|
|||||||
Var('android_url') + '/platform/external/perfetto.git' + '@' + '12dc10e0278cded35205cf84f80a821348cb6c56',
|
Var('android_url') + '/platform/external/perfetto.git' + '@' + '12dc10e0278cded35205cf84f80a821348cb6c56',
|
||||||
'v8/third_party/protobuf':
|
'v8/third_party/protobuf':
|
||||||
Var('chromium_url') + '/external/github.com/google/protobuf'+ '@' + 'b68a347f56137b4b1a746e8c7438495a6ac1bd91',
|
Var('chromium_url') + '/external/github.com/google/protobuf'+ '@' + 'b68a347f56137b4b1a746e8c7438495a6ac1bd91',
|
||||||
|
'v8/third_party/zlib':
|
||||||
|
Var('chromium_url') + '/chromium/src/third_party/zlib.git'+ '@' + 'e5c4d8c45ed18f84ea68f5029c9bceb1f67268b8',
|
||||||
}
|
}
|
||||||
|
|
||||||
include_rules = [
|
include_rules = [
|
||||||
|
@ -29,7 +29,7 @@ void ReadOnlyHeap::SetUp(Isolate* isolate, ReadOnlyDeserializer* des) {
|
|||||||
DCHECK_NOT_NULL(isolate);
|
DCHECK_NOT_NULL(isolate);
|
||||||
#ifdef V8_SHARED_RO_HEAP
|
#ifdef V8_SHARED_RO_HEAP
|
||||||
bool call_once_ran = false;
|
bool call_once_ran = false;
|
||||||
base::Optional<Checksum> des_checksum;
|
base::Optional<uint32_t> des_checksum;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (des != nullptr) des_checksum = des->GetChecksum();
|
if (des != nullptr) des_checksum = des->GetChecksum();
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
@ -50,7 +50,7 @@ void ReadOnlyHeap::SetUp(Isolate* isolate, ReadOnlyDeserializer* des) {
|
|||||||
USE(call_once_ran);
|
USE(call_once_ran);
|
||||||
USE(des_checksum);
|
USE(des_checksum);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
const base::Optional<Checksum> last_checksum =
|
const base::Optional<uint32_t> last_checksum =
|
||||||
shared_ro_heap_->read_only_blob_checksum_;
|
shared_ro_heap_->read_only_blob_checksum_;
|
||||||
if (last_checksum || des_checksum) {
|
if (last_checksum || des_checksum) {
|
||||||
// The read-only heap was set up from a snapshot. Make sure it's the always
|
// The read-only heap was set up from a snapshot. Make sure it's the always
|
||||||
|
@ -66,8 +66,6 @@ class ReadOnlyHeap final {
|
|||||||
ReadOnlySpace* read_only_space() const { return read_only_space_; }
|
ReadOnlySpace* read_only_space() const { return read_only_space_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Checksum = std::pair<uint32_t, uint32_t>;
|
|
||||||
|
|
||||||
// Creates a new read-only heap and attaches it to the provided isolate.
|
// Creates a new read-only heap and attaches it to the provided isolate.
|
||||||
static ReadOnlyHeap* CreateAndAttachToIsolate(Isolate* isolate);
|
static ReadOnlyHeap* CreateAndAttachToIsolate(Isolate* isolate);
|
||||||
// Runs the read-only deserailizer and calls InitFromIsolate to complete
|
// Runs the read-only deserailizer and calls InitFromIsolate to complete
|
||||||
@ -86,7 +84,7 @@ class ReadOnlyHeap final {
|
|||||||
#ifdef V8_SHARED_RO_HEAP
|
#ifdef V8_SHARED_RO_HEAP
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// The checksum of the blob the read-only heap was deserialized from, if any.
|
// The checksum of the blob the read-only heap was deserialized from, if any.
|
||||||
base::Optional<Checksum> read_only_blob_checksum_;
|
base::Optional<uint32_t> read_only_blob_checksum_;
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
Address read_only_roots_[kEntriesCount];
|
Address read_only_roots_[kEntriesCount];
|
||||||
|
@ -2,4 +2,7 @@ specific_include_rules = {
|
|||||||
"mksnapshot\.cc": [
|
"mksnapshot\.cc": [
|
||||||
"+include/libplatform/libplatform.h",
|
"+include/libplatform/libplatform.h",
|
||||||
],
|
],
|
||||||
|
"serializer-common.cc": [
|
||||||
|
"+third_party/zlib",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
@ -403,9 +403,7 @@ SerializedCodeData::SerializedCodeData(const std::vector<byte>* payload,
|
|||||||
CopyBytes(data_ + padded_payload_offset, payload->data(),
|
CopyBytes(data_ + padded_payload_offset, payload->data(),
|
||||||
static_cast<size_t>(payload->size()));
|
static_cast<size_t>(payload->size()));
|
||||||
|
|
||||||
Checksum checksum(ChecksummedContent());
|
SetHeaderValue(kChecksumOffset, Checksum(ChecksummedContent()));
|
||||||
SetHeaderValue(kChecksumPartAOffset, checksum.a());
|
|
||||||
SetHeaderValue(kChecksumPartBOffset, checksum.b());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||||
@ -417,8 +415,7 @@ SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
|||||||
uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
|
uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
|
||||||
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
|
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
|
||||||
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
|
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
|
||||||
uint32_t c1 = GetHeaderValue(kChecksumPartAOffset);
|
uint32_t c = GetHeaderValue(kChecksumOffset);
|
||||||
uint32_t c2 = GetHeaderValue(kChecksumPartBOffset);
|
|
||||||
if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||||
if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
|
if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
|
||||||
if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
|
if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
|
||||||
@ -427,7 +424,7 @@ SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
|||||||
POINTER_SIZE_ALIGN(kHeaderSize +
|
POINTER_SIZE_ALIGN(kHeaderSize +
|
||||||
GetHeaderValue(kNumReservationsOffset) * kInt32Size);
|
GetHeaderValue(kNumReservationsOffset) * kInt32Size);
|
||||||
if (payload_length > max_payload_length) return LENGTH_MISMATCH;
|
if (payload_length > max_payload_length) return LENGTH_MISMATCH;
|
||||||
if (!Checksum(ChecksummedContent()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
if (Checksum(ChecksummedContent()) != c) return CHECKSUM_MISMATCH;
|
||||||
return CHECK_SUCCESS;
|
return CHECK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +94,7 @@ class SerializedCodeData : public SerializedData {
|
|||||||
// [3] flag hash
|
// [3] flag hash
|
||||||
// [4] number of reservation size entries
|
// [4] number of reservation size entries
|
||||||
// [5] payload length
|
// [5] payload length
|
||||||
// [6] payload checksum part A
|
// [6] payload checksum
|
||||||
// [7] payload checksum part B
|
|
||||||
// ... reservations
|
// ... reservations
|
||||||
// ... code stub keys
|
// ... code stub keys
|
||||||
// ... serialized payload
|
// ... serialized payload
|
||||||
@ -105,12 +104,8 @@ class SerializedCodeData : public SerializedData {
|
|||||||
static const uint32_t kNumReservationsOffset = kFlagHashOffset + kUInt32Size;
|
static const uint32_t kNumReservationsOffset = kFlagHashOffset + kUInt32Size;
|
||||||
static const uint32_t kPayloadLengthOffset =
|
static const uint32_t kPayloadLengthOffset =
|
||||||
kNumReservationsOffset + kUInt32Size;
|
kNumReservationsOffset + kUInt32Size;
|
||||||
static const uint32_t kChecksumPartAOffset =
|
static const uint32_t kChecksumOffset = kPayloadLengthOffset + kUInt32Size;
|
||||||
kPayloadLengthOffset + kUInt32Size;
|
static const uint32_t kUnalignedHeaderSize = kChecksumOffset + kUInt32Size;
|
||||||
static const uint32_t kChecksumPartBOffset =
|
|
||||||
kChecksumPartAOffset + kUInt32Size;
|
|
||||||
static const uint32_t kUnalignedHeaderSize =
|
|
||||||
kChecksumPartBOffset + kUInt32Size;
|
|
||||||
static const uint32_t kHeaderSize = POINTER_SIZE_ALIGN(kUnalignedHeaderSize);
|
static const uint32_t kHeaderSize = POINTER_SIZE_ALIGN(kUnalignedHeaderSize);
|
||||||
|
|
||||||
// Used when consuming.
|
// Used when consuming.
|
||||||
|
@ -41,9 +41,7 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
|
|||||||
~Deserializer() override;
|
~Deserializer() override;
|
||||||
|
|
||||||
void SetRehashability(bool v) { can_rehash_ = v; }
|
void SetRehashability(bool v) { can_rehash_ = v; }
|
||||||
std::pair<uint32_t, uint32_t> GetChecksum() const {
|
uint32_t GetChecksum() const { return source_.GetChecksum(); }
|
||||||
return source_.GetChecksum();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Create a deserializer from a snapshot byte source.
|
// Create a deserializer from a snapshot byte source.
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "src/objects/foreign-inl.h"
|
#include "src/objects/foreign-inl.h"
|
||||||
#include "src/objects/objects-inl.h"
|
#include "src/objects/objects-inl.h"
|
||||||
#include "src/objects/slots.h"
|
#include "src/objects/slots.h"
|
||||||
|
#include "third_party/zlib/zlib.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -145,5 +146,16 @@ void SerializerDeserializer::RestoreExternalReferenceRedirectors(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
V8_EXPORT_PRIVATE extern uint32_t Checksum(Vector<const byte> payload) {
|
||||||
|
#ifdef MEMORY_SANITIZER
|
||||||
|
// Computing the checksum includes padding bytes for objects like strings.
|
||||||
|
// Mark every object as initialized in the code serializer.
|
||||||
|
MSAN_MEMORY_IS_INITIALIZED(payload.begin(), payload.length());
|
||||||
|
#endif // MEMORY_SANITIZER
|
||||||
|
// Priming the adler32 call so it can see what CPU features are available.
|
||||||
|
adler32(0, NULL, 0);
|
||||||
|
return static_cast<uint32_t>(adler32(0, payload.begin(), payload.length()));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -358,50 +358,7 @@ class SerializedData {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(SerializedData);
|
DISALLOW_COPY_AND_ASSIGN(SerializedData);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Checksum {
|
V8_EXPORT_PRIVATE uint32_t Checksum(Vector<const byte> payload);
|
||||||
public:
|
|
||||||
explicit Checksum(Vector<const byte> payload) {
|
|
||||||
#ifdef MEMORY_SANITIZER
|
|
||||||
// Computing the checksum includes padding bytes for objects like strings.
|
|
||||||
// Mark every object as initialized in the code serializer.
|
|
||||||
MSAN_MEMORY_IS_INITIALIZED(payload.begin(), payload.length());
|
|
||||||
#endif // MEMORY_SANITIZER
|
|
||||||
// Fletcher's checksum. Modified to reduce 64-bit sums to 32-bit.
|
|
||||||
uintptr_t a = 1;
|
|
||||||
uintptr_t b = 0;
|
|
||||||
// TODO(jgruber, v8:9171): The following DCHECK should ideally hold since we
|
|
||||||
// access payload through an uintptr_t pointer later on; and some
|
|
||||||
// architectures, e.g. arm, may generate instructions that expect correct
|
|
||||||
// alignment. However, we do not control alignment for external snapshots.
|
|
||||||
// DCHECK(IsAligned(reinterpret_cast<intptr_t>(payload.begin()),
|
|
||||||
// kIntptrSize));
|
|
||||||
DCHECK(IsAligned(payload.length(), kIntptrSize));
|
|
||||||
const uintptr_t* cur = reinterpret_cast<const uintptr_t*>(payload.begin());
|
|
||||||
const uintptr_t* end = cur + payload.length() / kIntptrSize;
|
|
||||||
while (cur < end) {
|
|
||||||
// Unsigned overflow expected and intended.
|
|
||||||
a += *cur++;
|
|
||||||
b += a;
|
|
||||||
}
|
|
||||||
#if V8_HOST_ARCH_64_BIT
|
|
||||||
a ^= a >> 32;
|
|
||||||
b ^= b >> 32;
|
|
||||||
#endif // V8_HOST_ARCH_64_BIT
|
|
||||||
a_ = static_cast<uint32_t>(a);
|
|
||||||
b_ = static_cast<uint32_t>(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Check(uint32_t a, uint32_t b) const { return a == a_ && b == b_; }
|
|
||||||
|
|
||||||
uint32_t a() const { return a_; }
|
|
||||||
uint32_t b() const { return b_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t a_;
|
|
||||||
uint32_t b_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(Checksum);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -192,9 +192,7 @@ v8::StartupData Snapshot::CreateSnapshotBlob(
|
|||||||
DCHECK_EQ(total_length, payload_offset);
|
DCHECK_EQ(total_length, payload_offset);
|
||||||
v8::StartupData result = {data, static_cast<int>(total_length)};
|
v8::StartupData result = {data, static_cast<int>(total_length)};
|
||||||
|
|
||||||
Checksum checksum(ChecksummedContent(&result));
|
SetHeaderValue(data, kChecksumOffset, Checksum(ChecksummedContent(&result)));
|
||||||
SetHeaderValue(data, kChecksumPartAOffset, checksum.a());
|
|
||||||
SetHeaderValue(data, kChecksumPartBOffset, checksum.b());
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -208,14 +206,13 @@ uint32_t Snapshot::ExtractNumContexts(const v8::StartupData* data) {
|
|||||||
bool Snapshot::VerifyChecksum(const v8::StartupData* data) {
|
bool Snapshot::VerifyChecksum(const v8::StartupData* data) {
|
||||||
base::ElapsedTimer timer;
|
base::ElapsedTimer timer;
|
||||||
if (FLAG_profile_deserialization) timer.Start();
|
if (FLAG_profile_deserialization) timer.Start();
|
||||||
uint32_t expected_a = GetHeaderValue(data, kChecksumPartAOffset);
|
uint32_t expected = GetHeaderValue(data, kChecksumOffset);
|
||||||
uint32_t expected_b = GetHeaderValue(data, kChecksumPartBOffset);
|
uint32_t result = Checksum(ChecksummedContent(data));
|
||||||
Checksum checksum(ChecksummedContent(data));
|
|
||||||
if (FLAG_profile_deserialization) {
|
if (FLAG_profile_deserialization) {
|
||||||
double ms = timer.Elapsed().InMillisecondsF();
|
double ms = timer.Elapsed().InMillisecondsF();
|
||||||
PrintF("[Verifying snapshot checksum took %0.3f ms]\n", ms);
|
PrintF("[Verifying snapshot checksum took %0.3f ms]\n", ms);
|
||||||
}
|
}
|
||||||
return checksum.Check(expected_a, expected_b);
|
return result == expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Snapshot::ExtractContextOffset(const v8::StartupData* data,
|
uint32_t Snapshot::ExtractContextOffset(const v8::StartupData* data,
|
||||||
|
@ -87,9 +87,8 @@ class SnapshotByteSource final {
|
|||||||
int position() { return position_; }
|
int position() { return position_; }
|
||||||
void set_position(int position) { position_ = position; }
|
void set_position(int position) { position_ = position; }
|
||||||
|
|
||||||
std::pair<uint32_t, uint32_t> GetChecksum() const {
|
uint32_t GetChecksum() const {
|
||||||
Checksum checksum(Vector<const byte>(data_, length_));
|
return Checksum(Vector<const byte>(data_, length_));
|
||||||
return {checksum.a(), checksum.b()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -111,12 +111,11 @@ class Snapshot : public AllStatic {
|
|||||||
// Snapshot blob layout:
|
// Snapshot blob layout:
|
||||||
// [0] number of contexts N
|
// [0] number of contexts N
|
||||||
// [1] rehashability
|
// [1] rehashability
|
||||||
// [2] checksum part A
|
// [2] checksum
|
||||||
// [3] checksum part B
|
// [3] (128 bytes) version string
|
||||||
// [4] (128 bytes) version string
|
// [4] offset to readonly
|
||||||
// [5] offset to readonly
|
// [5] offset to context 0
|
||||||
// [6] offset to context 0
|
// [6] offset to context 1
|
||||||
// [7] offset to context 1
|
|
||||||
// ...
|
// ...
|
||||||
// ... offset to context N - 1
|
// ... offset to context N - 1
|
||||||
// ... startup snapshot data
|
// ... startup snapshot data
|
||||||
@ -128,12 +127,8 @@ class Snapshot : public AllStatic {
|
|||||||
// TODO(yangguo): generalize rehashing, and remove this flag.
|
// TODO(yangguo): generalize rehashing, and remove this flag.
|
||||||
static const uint32_t kRehashabilityOffset =
|
static const uint32_t kRehashabilityOffset =
|
||||||
kNumberOfContextsOffset + kUInt32Size;
|
kNumberOfContextsOffset + kUInt32Size;
|
||||||
static const uint32_t kChecksumPartAOffset =
|
static const uint32_t kChecksumOffset = kRehashabilityOffset + kUInt32Size;
|
||||||
kRehashabilityOffset + kUInt32Size;
|
static const uint32_t kVersionStringOffset = kChecksumOffset + kUInt32Size;
|
||||||
static const uint32_t kChecksumPartBOffset =
|
|
||||||
kChecksumPartAOffset + kUInt32Size;
|
|
||||||
static const uint32_t kVersionStringOffset =
|
|
||||||
kChecksumPartBOffset + kUInt32Size;
|
|
||||||
static const uint32_t kVersionStringLength = 64;
|
static const uint32_t kVersionStringLength = 64;
|
||||||
static const uint32_t kReadOnlyOffsetOffset =
|
static const uint32_t kReadOnlyOffsetOffset =
|
||||||
kVersionStringOffset + kVersionStringLength;
|
kVersionStringOffset + kVersionStringLength;
|
||||||
@ -141,6 +136,7 @@ class Snapshot : public AllStatic {
|
|||||||
kReadOnlyOffsetOffset + kUInt32Size;
|
kReadOnlyOffsetOffset + kUInt32Size;
|
||||||
|
|
||||||
static Vector<const byte> ChecksummedContent(const v8::StartupData* data) {
|
static Vector<const byte> ChecksummedContent(const v8::StartupData* data) {
|
||||||
|
STATIC_ASSERT(kVersionStringOffset == kChecksumOffset + kUInt32Size);
|
||||||
const uint32_t kChecksumStart = kVersionStringOffset;
|
const uint32_t kChecksumStart = kVersionStringOffset;
|
||||||
return Vector<const byte>(
|
return Vector<const byte>(
|
||||||
reinterpret_cast<const byte*>(data->data + kChecksumStart),
|
reinterpret_cast<const byte*>(data->data + kChecksumStart),
|
||||||
|
@ -31,6 +31,7 @@ group("v8_run_gcmole") {
|
|||||||
"../../third_party/icu/source/",
|
"../../third_party/icu/source/",
|
||||||
"../../third_party/wasm-api/wasm.h",
|
"../../third_party/wasm-api/wasm.h",
|
||||||
"../../third_party/wasm-api/wasm.hh",
|
"../../third_party/wasm-api/wasm.hh",
|
||||||
|
"../../third_party/zlib/",
|
||||||
"../../third_party/inspector_protocol/",
|
"../../third_party/inspector_protocol/",
|
||||||
"$target_gen_dir/../../",
|
"$target_gen_dir/../../",
|
||||||
"$target_gen_dir/../../torque-generated/",
|
"$target_gen_dir/../../torque-generated/",
|
||||||
|
Loading…
Reference in New Issue
Block a user