Prechádzať zdrojové kódy

LibJS+LibWebView+WebContent+Ladybird: Output GC-graph into a file

Instead of displaying a massive JSON in stdout, it's more practical
to save the GC-graph to a file.
Aliaksandr Kalenik 1 rok pred
rodič
commit
57e5abae92

+ 6 - 1
Ladybird/Qt/BrowserWindow.cpp

@@ -278,7 +278,12 @@ BrowserWindow::BrowserWindow(Vector<URL> const& initial_urls, WebView::CookieJar
     auto* dump_gc_graph_action = new QAction("Dump GC graph", this);
     debug_menu->addAction(dump_gc_graph_action);
     QObject::connect(dump_gc_graph_action, &QAction::triggered, this, [this] {
-        debug_request("dump-gc-graph");
+        if (m_current_tab) {
+            auto gc_graph_path = m_current_tab->view().dump_gc_graph();
+            warnln("\033[33;1mDumped GC-graph into {}"
+                   "\033[0m",
+                gc_graph_path);
+        }
     });
 
     auto* clear_cache_action = new QAction("Clear &Cache", this);

+ 4 - 4
Userland/Libraries/LibJS/Heap/Heap.cpp

@@ -192,7 +192,7 @@ public:
         }
     }
 
-    void dump()
+    AK::JsonObject dump()
     {
         auto graph = AK::JsonObject();
         for (auto& it : m_graph) {
@@ -233,7 +233,7 @@ public:
             graph.set(DeprecatedString::number(it.key), node);
         }
 
-        dbgln("{}", graph.to_deprecated_string());
+        return graph;
     }
 
 private:
@@ -253,14 +253,14 @@ private:
     FlatPtr m_max_block_address;
 };
 
-void Heap::dump_graph()
+AK::JsonObject Heap::dump_graph()
 {
     HashMap<Cell*, HeapRoot> roots;
     gather_roots(roots);
     GraphConstructorVisitor visitor(*this, roots);
     vm().bytecode_interpreter().visit_edges(visitor);
     visitor.visit_all_cells();
-    visitor.dump();
+    return visitor.dump();
 }
 
 void Heap::collect_garbage(CollectionType collection_type, bool print_report)

+ 1 - 1
Userland/Libraries/LibJS/Heap/Heap.h

@@ -64,7 +64,7 @@ public:
     };
 
     void collect_garbage(CollectionType = CollectionType::CollectGarbage, bool print_report = false);
-    void dump_graph();
+    AK::JsonObject dump_graph();
 
     bool should_collect_on_every_allocation() const { return m_should_collect_on_every_allocation; }
     void set_should_collect_on_every_allocation(bool b) { m_should_collect_on_every_allocation = b; }

+ 15 - 2
Userland/Libraries/LibWebView/ViewImplementation.cpp

@@ -403,8 +403,8 @@ static ErrorOr<LexicalPath> save_screenshot(Gfx::ShareableBitmap const& bitmap)
 
     auto encoded = TRY(Gfx::PNGWriter::encode(*bitmap.bitmap()));
 
-    auto screenshot_file = TRY(Core::File::open(path.string(), Core::File::OpenMode::Write));
-    TRY(screenshot_file->write_until_depleted(encoded));
+    auto dump_file = TRY(Core::File::open(path.string(), Core::File::OpenMode::Write));
+    TRY(dump_file->write_until_depleted(encoded));
 
     return path;
 }
@@ -432,6 +432,19 @@ ErrorOr<LexicalPath> ViewImplementation::take_dom_node_screenshot(i32 node_id)
     return save_screenshot(bitmap);
 }
 
+ErrorOr<LexicalPath> ViewImplementation::dump_gc_graph()
+{
+    auto gc_graph_json = client().dump_gc_graph();
+
+    LexicalPath path { Core::StandardPaths::tempfile_directory() };
+    path = path.append(TRY(Core::DateTime::now().to_string("gc-graph-%Y-%m-%d-%H-%M-%S.json"sv)));
+
+    auto screenshot_file = TRY(Core::File::open(path.string(), Core::File::OpenMode::Write));
+    TRY(screenshot_file->write_until_depleted(gc_graph_json.bytes()));
+
+    return path;
+}
+
 void ViewImplementation::set_user_style_sheet(String source)
 {
     client().async_set_user_style(move(source));

+ 2 - 0
Userland/Libraries/LibWebView/ViewImplementation.h

@@ -99,6 +99,8 @@ public:
     ErrorOr<LexicalPath> take_screenshot(ScreenshotType);
     ErrorOr<LexicalPath> take_dom_node_screenshot(i32);
 
+    ErrorOr<LexicalPath> dump_gc_graph();
+
     void set_user_style_sheet(String source);
     // Load Native.css as the User style sheet, which attempts to make WebView content look as close to
     // native GUI widgets as possible.

+ 6 - 5
Userland/Services/WebContent/ConnectionFromClient.cpp

@@ -443,11 +443,6 @@ void ConnectionFromClient::debug_request(DeprecatedString const& request, Deprec
         return;
     }
 
-    if (request == "dump-gc-graph") {
-        Web::Bindings::main_thread_vm().heap().dump_graph();
-        return;
-    }
-
     if (request == "set-line-box-borders") {
         bool state = argument == "on";
         page().set_should_show_line_box_borders(state);
@@ -876,6 +871,12 @@ Messages::WebContentServer::TakeDomNodeScreenshotResponse ConnectionFromClient::
     return bitmap->to_shareable_bitmap();
 }
 
+Messages::WebContentServer::DumpGcGraphResponse ConnectionFromClient::dump_gc_graph()
+{
+    auto gc_graph_json = Web::Bindings::main_thread_vm().heap().dump_graph();
+    return MUST(String::from_deprecated_string(gc_graph_json.to_deprecated_string()));
+}
+
 Messages::WebContentServer::GetSelectedTextResponse ConnectionFromClient::get_selected_text()
 {
     return page().page().focused_context().selected_text();

+ 2 - 0
Userland/Services/WebContent/ConnectionFromClient.h

@@ -124,6 +124,8 @@ private:
     virtual Messages::WebContentServer::TakeDocumentScreenshotResponse take_document_screenshot() override;
     virtual Messages::WebContentServer::TakeDomNodeScreenshotResponse take_dom_node_screenshot(i32 node_id) override;
 
+    virtual Messages::WebContentServer::DumpGcGraphResponse dump_gc_graph() override;
+
     virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries() override;
     virtual Messages::WebContentServer::GetSessionStorageEntriesResponse get_session_storage_entries() override;
 

+ 2 - 0
Userland/Services/WebContent/WebContentServer.ipc

@@ -59,6 +59,8 @@ endpoint WebContentServer
     take_document_screenshot() => (Gfx::ShareableBitmap data)
     take_dom_node_screenshot(i32 node_id) => (Gfx::ShareableBitmap data)
 
+    dump_gc_graph() => (String json)
+
     run_javascript(DeprecatedString js_source) =|
 
     dump_layout_tree() => (DeprecatedString dump)