Commit c123ef99 authored by Marja Hölttä's avatar Marja Hölttä Committed by V8 LUCI CQ

[d8] Add a stress mode to test web snapshot / json deserializing

Bug: v8:11525
Change-Id: I74190f2136e91107deea2c31f750a2d1a43dc18a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3528502Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79531}
parent d7ccedb6
...@@ -1441,9 +1441,12 @@ bool Shell::ExecuteWebSnapshot(Isolate* isolate, const char* file_name) { ...@@ -1441,9 +1441,12 @@ bool Shell::ExecuteWebSnapshot(Isolate* isolate, const char* file_name) {
if (length == 0) { if (length == 0) {
isolate->ThrowError("Could not read the web snapshot file"); isolate->ThrowError("Could not read the web snapshot file");
} else { } else {
i::WebSnapshotDeserializer deserializer(isolate, snapshot_data.get(), for (int r = 0; r < DeserializationRunCount(); ++r) {
static_cast<size_t>(length)); bool skip_exports = r > 0;
success = deserializer.Deserialize(); i::WebSnapshotDeserializer deserializer(isolate, snapshot_data.get(),
static_cast<size_t>(length));
success = deserializer.Deserialize({}, skip_exports);
}
} }
if (!success) { if (!success) {
CHECK(try_catch.HasCaught()); CHECK(try_catch.HasCaught());
...@@ -1471,14 +1474,17 @@ bool Shell::LoadJSON(Isolate* isolate, const char* file_name) { ...@@ -1471,14 +1474,17 @@ bool Shell::LoadJSON(Isolate* isolate, const char* file_name) {
std::stringstream stream(data.get()); std::stringstream stream(data.get());
std::string line; std::string line;
while (std::getline(stream, line, '\n')) { while (std::getline(stream, line, '\n')) {
Local<String> source = for (int r = 0; r < DeserializationRunCount(); ++r) {
String::NewFromUtf8(isolate, line.c_str()).ToLocalChecked(); Local<String> source =
MaybeLocal<Value> maybe_value = JSON::Parse(realm, source); String::NewFromUtf8(isolate, line.c_str()).ToLocalChecked();
Local<Value> value; MaybeLocal<Value> maybe_value = JSON::Parse(realm, source);
if (!maybe_value.ToLocal(&value)) {
DCHECK(try_catch.HasCaught()); Local<Value> value;
ReportException(isolate, &try_catch); if (!maybe_value.ToLocal(&value)) {
return false; DCHECK(try_catch.HasCaught());
ReportException(isolate, &try_catch);
return false;
}
} }
} }
return true; return true;
...@@ -4517,6 +4523,9 @@ bool Shell::SetOptions(int argc, char* argv[]) { ...@@ -4517,6 +4523,9 @@ bool Shell::SetOptions(int argc, char* argv[]) {
options.cpu_profiler = true; options.cpu_profiler = true;
options.cpu_profiler_print = true; options.cpu_profiler_print = true;
argv[i] = nullptr; argv[i] = nullptr;
} else if (strcmp(argv[i], "--stress-deserialize") == 0) {
options.stress_deserialize = true;
argv[i] = nullptr;
} else if (strncmp(argv[i], "--web-snapshot-config=", 22) == 0) { } else if (strncmp(argv[i], "--web-snapshot-config=", 22) == 0) {
options.web_snapshot_config = argv[i] + 22; options.web_snapshot_config = argv[i] + 22;
argv[i] = nullptr; argv[i] = nullptr;
......
...@@ -464,6 +464,8 @@ class ShellOptions { ...@@ -464,6 +464,8 @@ class ShellOptions {
"web-snapshot-output", nullptr}; "web-snapshot-output", nullptr};
DisallowReassignment<bool> d8_web_snapshot_api = { DisallowReassignment<bool> d8_web_snapshot_api = {
"experimental-d8-web-snapshot-api", false}; "experimental-d8-web-snapshot-api", false};
// Applies to web snapshot and JSON deserialization.
DisallowReassignment<bool> stress_deserialize = {"stress-deserialize", false};
DisallowReassignment<bool> compile_only = {"compile-only", false}; DisallowReassignment<bool> compile_only = {"compile-only", false};
DisallowReassignment<int> repeat_compile = {"repeat-compile", 1}; DisallowReassignment<int> repeat_compile = {"repeat-compile", 1};
#if V8_ENABLE_WEBASSEMBLY #if V8_ENABLE_WEBASSEMBLY
...@@ -691,6 +693,10 @@ class Shell : public i::AllStatic { ...@@ -691,6 +693,10 @@ class Shell : public i::AllStatic {
static Local<FunctionTemplate> CreateSnapshotTemplate(Isolate* isolate); static Local<FunctionTemplate> CreateSnapshotTemplate(Isolate* isolate);
private: private:
static inline int DeserializationRunCount() {
return options.stress_deserialize ? 1000 : 1;
}
static Global<Context> evaluation_context_; static Global<Context> evaluation_context_;
static base::OnceType quit_once_; static base::OnceType quit_once_;
static Global<Function> stringify_function_; static Global<Function> stringify_function_;
......
...@@ -1345,7 +1345,7 @@ void WebSnapshotDeserializer::Throw(const char* message) { ...@@ -1345,7 +1345,7 @@ void WebSnapshotDeserializer::Throw(const char* message) {
} }
bool WebSnapshotDeserializer::Deserialize( bool WebSnapshotDeserializer::Deserialize(
MaybeHandle<FixedArray> external_references) { MaybeHandle<FixedArray> external_references, bool skip_exports) {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize);
if (external_references.ToHandle(&external_references_handle_)) { if (external_references.ToHandle(&external_references_handle_)) {
external_references_ = *external_references_handle_; external_references_ = *external_references_handle_;
...@@ -1364,7 +1364,7 @@ bool WebSnapshotDeserializer::Deserialize( ...@@ -1364,7 +1364,7 @@ bool WebSnapshotDeserializer::Deserialize(
if (FLAG_trace_web_snapshot) { if (FLAG_trace_web_snapshot) {
timer.Start(); timer.Start();
} }
if (!DeserializeSnapshot()) { if (!DeserializeSnapshot(skip_exports)) {
return false; return false;
} }
if (!DeserializeScript()) { if (!DeserializeScript()) {
...@@ -1379,7 +1379,7 @@ bool WebSnapshotDeserializer::Deserialize( ...@@ -1379,7 +1379,7 @@ bool WebSnapshotDeserializer::Deserialize(
return true; return true;
} }
bool WebSnapshotDeserializer::DeserializeSnapshot() { bool WebSnapshotDeserializer::DeserializeSnapshot(bool skip_exports) {
deferred_references_ = ArrayList::New(isolate_, 30); deferred_references_ = ArrayList::New(isolate_, 30);
const void* magic_bytes; const void* magic_bytes;
...@@ -1397,7 +1397,7 @@ bool WebSnapshotDeserializer::DeserializeSnapshot() { ...@@ -1397,7 +1397,7 @@ bool WebSnapshotDeserializer::DeserializeSnapshot() {
DeserializeObjects(); DeserializeObjects();
DeserializeClasses(); DeserializeClasses();
ProcessDeferredReferences(); ProcessDeferredReferences();
DeserializeExports(); DeserializeExports(skip_exports);
DCHECK_EQ(0, deferred_references_->Length()); DCHECK_EQ(0, deferred_references_->Length());
return !has_error(); return !has_error();
...@@ -2041,13 +2041,29 @@ void WebSnapshotDeserializer::DeserializeArrays() { ...@@ -2041,13 +2041,29 @@ void WebSnapshotDeserializer::DeserializeArrays() {
} }
} }
void WebSnapshotDeserializer::DeserializeExports() { void WebSnapshotDeserializer::DeserializeExports(bool skip_exports) {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Exports); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Exports);
uint32_t count; uint32_t count;
if (!deserializer_.ReadUint32(&count) || count > kMaxItemCount) { if (!deserializer_.ReadUint32(&count) || count > kMaxItemCount) {
Throw("Malformed export table"); Throw("Malformed export table");
return; return;
} }
if (skip_exports) {
// In the skip_exports mode, we read the exports but don't do anything about
// them. This is useful for stress testing; otherwise the GlobalDictionary
// handling below dominates.
for (uint32_t i = 0; i < count; ++i) {
Handle<String> export_name(ReadString(true), isolate_);
// No deferred references should occur at this point, since all objects
// have been deserialized.
Object export_value = ReadValue();
USE(export_name);
USE(export_value);
}
return;
}
// Pre-reserve the space for the properties we're going to add to the global // Pre-reserve the space for the properties we're going to add to the global
// object. // object.
Handle<JSGlobalObject> global = isolate_->global_object(); Handle<JSGlobalObject> global = isolate_->global_object();
......
...@@ -278,7 +278,8 @@ class V8_EXPORT WebSnapshotDeserializer ...@@ -278,7 +278,8 @@ class V8_EXPORT WebSnapshotDeserializer
size_t buffer_size); size_t buffer_size);
WebSnapshotDeserializer(Isolate* isolate, Handle<Script> snapshot_as_script); WebSnapshotDeserializer(Isolate* isolate, Handle<Script> snapshot_as_script);
~WebSnapshotDeserializer(); ~WebSnapshotDeserializer();
bool Deserialize(MaybeHandle<FixedArray> external_references = {}); bool Deserialize(MaybeHandle<FixedArray> external_references = {},
bool skip_exports = false);
// For inspecting the state after deserializing a snapshot. // For inspecting the state after deserializing a snapshot.
uint32_t string_count() const { return string_count_; } uint32_t string_count() const { return string_count_; }
...@@ -304,7 +305,7 @@ class V8_EXPORT WebSnapshotDeserializer ...@@ -304,7 +305,7 @@ class V8_EXPORT WebSnapshotDeserializer
base::Vector<const uint8_t> buffer); base::Vector<const uint8_t> buffer);
base::Vector<const uint8_t> ExtractScriptBuffer( base::Vector<const uint8_t> ExtractScriptBuffer(
Isolate* isolate, Handle<Script> snapshot_as_script); Isolate* isolate, Handle<Script> snapshot_as_script);
bool DeserializeSnapshot(); bool DeserializeSnapshot(bool skip_exports);
bool DeserializeScript(); bool DeserializeScript();
WebSnapshotDeserializer(const WebSnapshotDeserializer&) = delete; WebSnapshotDeserializer(const WebSnapshotDeserializer&) = delete;
...@@ -323,7 +324,7 @@ class V8_EXPORT WebSnapshotDeserializer ...@@ -323,7 +324,7 @@ class V8_EXPORT WebSnapshotDeserializer
void DeserializeClasses(); void DeserializeClasses();
void DeserializeArrays(); void DeserializeArrays();
void DeserializeObjects(); void DeserializeObjects();
void DeserializeExports(); void DeserializeExports(bool skip_exports);
Object ReadValue( Object ReadValue(
Handle<HeapObject> object_for_deferred_reference = Handle<HeapObject>(), Handle<HeapObject> object_for_deferred_reference = Handle<HeapObject>(),
......
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