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}
This commit is contained in:
parent
c6c1d8ffd6
commit
7f4d207c8b
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user