Coverage Report

Created: 2025-12-30 08:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/src/memory_tracker-inl.h
Line
Count
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 "cppgc_helpers.h"
7
#include "memory_tracker.h"
8
#include "util-inl.h"
9
10
namespace node {
11
12
// Fallback edge_name if node_name is not available, or "" if edge_name
13
// is not available either.
14
0
inline const char* GetNodeName(const char* node_name, const char* edge_name) {
15
0
  if (node_name != nullptr) {
16
0
    return node_name;
17
0
  }
18
0
  if (edge_name != nullptr) {
19
0
    return edge_name;
20
0
  }
21
0
  return "";
22
0
}
23
24
class MemoryRetainerNode : public v8::EmbedderGraph::Node {
25
 public:
26
  inline MemoryRetainerNode(MemoryTracker* tracker,
27
                            const MemoryRetainer* retainer)
28
0
      : retainer_(retainer) {
29
0
    CHECK_NOT_NULL(retainer_);
30
0
    v8::HandleScope handle_scope(tracker->isolate());
31
0
    v8::Local<v8::Object> obj = retainer_->WrappedObject();
32
0
    if (!obj.IsEmpty())
33
0
      wrapper_node_ = tracker->graph()->V8Node(obj.As<v8::Value>());
34
35
0
    name_ = retainer_->MemoryInfoName();
36
0
    size_ = retainer_->SelfSize();
37
0
    detachedness_ = retainer_->GetDetachedness();
38
0
  }
39
40
  inline MemoryRetainerNode(MemoryTracker* tracker, const CppgcMixin* mixin)
41
0
      : retainer_(mixin) {
42
    // In this case, the MemoryRetainerNode is merely a wrapper
43
    // to be used in the NodeMap and stack. The actual node being using to add
44
    // edges is always the merged wrapper node of the cppgc-managed wrapper.
45
0
    CHECK_NOT_NULL(retainer_);
46
0
    v8::Isolate* isolate = tracker->isolate();
47
0
    v8::HandleScope handle_scope(isolate);
48
0
    v8::Local<v8::Object> obj = mixin->object(isolate);
49
0
    wrapper_node_ = tracker->graph()->V8Node(obj.As<v8::Value>());
50
51
0
    name_ = retainer_->MemoryInfoName();
52
0
    size_ = 0;
53
0
    detachedness_ = retainer_->GetDetachedness();
54
0
  }
55
56
  inline MemoryRetainerNode(MemoryTracker* tracker,
57
                            const char* name,
58
                            size_t size,
59
                            bool is_root_node = false)
60
0
      : retainer_(nullptr) {
61
0
    name_ = name;
62
0
    size_ = size;
63
0
    is_root_node_ = is_root_node;
64
0
  }
65
66
0
  const char* Name() override { return name_; }
67
0
  const char* NamePrefix() override { return "Node /"; }
68
0
  size_t SizeInBytes() override { return size_; }
69
  // TODO(addaleax): Merging this with the "official" WrapperNode() method
70
  // seems to lose accuracy, e.g. SizeInBytes() is disregarded.
71
  // Figure out whether to do anything about that.
72
0
  Node* JSWrapperNode() { return wrapper_node_; }
73
74
0
  bool IsRootNode() override {
75
0
    if (retainer_ != nullptr) {
76
0
      return retainer_->IsRootNode();
77
0
    }
78
0
    return is_root_node_;
79
0
  }
80
81
0
  bool IsCppgcWrapper() const {
82
0
    return retainer_ != nullptr && retainer_->IsCppgcWrapper();
83
0
  }
84
85
0
  v8::EmbedderGraph::Node::Detachedness GetDetachedness() override {
86
0
    return detachedness_;
87
0
  }
88
89
 private:
90
  friend class MemoryTracker;
91
92
  // If retainer_ is not nullptr, then it must have a wrapper_node_,
93
  // and we have
94
  // name_ == retainer_->MemoryInfoName()
95
  // size_ == retainer_->SelfSize()
96
  // is_root_node_ == retainer_->IsRootNode()
97
  const MemoryRetainer* retainer_;
98
  Node* wrapper_node_ = nullptr;
99
100
  // Otherwise (retainer == nullptr), we set these fields in an ad-hoc way
101
  bool is_root_node_ = false;
102
  const char* name_;
103
  size_t size_ = 0;
104
  v8::EmbedderGraph::Node::Detachedness detachedness_ =
105
      v8::EmbedderGraph::Node::Detachedness::kUnknown;
106
};
107
108
void MemoryTracker::TrackFieldWithSize(const char* edge_name,
109
                                       size_t size,
110
0
                                       const char* node_name) {
111
0
  if (size > 0) AddNode(GetNodeName(node_name, edge_name), size, edge_name);
112
0
}
113
114
void MemoryTracker::TrackInlineFieldWithSize(const char* edge_name,
115
                                             size_t size,
116
0
                                             const char* node_name) {
117
0
  if (size > 0) AddNode(GetNodeName(node_name, edge_name), size, edge_name);
118
0
  CHECK(CurrentNode());
119
0
  AdjustCurrentNodeSize(-static_cast<int>(size));
120
0
}
121
122
void MemoryTracker::TrackField(const char* edge_name,
123
                               const MemoryRetainer& value,
124
0
                               const char* node_name) {
125
0
  TrackField(edge_name, &value);
126
0
}
127
128
void MemoryTracker::TrackField(const char* edge_name,
129
                               const MemoryRetainer* value,
130
0
                               const char* node_name) {
131
0
  if (value == nullptr) return;
132
0
  auto it = seen_.find(value);
133
0
  if (it != seen_.end()) {
134
0
    graph_->AddEdge(CurrentNode(), it->second, edge_name);
135
0
  } else {
136
0
    Track(value, edge_name);
137
0
  }
138
0
}
139
140
template <typename T, typename D>
141
void MemoryTracker::TrackField(const char* edge_name,
142
                               const std::unique_ptr<T, D>& value,
143
0
                               const char* node_name) {
144
0
  if (value.get() == nullptr) {
145
0
    return;
146
0
  }
147
0
  TrackField(edge_name, value.get(), node_name);
148
0
}
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::PrincipalRealm, std::__1::default_delete<node::PrincipalRealm> >(char const*, std::__1::unique_ptr<node::PrincipalRealm, std::__1::default_delete<node::PrincipalRealm> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::fs::FSContinuationData, std::__1::default_delete<node::fs::FSContinuationData> >(char const*, std::__1::unique_ptr<node::fs::FSContinuationData, std::__1::default_delete<node::fs::FSContinuationData> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::worker::TransferData, std::__1::default_delete<node::worker::TransferData> >(char const*, std::__1::unique_ptr<node::worker::TransferData, std::__1::default_delete<node::worker::TransferData> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::worker::MessagePortData, std::__1::default_delete<node::worker::MessagePortData> >(char const*, std::__1::unique_ptr<node::worker::MessagePortData, std::__1::default_delete<node::worker::MessagePortData> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::SocketAddressBlockList::Rule, std::__1::default_delete<node::SocketAddressBlockList::Rule> >(char const*, std::__1::unique_ptr<node::SocketAddressBlockList::Rule, std::__1::default_delete<node::SocketAddressBlockList::Rule> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::BackingStore, std::__1::default_delete<v8::BackingStore> >(char const*, std::__1::unique_ptr<v8::BackingStore, std::__1::default_delete<v8::BackingStore> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::DataQueue::Entry, std::__1::default_delete<node::DataQueue::Entry> >(char const*, std::__1::unique_ptr<node::DataQueue::Entry, std::__1::default_delete<node::DataQueue::Entry> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::quic::Session::Application, std::__1::default_delete<node::quic::Session::Application> >(char const*, std::__1::unique_ptr<node::quic::Session::Application, std::__1::default_delete<node::quic::Session::Application> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::quic::Session::Impl, std::__1::default_delete<node::quic::Session::Impl> >(char const*, std::__1::unique_ptr<node::quic::Session::Impl, std::__1::default_delete<node::quic::Session::Impl> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::quic::TLSSession, std::__1::default_delete<node::quic::TLSSession> >(char const*, std::__1::unique_ptr<node::quic::TLSSession, std::__1::default_delete<node::quic::TLSSession> > const&, char const*)
149
150
template <typename T>
151
void MemoryTracker::TrackField(const char* edge_name,
152
                               const std::shared_ptr<T>& value,
153
0
                               const char* node_name) {
154
0
  if (value.get() == nullptr) {
155
0
    return;
156
0
  }
157
0
  TrackField(edge_name, value.get(), node_name);
158
0
}
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::DataQueue>(char const*, std::__1::shared_ptr<node::DataQueue> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::worker::locks::Lock>(char const*, std::__1::shared_ptr<node::worker::locks::Lock> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::BackingStore>(char const*, std::__1::shared_ptr<v8::BackingStore> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::worker::Message>(char const*, std::__1::shared_ptr<node::worker::Message> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::SocketAddress>(char const*, std::__1::shared_ptr<node::SocketAddress> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::crypto::ManagedX509>(char const*, std::__1::shared_ptr<node::crypto::ManagedX509> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::Histogram>(char const*, std::__1::shared_ptr<node::Histogram> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::quic::TLSContext>(char const*, std::__1::shared_ptr<node::quic::TLSContext> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::DataQueue::Reader>(char const*, std::__1::shared_ptr<node::DataQueue::Reader> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::quic::Packet::Data>(char const*, std::__1::shared_ptr<node::quic::Packet::Data> const&, char const*)
159
160
template <typename T, bool kIsWeak>
161
void MemoryTracker::TrackField(const char* edge_name,
162
                               const BaseObjectPtrImpl<T, kIsWeak>& value,
163
0
                               const char* node_name) {
164
0
  if (value.get() == nullptr || kIsWeak) return;
165
0
  TrackField(edge_name, value.get(), node_name);
166
0
}
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::sqlite::DatabaseSync, true>(char const*, node::BaseObjectPtrImpl<node::sqlite::DatabaseSync, true> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::quic::Endpoint::UDP::Impl, true>(char const*, node::BaseObjectPtrImpl<node::quic::Endpoint::UDP::Impl, true> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::quic::Endpoint, true>(char const*, node::BaseObjectPtrImpl<node::quic::Endpoint, true> const&, char const*)
167
168
template <typename T, typename Iterator>
169
void MemoryTracker::TrackField(const char* edge_name,
170
                               const T& value,
171
                               const char* node_name,
172
                               const char* element_name,
173
0
                               bool subtract_from_self) {
174
  // If the container is empty, the size has been accounted into the parent's
175
  // self size
176
0
  if (value.begin() == value.end()) return;
177
  // Fall back to edge name if node names are not provided
178
0
  if (CurrentNode() != nullptr && subtract_from_self) {
179
    // Shift the self size of this container out to a separate node
180
0
    AdjustCurrentNodeSize(-static_cast<int>(sizeof(T)));
181
0
  }
182
0
  PushNode(GetNodeName(node_name, edge_name), sizeof(T), edge_name);
183
0
  for (Iterator it = value.begin(); it != value.end(); ++it) {
184
    // Use nullptr as edge names so the elements appear as indexed properties
185
0
    TrackField(nullptr, *it, element_name);
186
0
  }
187
0
  PopNode();
188
0
}
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::array<v8::Eternal<v8::String>, 69ul>, v8::Eternal<v8::String> const*>(char const*, std::__1::array<v8::Eternal<v8::String>, 69ul> const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::array<v8::Global<v8::Function>, 4ul>, v8::Global<v8::Function> const*>(char const*, std::__1::array<v8::Global<v8::Function>, 4ul> const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<double, std::__1::allocator<double> >, std::__1::__wrap_iter<double const*> >(char const*, std::__1::vector<double, std::__1::allocator<double> > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::__wrap_iter<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*> >(char const*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::unordered_set<node::shadow_realm::ShadowRealm*, std::__1::hash<node::shadow_realm::ShadowRealm*>, std::__1::equal_to<node::shadow_realm::ShadowRealm*>, std::__1::allocator<node::shadow_realm::ShadowRealm*> >, std::__1::__hash_const_iterator<std::__1::__hash_node<node::shadow_realm::ShadowRealm*, void*>*> >(char const*, std::__1::unordered_set<node::shadow_realm::ShadowRealm*, std::__1::hash<node::shadow_realm::ShadowRealm*>, std::__1::equal_to<node::shadow_realm::ShadowRealm*>, std::__1::allocator<node::shadow_realm::ShadowRealm*> > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, std::__1::__wrap_iter<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const*> >(char const*, std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::BlobBindingData::StoredDataObject, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::BlobBindingData::StoredDataObject> > >, std::__1::__hash_map_const_iterator<std::__1::__hash_const_iterator<std::__1::__hash_node<std::__1::__hash_value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::BlobBindingData::StoredDataObject>, void*>*> > >(char const*, std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, node::BlobBindingData::StoredDataObject, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::BlobBindingData::StoredDataObject> > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<node::BaseObjectPtrImpl<node::fs::FileHandleReadWrap, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::fs::FileHandleReadWrap, false> > >, std::__1::__wrap_iter<node::BaseObjectPtrImpl<node::fs::FileHandleReadWrap, false> const*> >(char const*, std::__1::vector<node::BaseObjectPtrImpl<node::fs::FileHandleReadWrap, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::fs::FileHandleReadWrap, false> > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<char, std::__1::allocator<char> >, std::__1::__wrap_iter<char const*> >(char const*, std::__1::vector<char, std::__1::allocator<char> > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::unordered_map<int, node::BaseObjectPtrImpl<node::http2::Http2Stream, false>, std::__1::hash<int>, std::__1::equal_to<int>, std::__1::allocator<std::__1::pair<int const, node::BaseObjectPtrImpl<node::http2::Http2Stream, false> > > >, std::__1::__hash_map_const_iterator<std::__1::__hash_const_iterator<std::__1::__hash_node<std::__1::__hash_value_type<int, node::BaseObjectPtrImpl<node::http2::Http2Stream, false> >, void*>*> > >(char const*, std::__1::unordered_map<int, node::BaseObjectPtrImpl<node::http2::Http2Stream, false>, std::__1::hash<int>, std::__1::equal_to<int>, std::__1::allocator<std::__1::pair<int const, node::BaseObjectPtrImpl<node::http2::Http2Stream, false> > > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::deque<node::BaseObjectPtrImpl<node::http2::Http2Ping, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::http2::Http2Ping, false> > >, std::__1::__deque_iterator<node::BaseObjectPtrImpl<node::http2::Http2Ping, false>, node::BaseObjectPtrImpl<node::http2::Http2Ping, false> const*, node::BaseObjectPtrImpl<node::http2::Http2Ping, false> const&, node::BaseObjectPtrImpl<node::http2::Http2Ping, false> const* const*, long, 512l> >(char const*, std::__1::deque<node::BaseObjectPtrImpl<node::http2::Http2Ping, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::http2::Http2Ping, false> > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::deque<node::BaseObjectPtrImpl<node::http2::Http2Settings, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::http2::Http2Settings, false> > >, std::__1::__deque_iterator<node::BaseObjectPtrImpl<node::http2::Http2Settings, false>, node::BaseObjectPtrImpl<node::http2::Http2Settings, false> const*, node::BaseObjectPtrImpl<node::http2::Http2Settings, false> const&, node::BaseObjectPtrImpl<node::http2::Http2Settings, false> const* const*, long, 512l> >(char const*, std::__1::deque<node::BaseObjectPtrImpl<node::http2::Http2Settings, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::http2::Http2Settings, false> > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<node::http2::NgHttp2StreamWrite, std::__1::allocator<node::http2::NgHttp2StreamWrite> >, std::__1::__wrap_iter<node::http2::NgHttp2StreamWrite const*> >(char const*, std::__1::vector<node::http2::NgHttp2StreamWrite, std::__1::allocator<node::http2::NgHttp2StreamWrite> > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<node::NgHeader<node::http2::Http2HeaderTraits>, std::__1::allocator<node::NgHeader<node::http2::Http2HeaderTraits> > >, std::__1::__wrap_iter<node::NgHeader<node::http2::Http2HeaderTraits> const*> >(char const*, std::__1::vector<node::NgHeader<node::http2::Http2HeaderTraits>, std::__1::allocator<node::NgHeader<node::http2::Http2HeaderTraits> > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::deque<node::http2::NgHttp2StreamWrite, std::__1::allocator<node::http2::NgHttp2StreamWrite> >, std::__1::__deque_iterator<node::http2::NgHttp2StreamWrite, node::http2::NgHttp2StreamWrite const*, node::http2::NgHttp2StreamWrite const&, node::http2::NgHttp2StreamWrite const* const*, long, 128l> >(char const*, std::__1::deque<node::http2::NgHttp2StreamWrite, std::__1::allocator<node::http2::NgHttp2StreamWrite> > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<std::__1::shared_ptr<v8::BackingStore>, std::__1::allocator<std::__1::shared_ptr<v8::BackingStore> > >, std::__1::__wrap_iter<std::__1::shared_ptr<v8::BackingStore> const*> >(char const*, std::__1::vector<std::__1::shared_ptr<v8::BackingStore>, std::__1::allocator<std::__1::shared_ptr<v8::BackingStore> > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<std::__1::unique_ptr<node::worker::TransferData, std::__1::default_delete<node::worker::TransferData> >, std::__1::allocator<std::__1::unique_ptr<node::worker::TransferData, std::__1::default_delete<node::worker::TransferData> > > >, std::__1::__wrap_iter<std::__1::unique_ptr<node::worker::TransferData, std::__1::default_delete<node::worker::TransferData> > const*> >(char const*, std::__1::vector<std::__1::unique_ptr<node::worker::TransferData, std::__1::default_delete<node::worker::TransferData> >, std::__1::allocator<std::__1::unique_ptr<node::worker::TransferData, std::__1::default_delete<node::worker::TransferData> > > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::deque<std::__1::shared_ptr<node::worker::Message>, std::__1::allocator<std::__1::shared_ptr<node::worker::Message> > >, std::__1::__deque_iterator<std::__1::shared_ptr<node::worker::Message>, std::__1::shared_ptr<node::worker::Message> const*, std::__1::shared_ptr<node::worker::Message> const&, std::__1::shared_ptr<node::worker::Message> const* const*, long, 256l> >(char const*, std::__1::deque<std::__1::shared_ptr<node::worker::Message>, std::__1::allocator<std::__1::shared_ptr<node::worker::Message> > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::__tree_const_iterator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__tree_node<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, void*>*, long> >(char const*, std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::list<std::__1::unique_ptr<node::SocketAddressBlockList::Rule, std::__1::default_delete<node::SocketAddressBlockList::Rule> >, std::__1::allocator<std::__1::unique_ptr<node::SocketAddressBlockList::Rule, std::__1::default_delete<node::SocketAddressBlockList::Rule> > > >, std::__1::__list_const_iterator<std::__1::unique_ptr<node::SocketAddressBlockList::Rule, std::__1::default_delete<node::SocketAddressBlockList::Rule> >, void*> >(char const*, std::__1::list<std::__1::unique_ptr<node::SocketAddressBlockList::Rule, std::__1::default_delete<node::SocketAddressBlockList::Rule> >, std::__1::allocator<std::__1::unique_ptr<node::SocketAddressBlockList::Rule, std::__1::default_delete<node::SocketAddressBlockList::Rule> > > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, std::__1::__wrap_iter<unsigned char const*> >(char const*, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::unordered_set<node::cares_wrap::NodeAresTask*, node::cares_wrap::NodeAresTask::Hash, node::cares_wrap::NodeAresTask::Equal, std::__1::allocator<node::cares_wrap::NodeAresTask*> >, std::__1::__hash_const_iterator<std::__1::__hash_node<node::cares_wrap::NodeAresTask*, void*>*> >(char const*, std::__1::unordered_set<node::cares_wrap::NodeAresTask*, node::cares_wrap::NodeAresTask::Hash, node::cares_wrap::NodeAresTask::Equal, std::__1::allocator<node::cares_wrap::NodeAresTask*> > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<std::__1::unique_ptr<node::DataQueue::Entry, std::__1::default_delete<node::DataQueue::Entry> >, std::__1::allocator<std::__1::unique_ptr<node::DataQueue::Entry, std::__1::default_delete<node::DataQueue::Entry> > > >, std::__1::__wrap_iter<std::__1::unique_ptr<node::DataQueue::Entry, std::__1::default_delete<node::DataQueue::Entry> > const*> >(char const*, std::__1::vector<std::__1::unique_ptr<node::DataQueue::Entry, std::__1::default_delete<node::DataQueue::Entry> >, std::__1::allocator<std::__1::unique_ptr<node::DataQueue::Entry, std::__1::default_delete<node::DataQueue::Entry> > > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::unordered_map<node::quic::StatelessResetToken, node::quic::Session*, node::quic::StatelessResetToken::Hash, std::__1::equal_to<node::quic::StatelessResetToken>, std::__1::allocator<std::__1::pair<node::quic::StatelessResetToken const, node::quic::Session*> > >, std::__1::__hash_map_const_iterator<std::__1::__hash_const_iterator<std::__1::__hash_node<std::__1::__hash_value_type<node::quic::StatelessResetToken, node::quic::Session*>, void*>*> > >(char const*, std::__1::unordered_map<node::quic::StatelessResetToken, node::quic::Session*, node::quic::StatelessResetToken::Hash, std::__1::equal_to<node::quic::StatelessResetToken>, std::__1::allocator<std::__1::pair<node::quic::StatelessResetToken const, node::quic::Session*> > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::unordered_map<node::quic::CID const, node::BaseObjectPtrImpl<node::quic::Session, false>, node::quic::CID::Hash, std::__1::equal_to<node::quic::CID const>, std::__1::allocator<std::__1::pair<node::quic::CID const, node::BaseObjectPtrImpl<node::quic::Session, false> > > >, std::__1::__hash_map_const_iterator<std::__1::__hash_const_iterator<std::__1::__hash_node<std::__1::__hash_value_type<node::quic::CID const, node::BaseObjectPtrImpl<node::quic::Session, false> >, void*>*> > >(char const*, std::__1::unordered_map<node::quic::CID const, node::BaseObjectPtrImpl<node::quic::Session, false>, node::quic::CID::Hash, std::__1::equal_to<node::quic::CID const>, std::__1::allocator<std::__1::pair<node::quic::CID const, node::BaseObjectPtrImpl<node::quic::Session, false> > > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::unordered_map<node::quic::CID const, node::quic::CID, node::quic::CID::Hash, std::__1::equal_to<node::quic::CID const>, std::__1::allocator<std::__1::pair<node::quic::CID const, node::quic::CID> > >, std::__1::__hash_map_const_iterator<std::__1::__hash_const_iterator<std::__1::__hash_node<std::__1::__hash_value_type<node::quic::CID const, node::quic::CID>, void*>*> > >(char const*, std::__1::unordered_map<node::quic::CID const, node::quic::CID, node::quic::CID::Hash, std::__1::equal_to<node::quic::CID const>, std::__1::allocator<std::__1::pair<node::quic::CID const, node::quic::CID> > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::unordered_map<long, node::BaseObjectPtrImpl<node::quic::Stream, false>, std::__1::hash<long>, std::__1::equal_to<long>, std::__1::allocator<std::__1::pair<long const, node::BaseObjectPtrImpl<node::quic::Stream, false> > > >, std::__1::__hash_map_const_iterator<std::__1::__hash_const_iterator<std::__1::__hash_node<std::__1::__hash_value_type<long, node::BaseObjectPtrImpl<node::quic::Stream, false> >, void*>*> > >(char const*, std::__1::unordered_map<long, node::BaseObjectPtrImpl<node::quic::Stream, false>, std::__1::hash<long>, std::__1::equal_to<long>, std::__1::allocator<std::__1::pair<long const, node::BaseObjectPtrImpl<node::quic::Stream, false> > > > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<node::crypto::KeyObjectData, std::__1::allocator<node::crypto::KeyObjectData> >, std::__1::__wrap_iter<node::crypto::KeyObjectData const*> >(char const*, std::__1::vector<node::crypto::KeyObjectData, std::__1::allocator<node::crypto::KeyObjectData> > const&, char const*, char const*, bool)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::vector<node::quic::Store, std::__1::allocator<node::quic::Store> >, std::__1::__wrap_iter<node::quic::Store const*> >(char const*, std::__1::vector<node::quic::Store, std::__1::allocator<node::quic::Store> > const&, char const*, char const*, bool)
189
190
template <typename T>
191
void MemoryTracker::TrackField(const char* edge_name,
192
                               const std::queue<T>& value,
193
                               const char* node_name,
194
0
                               const char* element_name) {
195
0
  struct ContainerGetter : public std::queue<T> {
196
0
    static const typename std::queue<T>::container_type& Get(
197
0
        const std::queue<T>& value) {
198
0
      return value.*&ContainerGetter::c;
199
0
    }
Unexecuted instantiation: node::MemoryTracker::TrackField<node::BaseObjectPtrImpl<node::http2::Http2Ping, false> >(char const*, std::__1::queue<node::BaseObjectPtrImpl<node::http2::Http2Ping, false>, std::__1::deque<node::BaseObjectPtrImpl<node::http2::Http2Ping, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::http2::Http2Ping, false> > > > const&, char const*, char const*)::ContainerGetter::Get(std::__1::queue<node::BaseObjectPtrImpl<node::http2::Http2Ping, false>, std::__1::deque<node::BaseObjectPtrImpl<node::http2::Http2Ping, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::http2::Http2Ping, false> > > > const&)
Unexecuted instantiation: node::MemoryTracker::TrackField<node::BaseObjectPtrImpl<node::http2::Http2Settings, false> >(char const*, std::__1::queue<node::BaseObjectPtrImpl<node::http2::Http2Settings, false>, std::__1::deque<node::BaseObjectPtrImpl<node::http2::Http2Settings, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::http2::Http2Settings, false> > > > const&, char const*, char const*)::ContainerGetter::Get(std::__1::queue<node::BaseObjectPtrImpl<node::http2::Http2Settings, false>, std::__1::deque<node::BaseObjectPtrImpl<node::http2::Http2Settings, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::http2::Http2Settings, false> > > > const&)
Unexecuted instantiation: node::MemoryTracker::TrackField<node::http2::NgHttp2StreamWrite>(char const*, std::__1::queue<node::http2::NgHttp2StreamWrite, std::__1::deque<node::http2::NgHttp2StreamWrite, std::__1::allocator<node::http2::NgHttp2StreamWrite> > > const&, char const*, char const*)::ContainerGetter::Get(std::__1::queue<node::http2::NgHttp2StreamWrite, std::__1::deque<node::http2::NgHttp2StreamWrite, std::__1::allocator<node::http2::NgHttp2StreamWrite> > > const&)
200
0
  };
201
202
0
  const auto& container = ContainerGetter::Get(value);
203
0
  TrackField(edge_name, container, node_name, element_name);
204
0
}
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::BaseObjectPtrImpl<node::http2::Http2Ping, false> >(char const*, std::__1::queue<node::BaseObjectPtrImpl<node::http2::Http2Ping, false>, std::__1::deque<node::BaseObjectPtrImpl<node::http2::Http2Ping, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::http2::Http2Ping, false> > > > const&, char const*, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::BaseObjectPtrImpl<node::http2::Http2Settings, false> >(char const*, std::__1::queue<node::BaseObjectPtrImpl<node::http2::Http2Settings, false>, std::__1::deque<node::BaseObjectPtrImpl<node::http2::Http2Settings, false>, std::__1::allocator<node::BaseObjectPtrImpl<node::http2::Http2Settings, false> > > > const&, char const*, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::http2::NgHttp2StreamWrite>(char const*, std::__1::queue<node::http2::NgHttp2StreamWrite, std::__1::deque<node::http2::NgHttp2StreamWrite, std::__1::allocator<node::http2::NgHttp2StreamWrite> > > const&, char const*, char const*)
205
206
template <typename T, typename test_for_number, typename dummy>
207
void MemoryTracker::TrackField(const char* edge_name,
208
                               const T& value,
209
0
                               const char* node_name) {
210
  // For numbers, creating new nodes is not worth the overhead.
211
0
  AdjustCurrentNodeSize(static_cast<int>(sizeof(T)));
212
0
}
Unexecuted instantiation: void node::MemoryTracker::TrackField<double, bool, bool>(char const*, double const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<char, bool, bool>(char const*, char const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<int, bool, bool>(char const*, int const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<unsigned char, bool, bool>(char const*, unsigned char const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<long, bool, bool>(char const*, long const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<unsigned long, bool, bool>(char const*, unsigned long const&, char const*)
213
214
template <typename T, typename U>
215
void MemoryTracker::TrackField(const char* edge_name,
216
                               const std::pair<T, U>& value,
217
0
                               const char* node_name) {
218
0
  PushNode(node_name == nullptr ? "pair" : node_name,
219
0
           sizeof(const std::pair<T, U>),
220
0
           edge_name);
221
  // TODO(joyeecheung): special case if one of these is a number type
222
  // that meets the test_for_number trait so that their sizes don't get
223
  // merged into the pair node
224
0
  TrackField("first", value.first);
225
0
  TrackField("second", value.second);
226
0
  PopNode();
227
0
}
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(char const*, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::BlobBindingData::StoredDataObject>(char const*, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, node::BlobBindingData::StoredDataObject> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<int const, node::BaseObjectPtrImpl<node::http2::Http2Stream, false> >(char const*, std::__1::pair<int const, node::BaseObjectPtrImpl<node::http2::Http2Stream, false> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::quic::StatelessResetToken const, node::quic::Session*>(char const*, std::__1::pair<node::quic::StatelessResetToken const, node::quic::Session*> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::quic::CID const, node::BaseObjectPtrImpl<node::quic::Session, false> >(char const*, std::__1::pair<node::quic::CID const, node::BaseObjectPtrImpl<node::quic::Session, false> > const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<node::quic::CID const, node::quic::CID>(char const*, std::__1::pair<node::quic::CID const, node::quic::CID> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<long const, node::BaseObjectPtrImpl<node::quic::Stream, false> >(char const*, std::__1::pair<long const, node::BaseObjectPtrImpl<node::quic::Stream, false> > const&, char const*)
228
229
template <typename T>
230
void MemoryTracker::TrackField(const char* edge_name,
231
                               const std::basic_string<T>& value,
232
0
                               const char* node_name) {
233
0
  TrackFieldWithSize(edge_name, value.size() * sizeof(T), "std::basic_string");
234
0
}
235
236
template <typename T>
237
void MemoryTracker::TrackField(const char* edge_name,
238
                               const v8::Eternal<T>& value,
239
0
                               const char* node_name) {
240
0
  TrackField(edge_name, value.Get(isolate_));
241
0
}
242
243
template <typename T>
244
void MemoryTracker::TrackField(const char* edge_name,
245
                               const v8::PersistentBase<T>& value,
246
0
                               const char* node_name) {
247
0
  if (value.IsWeak()) return;
248
0
  TrackField(edge_name, value.Get(isolate_));
249
0
}
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Int8Array>(char const*, v8::PersistentBase<v8::Int8Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Uint8Array>(char const*, v8::PersistentBase<v8::Uint8Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Int16Array>(char const*, v8::PersistentBase<v8::Int16Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Uint16Array>(char const*, v8::PersistentBase<v8::Uint16Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Int32Array>(char const*, v8::PersistentBase<v8::Int32Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Uint32Array>(char const*, v8::PersistentBase<v8::Uint32Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Float32Array>(char const*, v8::PersistentBase<v8::Float32Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Float64Array>(char const*, v8::PersistentBase<v8::Float64Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::BigInt64Array>(char const*, v8::PersistentBase<v8::BigInt64Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Function>(char const*, v8::PersistentBase<v8::Function> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Promise>(char const*, v8::PersistentBase<v8::Promise> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Value>(char const*, v8::PersistentBase<v8::Value> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Promise::Resolver>(char const*, v8::PersistentBase<v8::Promise::Resolver> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::WasmMemoryObject>(char const*, v8::PersistentBase<v8::WasmMemoryObject> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Map>(char const*, v8::PersistentBase<v8::Map> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::ArrayBufferView>(char const*, v8::PersistentBase<v8::ArrayBufferView> const&, char const*)
250
251
template <typename T>
252
void MemoryTracker::TrackField(const char* edge_name,
253
                               const v8::Local<T>& value,
254
0
                               const char* node_name) {
255
0
  if (!value.IsEmpty())
256
0
    graph_->AddEdge(CurrentNode(),
257
0
                    graph_->V8Node(value.template As<v8::Value>()),
258
0
                    edge_name);
259
0
}
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Int8Array>(char const*, v8::Local<v8::Int8Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Uint8Array>(char const*, v8::Local<v8::Uint8Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Int16Array>(char const*, v8::Local<v8::Int16Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Uint16Array>(char const*, v8::Local<v8::Uint16Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Int32Array>(char const*, v8::Local<v8::Int32Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Uint32Array>(char const*, v8::Local<v8::Uint32Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Float32Array>(char const*, v8::Local<v8::Float32Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Float64Array>(char const*, v8::Local<v8::Float64Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::BigInt64Array>(char const*, v8::Local<v8::BigInt64Array> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Symbol>(char const*, v8::Local<v8::Symbol> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::String>(char const*, v8::Local<v8::String> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Function>(char const*, v8::Local<v8::Function> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Promise>(char const*, v8::Local<v8::Promise> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Value>(char const*, v8::Local<v8::Value> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Promise::Resolver>(char const*, v8::Local<v8::Promise::Resolver> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Object>(char const*, v8::Local<v8::Object> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::WasmMemoryObject>(char const*, v8::Local<v8::WasmMemoryObject> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::Map>(char const*, v8::Local<v8::Map> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TrackField<v8::ArrayBufferView>(char const*, v8::Local<v8::ArrayBufferView> const&, char const*)
260
261
template <typename T>
262
void MemoryTracker::TrackField(const char* edge_name,
263
                               const MallocedBuffer<T>& value,
264
                               const char* node_name) {
265
  TrackFieldWithSize(edge_name, value.size, "MallocedBuffer");
266
}
267
268
void MemoryTracker::TrackField(const char* edge_name,
269
                               const v8::BackingStore* value,
270
0
                               const char* node_name) {
271
0
  TrackFieldWithSize(edge_name, value->ByteLength(), "BackingStore");
272
0
}
273
274
void MemoryTracker::TrackField(const char* name,
275
                               const uv_buf_t& value,
276
0
                               const char* node_name) {
277
0
  TrackFieldWithSize(name, value.len, "uv_buf_t");
278
0
}
279
280
void MemoryTracker::TrackField(const char* name,
281
                               const uv_timer_t& value,
282
0
                               const char* node_name) {
283
0
  TrackFieldWithSize(name, sizeof(value), "uv_timer_t");
284
0
}
285
286
void MemoryTracker::TrackField(const char* name,
287
                               const uv_async_t& value,
288
0
                               const char* node_name) {
289
0
  TrackFieldWithSize(name, sizeof(value), "uv_async_t");
290
0
}
291
292
void MemoryTracker::TrackInlineField(const char* name,
293
                                     const uv_async_t& value,
294
0
                                     const char* node_name) {
295
0
  TrackInlineFieldWithSize(name, sizeof(value), "uv_async_t");
296
0
}
297
298
0
void MemoryTracker::Track(const CppgcMixin* retainer, const char* edge_name) {
299
0
  v8::HandleScope handle_scope(isolate_);
300
0
  auto it = seen_.find(retainer);
301
0
  if (it != seen_.end()) {
302
0
    if (CurrentNode() != nullptr) {
303
0
      graph_->AddEdge(CurrentNode(), it->second, edge_name);
304
0
    }
305
0
    return;  // It has already been tracked, no need to call MemoryInfo again
306
0
  }
307
0
  MemoryRetainerNode* n = PushNode(retainer, edge_name);
308
0
  retainer->MemoryInfo(this);
309
0
  CHECK_EQ(CurrentNode(), n->JSWrapperNode());
310
  // This is a dummy MemoryRetainerNode. The real graph node is wrapper_node_.
311
0
  PopNode();
312
0
}
313
314
void MemoryTracker::Track(const MemoryRetainer* retainer,
315
0
                          const char* edge_name) {
316
0
  v8::HandleScope handle_scope(isolate_);
317
0
  auto it = seen_.find(retainer);
318
0
  if (it != seen_.end()) {
319
0
    if (CurrentNode() != nullptr) {
320
0
      graph_->AddEdge(CurrentNode(), it->second, edge_name);
321
0
    }
322
0
    return;  // It has already been tracked, no need to call MemoryInfo again
323
0
  }
324
0
  MemoryRetainerNode* n = PushNode(retainer, edge_name);
325
0
  retainer->MemoryInfo(this);
326
0
  CHECK_EQ(CurrentNode(), n);
327
0
  CHECK_NE(n->size_, 0);
328
0
  PopNode();
329
0
}
330
331
void MemoryTracker::TrackInlineField(const MemoryRetainer* retainer,
332
0
                                     const char* edge_name) {
333
0
  Track(retainer, edge_name);
334
0
  CHECK(CurrentNode());
335
0
  AdjustCurrentNodeSize(-(static_cast<int>(retainer->SelfSize())));
336
0
}
337
338
template <typename T>
339
inline void MemoryTracker::TraitTrack(const T& retainer,
340
0
                                      const char* edge_name) {
341
0
  MemoryRetainerNode* n =
342
0
      PushNode(MemoryRetainerTraits<T>::MemoryInfoName(retainer),
343
0
               MemoryRetainerTraits<T>::SelfSize(retainer),
344
0
               edge_name);
345
0
  MemoryRetainerTraits<T>::MemoryInfo(this, retainer);
346
0
  CHECK_EQ(CurrentNode(), n);
347
0
  CHECK_NE(n->size_, 0);
348
0
  PopNode();
349
0
}
Unexecuted instantiation: void node::MemoryTracker::TraitTrack<ada::url_pattern<node::url_pattern::URLPatternRegexProvider> >(ada::url_pattern<node::url_pattern::URLPatternRegexProvider> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TraitTrack<ada::url_pattern_component<node::url_pattern::URLPatternRegexProvider> >(ada::url_pattern_component<node::url_pattern::URLPatternRegexProvider> const&, char const*)
350
351
template <typename T>
352
inline void MemoryTracker::TraitTrackInline(const T& retainer,
353
0
                                            const char* edge_name) {
354
0
  TraitTrack(retainer, edge_name);
355
0
  CHECK(CurrentNode());
356
0
  AdjustCurrentNodeSize(
357
0
      -(static_cast<int>(MemoryRetainerTraits<T>::SelfSize(retainer))));
358
0
}
Unexecuted instantiation: void node::MemoryTracker::TraitTrackInline<ada::url_pattern<node::url_pattern::URLPatternRegexProvider> >(ada::url_pattern<node::url_pattern::URLPatternRegexProvider> const&, char const*)
Unexecuted instantiation: void node::MemoryTracker::TraitTrackInline<ada::url_pattern_component<node::url_pattern::URLPatternRegexProvider> >(ada::url_pattern_component<node::url_pattern::URLPatternRegexProvider> const&, char const*)
359
360
0
v8::EmbedderGraph::Node* MemoryTracker::CurrentNode() const {
361
0
  if (node_stack_.empty()) return nullptr;
362
0
  MemoryRetainerNode* n = node_stack_.top();
363
0
  if (n->IsCppgcWrapper()) {
364
0
    return n->JSWrapperNode();
365
0
  }
366
0
  return n;
367
0
}
368
369
MemoryRetainerNode* MemoryTracker::AddNode(const CppgcMixin* retainer,
370
0
                                           const char* edge_name) {
371
0
  auto it = seen_.find(retainer);
372
0
  if (it != seen_.end()) {
373
0
    return it->second;
374
0
  }
375
376
0
  MemoryRetainerNode* n = new MemoryRetainerNode(this, retainer);
377
0
  seen_[retainer] = n;
378
0
  if (CurrentNode() != nullptr) {
379
0
    graph_->AddEdge(CurrentNode(), n->JSWrapperNode(), edge_name);
380
0
  }
381
382
0
  return n;
383
0
}
384
385
MemoryRetainerNode* MemoryTracker::AddNode(const MemoryRetainer* retainer,
386
0
                                           const char* edge_name) {
387
0
  auto it = seen_.find(retainer);
388
0
  if (it != seen_.end()) {
389
0
    return it->second;
390
0
  }
391
392
0
  MemoryRetainerNode* n = new MemoryRetainerNode(this, retainer);
393
0
  graph_->AddNode(std::unique_ptr<v8::EmbedderGraph::Node>(n));
394
0
  seen_[retainer] = n;
395
0
  if (CurrentNode() != nullptr) graph_->AddEdge(CurrentNode(), n, edge_name);
396
397
0
  if (n->JSWrapperNode() != nullptr) {
398
0
    graph_->AddEdge(n, n->JSWrapperNode(), "native_to_javascript");
399
0
    graph_->AddEdge(n->JSWrapperNode(), n, "javascript_to_native");
400
0
  }
401
402
0
  return n;
403
0
}
404
405
MemoryRetainerNode* MemoryTracker::AddNode(const char* node_name,
406
                                           size_t size,
407
0
                                           const char* edge_name) {
408
0
  MemoryRetainerNode* n = new MemoryRetainerNode(this, node_name, size);
409
0
  graph_->AddNode(std::unique_ptr<v8::EmbedderGraph::Node>(n));
410
411
0
  if (CurrentNode() != nullptr) graph_->AddEdge(CurrentNode(), n, edge_name);
412
413
0
  return n;
414
0
}
415
416
MemoryRetainerNode* MemoryTracker::PushNode(const CppgcMixin* retainer,
417
0
                                            const char* edge_name) {
418
0
  MemoryRetainerNode* n = AddNode(retainer, edge_name);
419
0
  node_stack_.push(n);
420
0
  return n;
421
0
}
422
423
MemoryRetainerNode* MemoryTracker::PushNode(const MemoryRetainer* retainer,
424
0
                                            const char* edge_name) {
425
0
  MemoryRetainerNode* n = AddNode(retainer, edge_name);
426
0
  node_stack_.push(n);
427
0
  return n;
428
0
}
429
430
MemoryRetainerNode* MemoryTracker::PushNode(const char* node_name,
431
                                            size_t size,
432
0
                                            const char* edge_name) {
433
0
  MemoryRetainerNode* n = AddNode(node_name, size, edge_name);
434
0
  node_stack_.push(n);
435
0
  return n;
436
0
}
437
438
0
void MemoryTracker::PopNode() {
439
0
  node_stack_.pop();
440
0
}
441
442
0
void MemoryTracker::AdjustCurrentNodeSize(int diff) {
443
0
  if (node_stack_.empty()) return;
444
0
  MemoryRetainerNode* n = node_stack_.top();
445
0
  if (!n->IsCppgcWrapper()) {
446
0
    n->size_ = static_cast<size_t>(static_cast<int>(n->size_) + diff);
447
0
  }
448
0
}
449
450
}  // namespace node
451
452
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
453
454
#endif  // SRC_MEMORY_TRACKER_INL_H_