GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/memory_tracker.h Lines: 10 10 100.0 %
Date: 2019-02-23 22:23:05 Branches: 1 2 50.0 %

Line Branch Exec Source
1
#ifndef SRC_MEMORY_TRACKER_H_
2
#define SRC_MEMORY_TRACKER_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include <unordered_map>
7
#include <queue>
8
#include <stack>
9
#include <string>
10
#include <limits>
11
#include <uv.h>
12
#include "aliased_buffer.h"
13
#include "v8-profiler.h"
14
15
namespace node {
16
17
// Set the node name of a MemoryRetainer to klass
18
#define SET_MEMORY_INFO_NAME(Klass)                                            \
19
  inline std::string MemoryInfoName() const override { return #Klass; }
20
21
// Set the self size of a MemoryRetainer to the stack-allocated size of a
22
// certain class
23
#define SET_SELF_SIZE(Klass)                                                   \
24
  inline size_t SelfSize() const override { return sizeof(Klass); }
25
26
// Used when there is no additional fields to track
27
#define SET_NO_MEMORY_INFO()                                                   \
28
  inline void MemoryInfo(node::MemoryTracker* tracker) const override {}
29
30
class MemoryTracker;
31
class MemoryRetainerNode;
32
33
namespace crypto {
34
class NodeBIO;
35
}
36
37
/* Example:
38
 *
39
 * class ExampleRetainer : public MemoryRetainer {
40
 *   public:
41
 *     // Or use SET_NO_MEMORY_INFO() when there is no additional fields
42
 *     // to track.
43
 *     void MemoryInfo(MemoryTracker* tracker) const override {
44
 *       // Node name and size comes from the MemoryInfoName and SelfSize of
45
 *       // AnotherRetainerClass
46
 *       tracker->TrackField("another_retainer", another_retainer_);
47
 *       // Specify node name and size explicitly
48
 *       tracker->TrackFieldWithSize("internal_member",
49
 *                                   internal_member_.size(),
50
 *                                   "InternalClass");
51
 *       // Node name falls back to the edge name,
52
 *       // elements in the container appear as grandchildren nodes
53
 *       tracker->TrackField("vector", vector_);
54
 *       // Node name and size come from the JS object
55
 *       tracker->TrackField("target", target_);
56
 *     }
57
 *
58
 *     // Or use SET_MEMORY_INFO_NAME(ExampleRetainer)
59
 *     std::string MemoryInfoName() const override {
60
 *       return "ExampleRetainer";
61
 *     }
62
 *
63
 *     // Or use SET_SELF_SIZE(ExampleRetainer)
64
 *     size_t SelfSize() const override {
65
 *       return sizeof(ExampleRetainer);
66
 *     }
67
 *
68
 *     // Note: no need to implement these two methods when implementing
69
 *     // a BaseObject or an AsyncWrap class
70
 *     bool IsRootNode() const override { return !wrapped_.IsWeak(); }
71
 *     v8::Local<v8::Object> WrappedObject() const override {
72
 *       return node::PersistentToLocal::Default(wrapped_);
73
 *     }
74
 *   private:
75
 *     AnotherRetainerClass another_retainer_;
76
 *     InternalClass internal_member_;
77
 *     std::vector<uv_async_t> vector_;
78
 *     node::Persistent<Object> target_;
79
 *
80
 *     node::Persistent<Object> wrapped_;
81
 * }
82
 *
83
 * This creates the following graph:
84
 *   Node / ExampleRetainer
85
 *    |> another_retainer :: Node / AnotherRetainerClass
86
 *    |> internal_member :: Node / InternalClass
87
 *    |> vector :: Node / vector (elements will be grandchildren)
88
 *        |> [1] :: Node / uv_async_t (uv_async_t has predefined names)
89
 *        |> [2] :: Node / uv_async_t
90
 *        |> ...
91
 *    |> target :: TargetClass (JS class name of the target object)
92
 *    |> wrapped :: WrappedClass (JS class name of the wrapped object)
93
 *        |> wrapper :: Node / ExampleRetainer (back reference)
94
 */
95
771122
class MemoryRetainer {
96
 public:
97
825158
  virtual ~MemoryRetainer() {}
98
99
  // Subclasses should implement these methods to provide information
100
  // for the V8 heap snapshot generator.
101
  // The MemoryInfo() method is assumed to be called within a context
102
  // where all the edges start from the node of the current retainer,
103
  // and point to the nodes as specified by tracker->Track* calls.
104
  virtual void MemoryInfo(MemoryTracker* tracker) const = 0;
105
  virtual std::string MemoryInfoName() const = 0;
106
  virtual size_t SelfSize() const = 0;
107
108
22
  virtual v8::Local<v8::Object> WrappedObject() const {
109
22
    return v8::Local<v8::Object>();
110
  }
111
112
22
  virtual bool IsRootNode() const { return false; }
113
};
114
115
32
class MemoryTracker {
116
 public:
117
  // Used to specify node name and size explicitly
118
  inline void TrackFieldWithSize(const char* edge_name,
119
                                 size_t size,
120
                                 const char* node_name = nullptr);
121
  // Shortcut to extract the underlying object out of the smart pointer
122
  template <typename T>
123
  inline void TrackField(const char* edge_name,
124
                         const std::unique_ptr<T>& value,
125
                         const char* node_name = nullptr);
126
127
  // For containers, the elements will be graphed as grandchildren nodes
128
  // if the container is not empty.
129
  // By default, we assume the parent count the stack size of the container
130
  // into its SelfSize so that will be subtracted from the parent size when we
131
  // spin off a new node for the container.
132
  // TODO(joyeecheung): use RTTI to retrieve the class name at runtime?
133
  template <typename T, typename Iterator = typename T::const_iterator>
134
  inline void TrackField(const char* edge_name,
135
                         const T& value,
136
                         const char* node_name = nullptr,
137
                         const char* element_name = nullptr,
138
                         bool subtract_from_self = true);
139
  template <typename T>
140
  inline void TrackField(const char* edge_name,
141
                         const std::queue<T>& value,
142
                         const char* node_name = nullptr,
143
                         const char* element_name = nullptr);
144
  template <typename T, typename U>
145
  inline void TrackField(const char* edge_name,
146
                         const std::pair<T, U>& value,
147
                         const char* node_name = nullptr);
148
149
  // For the following types, node_name will be ignored and predefined names
150
  // will be used instead. They are only in the signature for template
151
  // expansion.
152
  inline void TrackField(const char* edge_name,
153
                         const MemoryRetainer& value,
154
                         const char* node_name = nullptr);
155
  inline void TrackField(const char* edge_name,
156
                         const MemoryRetainer* value,
157
                         const char* node_name = nullptr);
158
  template <typename T>
159
  inline void TrackField(const char* edge_name,
160
                         const std::basic_string<T>& value,
161
                         const char* node_name = nullptr);
162
  template <typename T,
163
            typename test_for_number = typename std::
164
                enable_if<std::numeric_limits<T>::is_specialized, bool>::type,
165
            typename dummy = bool>
166
  inline void TrackField(const char* edge_name,
167
                         const T& value,
168
                         const char* node_name = nullptr);
169
  template <typename T, typename Traits>
170
  inline void TrackField(const char* edge_name,
171
                         const v8::Persistent<T, Traits>& value,
172
                         const char* node_name = nullptr);
173
  template <typename T>
174
  inline void TrackField(const char* edge_name,
175
                         const v8::Local<T>& value,
176
                         const char* node_name = nullptr);
177
  template <typename T>
178
  inline void TrackField(const char* edge_name,
179
                         const MallocedBuffer<T>& value,
180
                         const char* node_name = nullptr);
181
  inline void TrackField(const char* edge_name,
182
                         const uv_buf_t& value,
183
                         const char* node_name = nullptr);
184
  inline void TrackField(const char* edge_name,
185
                         const uv_timer_t& value,
186
                         const char* node_name = nullptr);
187
  inline void TrackField(const char* edge_name,
188
                         const uv_async_t& value,
189
                         const char* node_name = nullptr);
190
  template <class NativeT, class V8T>
191
  inline void TrackField(const char* edge_name,
192
                         const AliasedBuffer<NativeT, V8T>& value,
193
                         const char* node_name = nullptr);
194
195
  // Put a memory container into the graph, create an edge from
196
  // the current node if there is one on the stack.
197
  inline void Track(const MemoryRetainer* retainer,
198
                    const char* edge_name = nullptr);
199
200
95
  inline v8::EmbedderGraph* graph() { return graph_; }
201
117
  inline v8::Isolate* isolate() { return isolate_; }
202
203
32
  inline explicit MemoryTracker(v8::Isolate* isolate,
204
                                v8::EmbedderGraph* graph)
205
32
    : isolate_(isolate), graph_(graph) {}
206
207
 private:
208
  typedef std::unordered_map<const MemoryRetainer*, MemoryRetainerNode*>
209
      NodeMap;
210
211
  inline MemoryRetainerNode* CurrentNode() const;
212
  inline MemoryRetainerNode* AddNode(const MemoryRetainer* retainer,
213
                                     const char* edge_name = nullptr);
214
  inline MemoryRetainerNode* PushNode(const MemoryRetainer* retainer,
215
                                      const char* edge_name = nullptr);
216
  inline MemoryRetainerNode* AddNode(const char* node_name,
217
                                     size_t size,
218
                                     const char* edge_name = nullptr);
219
  inline MemoryRetainerNode* PushNode(const char* node_name,
220
                                      size_t size,
221
                                      const char* edge_name = nullptr);
222
  inline void PopNode();
223
224
  v8::Isolate* isolate_;
225
  v8::EmbedderGraph* graph_;
226
  std::stack<MemoryRetainerNode*> node_stack_;
227
  NodeMap seen_;
228
};
229
230
}  // namespace node
231
232
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
233
234
#endif  // SRC_MEMORY_TRACKER_H_