Commit 7f4d207c authored by yangguo's avatar yangguo Committed by Commit bot

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}
parent c6c1d8ff
......@@ -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;
}
}
......
......@@ -2500,7 +2500,11 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
AllocateData(size);
// Set header values.
SetHeaderValue(kCheckSumOffset, CheckSum(cs.source()));
SetHeaderValue(kVersionHashOffset, Version::Hash());
SetHeaderValue(kSourceHashOffset, SourceHash(cs.source()));
SetHeaderValue(kCpuFeaturesOffset,
static_cast<uint32_t>(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<byte>& payload,
bool SerializedCodeData::IsSane(String* source) {
return GetHeaderValue(kCheckSumOffset) == CheckSum(source) &&
return GetHeaderValue(kVersionHashOffset) == Version::Hash() &&
GetHeaderValue(kSourceHashOffset) == SourceHash(source) &&
GetHeaderValue(kCpuFeaturesOffset) ==
static_cast<uint32_t>(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_);
......
......@@ -494,12 +494,12 @@ class SerializedData {
class IsLastChunkBits : public BitField<bool, 31, 1> {};
protected:
void SetHeaderValue(int offset, int value) {
memcpy(reinterpret_cast<int*>(data_) + offset, &value, sizeof(value));
void SetHeaderValue(int offset, uint32_t value) {
memcpy(reinterpret_cast<uint32_t*>(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<int*>(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
......
......@@ -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<int>(base::hash_combine(major_, minor_, build_, patch_));
static uint32_t Hash() {
return static_cast<uint32_t>(
base::hash_combine(major_, minor_, build_, patch_));
}
// Calculate the V8 version string.
......
......@@ -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<const uint8_t*>(garbage);
int length = 16;
v8::ScriptCompiler::CachedData* cached_data =
......
......@@ -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<v8::Context> context = v8::Context::New(isolate1);
v8::Context::Scope context_scope(context);
v8::Local<v8::String> source_str = v8_str(source);
v8::ScriptOrigin origin(v8_str("test"));
v8::ScriptCompiler::Source source(source_str, origin);
v8::Local<v8::UnboundScript> 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<uint8_t>(data->length);
MemCopy(buffer, data->data, data->length);
cache = new v8::ScriptCompiler::CachedData(
buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
v8::Local<v8::Value> 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<v8::Context> context = v8::Context::New(isolate2);
v8::Context::Scope context_scope(context);
v8::Local<v8::String> 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;
......
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