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-inl.h Lines: 139 145 95.9 %
Date: 2019-07-28 22:34:34 Branches: 80 130 61.5 %

Line Branch Exec Source
1
#ifndef SRC_MEMORY_TRACKER_INL_H_
2
#define SRC_MEMORY_TRACKER_INL_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "memory_tracker.h"
7
8
namespace node {
9
10
// Fallback edge_name if node_name is not available, or "" if edge_name
11
// is not available either.
12
4923
inline const char* GetNodeName(const char* node_name, const char* edge_name) {
13
4923
  if (node_name != nullptr) {
14
4666
    return node_name;
15
  }
16
257
  if (edge_name != nullptr) {
17
257
    return edge_name;
18
  }
19
  return "";
20
}
21
22
11914
class MemoryRetainerNode : public v8::EmbedderGraph::Node {
23
 public:
24
681
  inline MemoryRetainerNode(MemoryTracker* tracker,
25
                                     const MemoryRetainer* retainer)
26
681
      : retainer_(retainer) {
27
681
    CHECK_NOT_NULL(retainer_);
28
681
    v8::HandleScope handle_scope(tracker->isolate());
29
681
    v8::Local<v8::Object> obj = retainer_->WrappedObject();
30
1032
    if (!obj.IsEmpty()) wrapper_node_ = tracker->graph()->V8Node(obj);
31
32
681
    name_ = retainer_->MemoryInfoName();
33
681
    size_ = retainer_->SelfSize();
34
681
  }
35
36
5276
  inline MemoryRetainerNode(MemoryTracker* tracker,
37
                                     const char* name,
38
                                     size_t size,
39
                                     bool is_root_node = false)
40
5276
      : retainer_(nullptr) {
41
5276
    name_ = name;
42
5276
    size_ = size;
43
5276
    is_root_node_ = is_root_node;
44
5276
  }
45
46
5957
  const char* Name() override { return name_.c_str(); }
47
7878
  const char* NamePrefix() override { return "Node /"; }
48
5957
  size_t SizeInBytes() override { return size_; }
49
  // TODO(addaleax): Merging this with the "official" WrapperNode() method
50
  // seems to lose accuracy, e.g. SizeInBytes() is disregarded.
51
  // Figure out whether to do anything about that.
52
1383
  Node* JSWrapperNode() { return wrapper_node_; }
53
54
9993
  bool IsRootNode() override {
55
9993
    if (retainer_ != nullptr) {
56
1133
      return retainer_->IsRootNode();
57
    }
58
8860
    return is_root_node_;
59
  }
60
61
 private:
62
  friend class MemoryTracker;
63
64
  // If retainer_ is not nullptr, then it must have a wrapper_node_,
65
  // and we have
66
  // name_ == retainer_->MemoryInfoName()
67
  // size_ == retainer_->SelfSize()
68
  // is_root_node_ == retainer_->IsRootNode()
69
  const MemoryRetainer* retainer_;
70
  Node* wrapper_node_ = nullptr;
71
72
  // Otherwise (retainer == nullptr), we set these fields in an ad-hoc way
73
  bool is_root_node_ = false;
74
  std::string name_;
75
  size_t size_ = 0;
76
};
77
78
4696
void MemoryTracker::TrackFieldWithSize(const char* edge_name,
79
                                       size_t size,
80
                                       const char* node_name) {
81
4696
  if (size > 0) AddNode(GetNodeName(node_name, edge_name), size, edge_name);
82
4696
}
83
84
210
void MemoryTracker::TrackField(const char* edge_name,
85
                               const MemoryRetainer& value,
86
                               const char* node_name) {
87
210
  TrackField(edge_name, &value);
88
210
}
89
90
646
void MemoryTracker::TrackField(const char* edge_name,
91
                               const MemoryRetainer* value,
92
                               const char* node_name) {
93
1292
  if (value == nullptr) return;
94
646
  auto it = seen_.find(value);
95
646
  if (it != seen_.end()) {
96
20
    graph_->AddEdge(CurrentNode(), it->second, edge_name);
97
  } else {
98
626
    Track(value, edge_name);
99
  }
100
}
101
102
template <typename T>
103
24
void MemoryTracker::TrackField(const char* edge_name,
104
                               const std::unique_ptr<T>& value,
105
                               const char* node_name) {
106

24
  if (value.get() == nullptr) {
107
32
    return;
108
  }
109
16
  TrackField(edge_name, value.get(), node_name);
110
}
111
112
template <typename T, typename Iterator>
113
380
void MemoryTracker::TrackField(const char* edge_name,
114
                               const T& value,
115
                               const char* node_name,
116
                               const char* element_name,
117
                               bool subtract_from_self) {
118
  // If the container is empty, the size has been accounted into the parent's
119
  // self size
120



760
  if (value.begin() == value.end()) return;
121
  // Fall back to edge name if node names are not provided
122









257
  if (CurrentNode() != nullptr && subtract_from_self) {
123
    // Shift the self size of this container out to a separate node
124
257
    CurrentNode()->size_ -= sizeof(T);
125
  }
126
257
  PushNode(GetNodeName(node_name, edge_name), sizeof(T), edge_name);
127




7388
  for (Iterator it = value.begin(); it != value.end(); ++it) {
128
    // Use nullptr as edge names so the elements appear as indexed properties
129
7131
    TrackField(nullptr, *it, element_name);
130
  }
131
257
  PopNode();
132
}
133
134
template <typename T>
135
22
void MemoryTracker::TrackField(const char* edge_name,
136
                               const std::queue<T>& value,
137
                               const char* node_name,
138
                               const char* element_name) {
139
  struct ContainerGetter : public std::queue<T> {
140
22
    static const typename std::queue<T>::container_type& Get(
141
        const std::queue<T>& value) {
142
22
      return value.*&ContainerGetter::c;
143
    }
144
  };
145
146
22
  const auto& container = ContainerGetter::Get(value);
147
22
  TrackField(edge_name, container, node_name, element_name);
148
22
}
149
150
template <typename T, typename test_for_number, typename dummy>
151
83
void MemoryTracker::TrackField(const char* edge_name,
152
                               const T& value,
153
                               const char* node_name) {
154
  // For numbers, creating new nodes is not worth the overhead.
155
83
  CurrentNode()->size_ += sizeof(T);
156
83
}
157
158
template <typename T, typename U>
159
4
void MemoryTracker::TrackField(const char* edge_name,
160
                               const std::pair<T, U>& value,
161
                               const char* node_name) {
162
4
  PushNode(node_name == nullptr ? "pair" : node_name,
163
           sizeof(const std::pair<T, U>),
164
4
           edge_name);
165
  // TODO(joyeecheung): special case if one of these is a number type
166
  // that meets the test_for_number trait so that their sizes don't get
167
  // merged into the pair node
168
4
  TrackField("first", value.first);
169
4
  TrackField("second", value.second);
170
4
  PopNode();
171
4
}
172
173
template <typename T>
174
4496
void MemoryTracker::TrackField(const char* edge_name,
175
                               const std::basic_string<T>& value,
176
                               const char* node_name) {
177
4496
  TrackFieldWithSize(edge_name, value.size() * sizeof(T), "std::basic_string");
178
4496
}
179
180
template <typename T>
181
2193
void MemoryTracker::TrackField(const char* edge_name,
182
                               const v8::Eternal<T>& value,
183
                               const char* node_name) {
184
4386
  TrackField(edge_name, value.Get(isolate_));
185
2193
}
186
187
template <typename T>
188
2
void MemoryTracker::TrackField(const char* edge_name,
189
                               const v8::PersistentBase<T>& value,
190
                               const char* node_name) {
191
4
  TrackField(edge_name, value.Get(isolate_));
192
2
}
193
194
template <typename T>
195
15713
void MemoryTracker::TrackField(const char* edge_name,
196
                               const v8::Local<T>& value,
197
                               const char* node_name) {
198




15713
  if (!value.IsEmpty())
199
29486
    graph_->AddEdge(CurrentNode(), graph_->V8Node(value), edge_name);
200
15713
}
201
202
template <typename T>
203
void MemoryTracker::TrackField(const char* edge_name,
204
                               const MallocedBuffer<T>& value,
205
                               const char* node_name) {
206
  TrackFieldWithSize(edge_name, value.size, "MallocedBuffer");
207
}
208
209
2
void MemoryTracker::TrackField(const char* name,
210
                               const uv_buf_t& value,
211
                               const char* node_name) {
212
2
  TrackFieldWithSize(name, value.len, "uv_buf_t");
213
2
}
214
215
2
void MemoryTracker::TrackField(const char* name,
216
                               const uv_timer_t& value,
217
                               const char* node_name) {
218
2
  TrackFieldWithSize(name, sizeof(value), "uv_timer_t");
219
2
}
220
221
55
void MemoryTracker::TrackField(const char* name,
222
                               const uv_async_t& value,
223
                               const char* node_name) {
224
55
  TrackFieldWithSize(name, sizeof(value), "uv_async_t");
225
55
}
226
227
template <class NativeT, class V8T>
228
462
void MemoryTracker::TrackField(const char* name,
229
                               const AliasedBufferBase<NativeT, V8T>& value,
230
                               const char* node_name) {
231
462
  TrackField(name, value.GetJSArray(), "AliasedBuffer");
232
462
}
233
234
681
void MemoryTracker::Track(const MemoryRetainer* retainer,
235
                          const char* edge_name) {
236
681
  v8::HandleScope handle_scope(isolate_);
237
681
  auto it = seen_.find(retainer);
238
681
  if (it != seen_.end()) {
239
    if (CurrentNode() != nullptr) {
240
      graph_->AddEdge(CurrentNode(), it->second, edge_name);
241
    }
242
681
    return;  // It has already been tracked, no need to call MemoryInfo again
243
  }
244
681
  MemoryRetainerNode* n = PushNode(retainer, edge_name);
245
681
  retainer->MemoryInfo(this);
246
681
  CHECK_EQ(CurrentNode(), n);
247
681
  CHECK_NE(n->size_, 0);
248
681
  PopNode();
249
}
250
251
4
void MemoryTracker::TrackInlineField(const MemoryRetainer* retainer,
252
                                     const char* edge_name) {
253
4
  Track(retainer, edge_name);
254
4
  CHECK(CurrentNode());
255
4
  CurrentNode()->size_ -= retainer->SelfSize();
256
4
}
257
258
28261
MemoryRetainerNode* MemoryTracker::CurrentNode() const {
259
28261
  if (node_stack_.empty()) return nullptr;
260
28210
  return node_stack_.top();
261
}
262
263
681
MemoryRetainerNode* MemoryTracker::AddNode(const MemoryRetainer* retainer,
264
                                           const char* edge_name) {
265
681
  auto it = seen_.find(retainer);
266
681
  if (it != seen_.end()) {
267
    return it->second;
268
  }
269
270
681
  MemoryRetainerNode* n = new MemoryRetainerNode(this, retainer);
271
681
  graph_->AddNode(std::unique_ptr<v8::EmbedderGraph::Node>(n));
272
681
  seen_[retainer] = n;
273
681
  if (CurrentNode() != nullptr) graph_->AddEdge(CurrentNode(), n, edge_name);
274
275
681
  if (n->JSWrapperNode() != nullptr) {
276
351
    graph_->AddEdge(n, n->JSWrapperNode(), "wrapped");
277
351
    graph_->AddEdge(n->JSWrapperNode(), n, "wrapper");
278
  }
279
280
681
  return n;
281
}
282
283
5276
MemoryRetainerNode* MemoryTracker::AddNode(const char* node_name,
284
                                           size_t size,
285
                                           const char* edge_name) {
286
5276
  MemoryRetainerNode* n = new MemoryRetainerNode(this, node_name, size);
287
5276
  graph_->AddNode(std::unique_ptr<v8::EmbedderGraph::Node>(n));
288
289
5276
  if (CurrentNode() != nullptr) graph_->AddEdge(CurrentNode(), n, edge_name);
290
291
5276
  return n;
292
}
293
294
681
MemoryRetainerNode* MemoryTracker::PushNode(const MemoryRetainer* retainer,
295
                                            const char* edge_name) {
296
681
  MemoryRetainerNode* n = AddNode(retainer, edge_name);
297
681
  node_stack_.push(n);
298
681
  return n;
299
}
300
301
610
MemoryRetainerNode* MemoryTracker::PushNode(const char* node_name,
302
                                            size_t size,
303
                                            const char* edge_name) {
304
610
  MemoryRetainerNode* n = AddNode(node_name, size, edge_name);
305
610
  node_stack_.push(n);
306
610
  return n;
307
}
308
309
1291
void MemoryTracker::PopNode() {
310
1291
  node_stack_.pop();
311
1291
}
312
313
}  // namespace node
314
315
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
316
317
#endif  // SRC_MEMORY_TRACKER_INL_H_