mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 10:52:44 +00:00 
			
		
		
		
	 0ff29349e6
			
		
	
	
		0ff29349e6
		
	
	
	
	
		
			
			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"
        ]
    },
```
		
	
			
		
			
				
	
	
		
			81 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
 | |
|  * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <AK/HashMap.h>
 | |
| #include <AK/IntrusiveList.h>
 | |
| #include <AK/Vector.h>
 | |
| #include <LibJS/Forward.h>
 | |
| #include <LibJS/Heap/Cell.h>
 | |
| #include <LibJS/Heap/HeapRootTypeOrLocation.h>
 | |
| 
 | |
| namespace JS {
 | |
| 
 | |
| class MarkedVectorBase {
 | |
| public:
 | |
|     virtual void gather_roots(HashMap<Cell*, JS::HeapRootTypeOrLocation>&) const = 0;
 | |
| 
 | |
| protected:
 | |
|     explicit MarkedVectorBase(Heap&);
 | |
|     ~MarkedVectorBase();
 | |
| 
 | |
|     MarkedVectorBase& operator=(MarkedVectorBase const&);
 | |
| 
 | |
|     Heap* m_heap { nullptr };
 | |
|     IntrusiveListNode<MarkedVectorBase> m_list_node;
 | |
| 
 | |
| public:
 | |
|     using List = IntrusiveList<&MarkedVectorBase::m_list_node>;
 | |
| };
 | |
| 
 | |
| template<typename T, size_t inline_capacity>
 | |
| class MarkedVector final
 | |
|     : public MarkedVectorBase
 | |
|     , public Vector<T, inline_capacity> {
 | |
| 
 | |
| public:
 | |
|     explicit MarkedVector(Heap& heap)
 | |
|         : MarkedVectorBase(heap)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     virtual ~MarkedVector() = default;
 | |
| 
 | |
|     MarkedVector(MarkedVector const& other)
 | |
|         : MarkedVectorBase(*other.m_heap)
 | |
|         , Vector<T, inline_capacity>(other)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     MarkedVector(MarkedVector&& other)
 | |
|         : MarkedVectorBase(*other.m_heap)
 | |
|         , Vector<T, inline_capacity>(move(static_cast<Vector<T, inline_capacity>&>(other)))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     MarkedVector& operator=(MarkedVector const& other)
 | |
|     {
 | |
|         Vector<T, inline_capacity>::operator=(other);
 | |
|         MarkedVectorBase::operator=(other);
 | |
|         return *this;
 | |
|     }
 | |
| 
 | |
|     virtual void gather_roots(HashMap<Cell*, JS::HeapRootTypeOrLocation>& roots) const override
 | |
|     {
 | |
|         for (auto& value : *this) {
 | |
|             if constexpr (IsSame<Value, T>) {
 | |
|                 if (value.is_cell())
 | |
|                     roots.set(&const_cast<T&>(value).as_cell(), HeapRootType::MarkedVector);
 | |
|             } else {
 | |
|                 roots.set(value, HeapRootType::MarkedVector);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| };
 | |
| 
 | |
| }
 |