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) {
if (length == 0) {
isolate->ThrowError("Could not read the web snapshot file");
} else {
for (int r = 0; r < DeserializationRunCount(); ++r) {
bool skip_exports = r > 0;
i::WebSnapshotDeserializer deserializer(isolate, snapshot_data.get(),
static_cast<size_t>(length));
success = deserializer.Deserialize();
success = deserializer.Deserialize({}, skip_exports);
}
}
if (!success) {
CHECK(try_catch.HasCaught());
......@@ -1471,9 +1474,11 @@ bool Shell::LoadJSON(Isolate* isolate, const char* file_name) {
std::stringstream stream(data.get());
std::string line;
while (std::getline(stream, line, '\n')) {
for (int r = 0; r < DeserializationRunCount(); ++r) {
Local<String> source =
String::NewFromUtf8(isolate, line.c_str()).ToLocalChecked();
MaybeLocal<Value> maybe_value = JSON::Parse(realm, source);
Local<Value> value;
if (!maybe_value.ToLocal(&value)) {
DCHECK(try_catch.HasCaught());
......@@ -1481,6 +1486,7 @@ bool Shell::LoadJSON(Isolate* isolate, const char* file_name) {
return false;
}
}
}
return true;
}
......@@ -4517,6 +4523,9 @@ bool Shell::SetOptions(int argc, char* argv[]) {
options.cpu_profiler = true;
options.cpu_profiler_print = true;
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) {
options.web_snapshot_config = argv[i] + 22;
argv[i] = nullptr;
......
......@@ -464,6 +464,8 @@ class ShellOptions {
"web-snapshot-output", nullptr};
DisallowReassignment<bool> d8_web_snapshot_api = {
"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<int> repeat_compile = {"repeat-compile", 1};
#if V8_ENABLE_WEBASSEMBLY
......@@ -691,6 +693,10 @@ class Shell : public i::AllStatic {
static Local<FunctionTemplate> CreateSnapshotTemplate(Isolate* isolate);
private:
static inline int DeserializationRunCount() {
return options.stress_deserialize ? 1000 : 1;
}
static Global<Context> evaluation_context_;
static base::OnceType quit_once_;
static Global<Function> stringify_function_;
......
......@@ -1345,7 +1345,7 @@ void WebSnapshotDeserializer::Throw(const char* message) {
}
bool WebSnapshotDeserializer::Deserialize(
MaybeHandle<FixedArray> external_references) {
MaybeHandle<FixedArray> external_references, bool skip_exports) {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize);
if (external_references.ToHandle(&external_references_handle_)) {
external_references_ = *external_references_handle_;
......@@ -1364,7 +1364,7 @@ bool WebSnapshotDeserializer::Deserialize(
if (FLAG_trace_web_snapshot) {
timer.Start();
}
if (!DeserializeSnapshot()) {
if (!DeserializeSnapshot(skip_exports)) {
return false;
}
if (!DeserializeScript()) {
......@@ -1379,7 +1379,7 @@ bool WebSnapshotDeserializer::Deserialize(
return true;
}
bool WebSnapshotDeserializer::DeserializeSnapshot() {
bool WebSnapshotDeserializer::DeserializeSnapshot(bool skip_exports) {
deferred_references_ = ArrayList::New(isolate_, 30);
const void* magic_bytes;
......@@ -1397,7 +1397,7 @@ bool WebSnapshotDeserializer::DeserializeSnapshot() {
DeserializeObjects();
DeserializeClasses();
ProcessDeferredReferences();
DeserializeExports();
DeserializeExports(skip_exports);
DCHECK_EQ(0, deferred_references_->Length());
return !has_error();
......@@ -2041,13 +2041,29 @@ void WebSnapshotDeserializer::DeserializeArrays() {
}
}
void WebSnapshotDeserializer::DeserializeExports() {
void WebSnapshotDeserializer::DeserializeExports(bool skip_exports) {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Exports);
uint32_t count;
if (!deserializer_.ReadUint32(&count) || count > kMaxItemCount) {
Throw("Malformed export table");
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
// object.
Handle<JSGlobalObject> global = isolate_->global_object();
......
......@@ -278,7 +278,8 @@ class V8_EXPORT WebSnapshotDeserializer
size_t buffer_size);
WebSnapshotDeserializer(Isolate* isolate, Handle<Script> snapshot_as_script);
~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.
uint32_t string_count() const { return string_count_; }
......@@ -304,7 +305,7 @@ class V8_EXPORT WebSnapshotDeserializer
base::Vector<const uint8_t> buffer);
base::Vector<const uint8_t> ExtractScriptBuffer(
Isolate* isolate, Handle<Script> snapshot_as_script);
bool DeserializeSnapshot();
bool DeserializeSnapshot(bool skip_exports);
bool DeserializeScript();
WebSnapshotDeserializer(const WebSnapshotDeserializer&) = delete;
......@@ -323,7 +324,7 @@ class V8_EXPORT WebSnapshotDeserializer
void DeserializeClasses();
void DeserializeArrays();
void DeserializeObjects();
void DeserializeExports();
void DeserializeExports(bool skip_exports);
Object ReadValue(
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