Heap Snapshot should include different Edge types and data (Property, Index, Variable)
[WebKit-https.git] / Source / JavaScriptCore / heap / HeapSnapshotBuilder.h
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef HeapSnapshotBuilder_h
27 #define HeapSnapshotBuilder_h
28
29 #include <functional>
30 #include <wtf/Lock.h>
31 #include <wtf/Vector.h>
32 #include <wtf/text/UniquedStringImpl.h>
33 #include <wtf/text/WTFString.h>
34
35 namespace JSC {
36
37 class HeapProfiler;
38 class HeapSnapshot;
39 class JSCell;
40
41 struct HeapSnapshotNode {
42     HeapSnapshotNode(JSCell* cell, unsigned identifier)
43         : cell(cell)
44         , identifier(identifier)
45     { }
46
47     JSCell* cell;
48     unsigned identifier;
49 };
50
51 enum class EdgeType : uint8_t {
52     Internal,     // Normal strong reference. No name.
53     Property,     // Named property. In `object.property` the name is "property"
54     Index,        // Indexed property. In `array[0]` name is index "0".
55     Variable,     // Variable held by a scope. In `let x, f=() => x++` name is "x" in f's captured scope.
56     // FIXME: <https://webkit.org/b/154934> Heap Snapshot should include "Weak" edges
57 };
58
59 struct HeapSnapshotEdge {
60     HeapSnapshotEdge(JSCell* from, JSCell* to)
61         : from(from)
62         , to(to)
63         , type(EdgeType::Internal)
64     { }
65
66     HeapSnapshotEdge(JSCell* from, JSCell* to, EdgeType type, UniquedStringImpl* name)
67         : from(from)
68         , to(to)
69         , type(type)
70     {
71         ASSERT(type == EdgeType::Property || type == EdgeType::Variable);
72         u.name = name;
73     }
74
75     HeapSnapshotEdge(JSCell* from, JSCell* to, uint32_t index)
76         : from(from)
77         , to(to)
78         , type(EdgeType::Index)
79     {
80         u.index = index;
81     }
82
83     JSCell* from;
84     JSCell* to;
85     EdgeType type;
86     union {
87         UniquedStringImpl* name;
88         uint32_t index;
89     } u;
90 };
91
92 class JS_EXPORT_PRIVATE HeapSnapshotBuilder {
93     WTF_MAKE_FAST_ALLOCATED;
94 public:
95     HeapSnapshotBuilder(HeapProfiler&);
96     ~HeapSnapshotBuilder();
97
98     static unsigned nextAvailableObjectIdentifier;
99     static unsigned getNextObjectIdentifier();    
100
101     // Performs a garbage collection that builds a snapshot of all live cells.
102     void buildSnapshot();
103
104     // A marked cell.
105     void appendNode(JSCell*);
106
107     // A reference from one cell to another.
108     void appendEdge(JSCell* from, JSCell* to);
109     void appendPropertyNameEdge(JSCell* from, JSCell* to, UniquedStringImpl* propertyName);
110     void appendVariableNameEdge(JSCell* from, JSCell* to, UniquedStringImpl* variableName);
111     void appendIndexEdge(JSCell* from, JSCell* to, uint32_t index);
112
113     String json();
114     String json(std::function<bool (const HeapSnapshotNode&)> allowNodeCallback);
115
116 private:
117     // Finalized snapshots are not modified during building. So searching them
118     // for an existing node can be done concurrently without a lock.
119     bool hasExistingNodeForCell(JSCell*);
120
121     HeapProfiler& m_profiler;
122
123     // SlotVisitors run in parallel.
124     Lock m_buildingNodeMutex;
125     std::unique_ptr<HeapSnapshot> m_snapshot;
126     Lock m_buildingEdgeMutex;
127     Vector<HeapSnapshotEdge> m_edges;
128 };
129
130 } // namespace JSC
131
132 #endif // HeapSnapshotBuilder_h