1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-01 10:48:13 +00:00

LibJS: Add GC graph dumper

This change introduces a very basic GC graph dumper. The `dump_graph()`
function outputs JSON data that contains information about all nodes in
the graph, including their class types and edges.

Root nodes will have a property indicating their root type or source
location if the root is captured by a SafeFunction. It would be useful
to add source location for other types of roots in the future.

Output JSON dump have following format:
```json
    "4908721208": {
        "class_name": "Accessor",
        "edges": [
            "4909298232",
            "4909297976"
        ]
    },
    "4907520440": {
        "root": "SafeFunction Optional Optional.h:137",
        "class_name": "Realm",
        "edges": [
            "4908269624",
            "4924821560",
            "4908409240",
            "4908483960",
            "4924527672"
        ]
    },
    "4908251320": {
        "class_name": "CSSStyleRule",
        "edges": [
            "4908302648",
            "4925101656",
            "4908251192"
        ]
    },
```
This commit is contained in:
Aliaksandr Kalenik 2023-08-17 15:34:19 +02:00 committed by Andreas Kling
parent ee29a21ae8
commit 0ff29349e6
7 changed files with 200 additions and 54 deletions

View file

@ -19,6 +19,7 @@
#include <LibJS/Heap/Cell.h>
#include <LibJS/Heap/CellAllocator.h>
#include <LibJS/Heap/Handle.h>
#include <LibJS/Heap/HeapRootTypeOrLocation.h>
#include <LibJS/Heap/Internals.h>
#include <LibJS/Heap/MarkedVector.h>
#include <LibJS/Runtime/Completion.h>
@ -58,6 +59,7 @@ public:
};
void collect_garbage(CollectionType = CollectionType::CollectGarbage, bool print_report = false);
void 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; }
@ -83,10 +85,10 @@ private:
Cell* allocate_cell(size_t);
void gather_roots(HashTable<Cell*>&);
void gather_conservative_roots(HashTable<Cell*>&);
void gather_asan_fake_stack_roots(HashTable<FlatPtr>&, FlatPtr);
void mark_live_cells(HashTable<Cell*> const& live_cells);
void gather_roots(HashMap<Cell*, HeapRootTypeOrLocation>&);
void gather_conservative_roots(HashMap<Cell*, HeapRootTypeOrLocation>&);
void gather_asan_fake_stack_roots(HashMap<FlatPtr, HeapRootTypeOrLocation>&, FlatPtr);
void mark_live_cells(HashMap<Cell*, HeapRootTypeOrLocation> const& live_cells);
void finalize_unmarked_cells();
void sweep_dead_cells(bool print_report, Core::ElapsedTimer const&);