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;
}
}
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);
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_);
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;
}
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
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.
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 =
}
+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;