From 7f4d207c8bd510cd1843ff3e30608f0e5290cb1e Mon Sep 17 00:00:00 2001 From: yangguo Date: Fri, 6 Feb 2015 07:20:40 -0800 Subject: [PATCH] Add hash fields to code cache header. R=jochen@chromium.org BUG=chromium:441896 LOG=N Review URL: https://codereview.chromium.org/909473002 Cr-Commit-Position: refs/heads/master@{#26490} --- src/flags.cc | 1 + src/serialize.cc | 17 +++++++++------ src/serialize.h | 34 +++++++++++++++++------------ src/version.h | 5 +++-- test/cctest/test-api.cc | 2 +- test/cctest/test-serialize.cc | 50 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 85 insertions(+), 24 deletions(-) diff --git a/src/flags.cc b/src/flags.cc index 2aa4e6b..5e33bda 100644 --- a/src/flags.cc +++ b/src/flags.cc @@ -556,6 +556,7 @@ uint32_t FlagList::Hash() { for (size_t i = 0; i < num_flags; ++i) { Flag* current = &flags[i]; if (!current->IsDefault()) { + modified_args_as_string << i; modified_args_as_string << *current; } } diff --git a/src/serialize.cc b/src/serialize.cc index 0b9e938..1423b23 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -2500,7 +2500,11 @@ SerializedCodeData::SerializedCodeData(const List& payload, AllocateData(size); // Set header values. - SetHeaderValue(kCheckSumOffset, CheckSum(cs.source())); + SetHeaderValue(kVersionHashOffset, Version::Hash()); + SetHeaderValue(kSourceHashOffset, SourceHash(cs.source())); + SetHeaderValue(kCpuFeaturesOffset, + static_cast(CpuFeatures::SupportedFeatures())); + SetHeaderValue(kFlagHashOffset, FlagList::Hash()); SetHeaderValue(kNumInternalizedStringsOffset, cs.num_internalized_strings()); SetHeaderValue(kReservationsOffset, reservations.length()); SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); @@ -2521,16 +2525,15 @@ SerializedCodeData::SerializedCodeData(const List& payload, bool SerializedCodeData::IsSane(String* source) { - return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && + return GetHeaderValue(kVersionHashOffset) == Version::Hash() && + GetHeaderValue(kSourceHashOffset) == SourceHash(source) && + GetHeaderValue(kCpuFeaturesOffset) == + static_cast(CpuFeatures::SupportedFeatures()) && + GetHeaderValue(kFlagHashOffset) == FlagList::Hash() && Payload().length() >= SharedFunctionInfo::kSize; } -int SerializedCodeData::CheckSum(String* string) { - return Version::Hash() ^ string->length(); -} - - // Return ScriptData object and relinquish ownership over it to the caller. ScriptData* SerializedCodeData::GetScriptData() { DCHECK(owns_data_); diff --git a/src/serialize.h b/src/serialize.h index 9aaf381..444e881 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -494,12 +494,12 @@ class SerializedData { class IsLastChunkBits : public BitField {}; protected: - void SetHeaderValue(int offset, int value) { - memcpy(reinterpret_cast(data_) + offset, &value, sizeof(value)); + void SetHeaderValue(int offset, uint32_t value) { + memcpy(reinterpret_cast(data_) + offset, &value, sizeof(value)); } - int GetHeaderValue(int offset) const { - int value; + uint32_t GetHeaderValue(int offset) const { + uint32_t value; memcpy(&value, reinterpret_cast(data_) + offset, sizeof(value)); return value; } @@ -948,19 +948,25 @@ class SerializedCodeData : public SerializedData { bool IsSane(String* source); - int CheckSum(String* source); + uint32_t SourceHash(String* source) { return source->length(); } // The data header consists of int-sized entries: // [0] version hash - // [1] number of internalized strings - // [2] number of code stub keys - // [3] number of reservation size entries - // [4] payload length - static const int kCheckSumOffset = 0; - static const int kNumInternalizedStringsOffset = 1; - static const int kReservationsOffset = 2; - static const int kNumCodeStubKeysOffset = 3; - static const int kPayloadLengthOffset = 4; + // [1] source hash + // [2] cpu features + // [3] flag hash + // [4] number of internalized strings + // [5] number of code stub keys + // [6] number of reservation size entries + // [7] payload length + static const int kVersionHashOffset = 0; + static const int kSourceHashOffset = 1; + static const int kCpuFeaturesOffset = 2; + static const int kFlagHashOffset = 3; + static const int kNumInternalizedStringsOffset = 4; + static const int kReservationsOffset = 5; + static const int kNumCodeStubKeysOffset = 6; + static const int kPayloadLengthOffset = 7; static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize; }; } } // namespace v8::internal diff --git a/src/version.h b/src/version.h index 008ed27..dbcec1b 100644 --- a/src/version.h +++ b/src/version.h @@ -18,8 +18,9 @@ class Version { static int GetBuild() { return build_; } static int GetPatch() { return patch_; } static bool IsCandidate() { return candidate_; } - static int Hash() { - return static_cast(base::hash_combine(major_, minor_, build_, patch_)); + static uint32_t Hash() { + return static_cast( + base::hash_combine(major_, minor_, build_, patch_)); } // Calculate the V8 version string. diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 742ccd8..753b471 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -21765,7 +21765,7 @@ TEST(StreamingWithHarmonyScopes) { void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) { - const char* garbage = "garbage garbage garbage garbage."; + const char* garbage = "garbage garbage garbage garbage garbage garbage"; const uint8_t* data = reinterpret_cast(garbage); int length = 16; v8::ScriptCompiler::CachedData* cached_data = diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc index ef01325..85729cc 100644 --- a/test/cctest/test-serialize.cc +++ b/test/cctest/test-serialize.cc @@ -1317,6 +1317,56 @@ TEST(SerializeToplevelIsolates) { } +TEST(SerializeToplevelFlagChange) { + FLAG_serialize_toplevel = true; + + const char* source = "function f() { return 'abc'; }; f() + 'def'"; + v8::ScriptCompiler::CachedData* cache; + + v8::Isolate* isolate1 = v8::Isolate::New(); + { + v8::Isolate::Scope iscope(isolate1); + v8::HandleScope scope(isolate1); + v8::Local context = v8::Context::New(isolate1); + v8::Context::Scope context_scope(context); + + v8::Local source_str = v8_str(source); + v8::ScriptOrigin origin(v8_str("test")); + v8::ScriptCompiler::Source source(source_str, origin); + v8::Local script = v8::ScriptCompiler::CompileUnbound( + isolate1, &source, v8::ScriptCompiler::kProduceCodeCache); + const v8::ScriptCompiler::CachedData* data = source.GetCachedData(); + CHECK(data); + // Persist cached data. + uint8_t* buffer = NewArray(data->length); + MemCopy(buffer, data->data, data->length); + cache = new v8::ScriptCompiler::CachedData( + buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned); + + v8::Local result = script->BindToCurrentContext()->Run(); + CHECK(result->ToString(isolate1)->Equals(v8_str("abcdef"))); + } + isolate1->Dispose(); + + v8::Isolate* isolate2 = v8::Isolate::New(); + FLAG_allow_natives_syntax = true; // Flag change should trigger cache reject. + { + v8::Isolate::Scope iscope(isolate2); + v8::HandleScope scope(isolate2); + v8::Local context = v8::Context::New(isolate2); + v8::Context::Scope context_scope(context); + + v8::Local source_str = v8_str(source); + v8::ScriptOrigin origin(v8_str("test")); + v8::ScriptCompiler::Source source(source_str, origin, cache); + v8::ScriptCompiler::CompileUnbound(isolate2, &source, + v8::ScriptCompiler::kConsumeCodeCache); + CHECK(cache->rejected); + } + isolate2->Dispose(); +} + + TEST(SerializeWithHarmonyScoping) { FLAG_serialize_toplevel = true; FLAG_harmony_scoping = true; -- 2.7.4