HeapSnapshotBuilder.h [plain text]
#pragma once
#include "SlotVisitor.h"
#include <functional>
#include <wtf/Lock.h>
#include <wtf/Vector.h>
#include <wtf/text/UniquedStringImpl.h>
#include <wtf/text/WTFString.h>
namespace JSC {
class ConservativeRoots;
class HeapProfiler;
class HeapSnapshot;
class JSCell;
typedef unsigned NodeIdentifier;
struct HeapSnapshotNode {
HeapSnapshotNode(JSCell* cell, unsigned identifier)
: cell(cell)
, identifier(identifier)
{ }
JSCell* cell;
NodeIdentifier identifier;
};
enum class EdgeType : uint8_t {
Internal, Property, Index, Variable, };
struct HeapSnapshotEdge {
HeapSnapshotEdge(JSCell* fromCell, JSCell* toCell)
: type(EdgeType::Internal)
{
from.cell = fromCell;
to.cell = toCell;
}
HeapSnapshotEdge(JSCell* fromCell, JSCell* toCell, EdgeType type, UniquedStringImpl* name)
: type(type)
{
ASSERT(type == EdgeType::Property || type == EdgeType::Variable);
from.cell = fromCell;
to.cell = toCell;
u.name = name;
}
HeapSnapshotEdge(JSCell* fromCell, JSCell* toCell, uint32_t index)
: type(EdgeType::Index)
{
from.cell = fromCell;
to.cell = toCell;
u.index = index;
}
union {
JSCell *cell;
NodeIdentifier identifier;
} from;
union {
JSCell *cell;
NodeIdentifier identifier;
} to;
union {
UniquedStringImpl* name;
uint32_t index;
} u;
EdgeType type;
};
class JS_EXPORT_PRIVATE HeapSnapshotBuilder {
WTF_MAKE_FAST_ALLOCATED;
public:
enum SnapshotType { InspectorSnapshot, GCDebuggingSnapshot };
HeapSnapshotBuilder(HeapProfiler&, SnapshotType = SnapshotType::InspectorSnapshot);
~HeapSnapshotBuilder();
static void resetNextAvailableObjectIdentifier();
void buildSnapshot();
void appendNode(JSCell*);
void appendEdge(JSCell* from, JSCell* to, SlotVisitor::RootMarkReason);
void appendPropertyNameEdge(JSCell* from, JSCell* to, UniquedStringImpl* propertyName);
void appendVariableNameEdge(JSCell* from, JSCell* to, UniquedStringImpl* variableName);
void appendIndexEdge(JSCell* from, JSCell* to, uint32_t index);
void setOpaqueRootReachabilityReasonForCell(JSCell*, const char*);
void setWrappedObjectForCell(JSCell*, void*);
void setLabelForCell(JSCell*, const String&);
String json();
String json(Function<bool (const HeapSnapshotNode&)> allowNodeCallback);
private:
static NodeIdentifier nextAvailableObjectIdentifier;
static NodeIdentifier getNextObjectIdentifier();
bool previousSnapshotHasNodeForCell(JSCell*, NodeIdentifier&);
String descriptionForCell(JSCell*) const;
struct RootData {
const char* reachabilityFromOpaqueRootReasons { nullptr };
SlotVisitor::RootMarkReason markReason { SlotVisitor::RootMarkReason::None };
};
HeapProfiler& m_profiler;
Lock m_buildingNodeMutex;
std::unique_ptr<HeapSnapshot> m_snapshot;
Lock m_buildingEdgeMutex;
Vector<HeapSnapshotEdge> m_edges;
HashMap<JSCell*, RootData> m_rootData;
HashMap<JSCell*, void*> m_wrappedObjectPointers;
HashMap<JSCell*, String> m_cellLabels;
SnapshotType m_snapshotType;
};
}