/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_ |