diff options
author | Anna Henningsen <anna@addaleax.net> | 2018-07-11 00:59:53 +0200 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2018-07-15 20:35:35 +0200 |
commit | 266a7e62585b975f2ea2d25473b21395f5ca5a3f (patch) | |
tree | 0e5229e042517620784aea2f8114c2cf3d287bb7 /src/memory_tracker-inl.h | |
parent | d2a1408f119181675d9d3f20982ccd863443baad (diff) | |
download | android-node-v8-266a7e62585b975f2ea2d25473b21395f5ca5a3f.tar.gz android-node-v8-266a7e62585b975f2ea2d25473b21395f5ca5a3f.tar.bz2 android-node-v8-266a7e62585b975f2ea2d25473b21395f5ca5a3f.zip |
src: use V8 graph heap snapshot API
Transition to a newer, more flexible API for
heap snapshot creation.
This addresses a currently pending deprecation in the V8 API.
PR-URL: https://github.com/nodejs/node/pull/21741
Fixes: https://github.com/nodejs/node/issues/21633
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Diffstat (limited to 'src/memory_tracker-inl.h')
-rw-r--r-- | src/memory_tracker-inl.h | 105 |
1 files changed, 98 insertions, 7 deletions
diff --git a/src/memory_tracker-inl.h b/src/memory_tracker-inl.h index 758223492f..568a4364f9 100644 --- a/src/memory_tracker-inl.h +++ b/src/memory_tracker-inl.h @@ -7,13 +7,54 @@ namespace node { +class MemoryRetainerNode : public v8::EmbedderGraph::Node { + public: + explicit inline MemoryRetainerNode(MemoryTracker* tracker, + const MemoryRetainer* retainer, + const char* name) + : retainer_(retainer) { + if (retainer_ != nullptr) { + v8::HandleScope handle_scope(tracker->isolate()); + v8::Local<v8::Object> obj = retainer_->WrappedObject(); + if (!obj.IsEmpty()) + wrapper_node_ = tracker->graph()->V8Node(obj); + + name_ = retainer_->MemoryInfoName(); + } + if (name_.empty() && name != nullptr) { + name_ = name; + } + } + + const char* Name() override { return name_.c_str(); } + const char* NamePrefix() override { return "Node /"; } + size_t SizeInBytes() override { return size_; } + // TODO(addaleax): Merging this with the "official" WrapperNode() method + // seems to lose accuracy, e.g. SizeInBytes() is disregarded. + // Figure out whether to do anything about that. + Node* JSWrapperNode() { return wrapper_node_; } + + bool IsRootNode() override { + return retainer_ != nullptr && retainer_->IsRootNode(); + } + + private: + friend class MemoryTracker; + + Node* wrapper_node_ = nullptr; + const MemoryRetainer* retainer_; + std::string name_; + size_t size_ = 0; +}; + template <typename T> void MemoryTracker::TrackThis(const T* obj) { - accumulated_size_ += sizeof(T); + CurrentNode()->size_ = sizeof(T); } void MemoryTracker::TrackFieldWithSize(const char* name, size_t size) { - accumulated_size_ += size; + if (size > 0) + AddNode(name)->size_ = size; } void MemoryTracker::TrackField(const char* name, const MemoryRetainer& value) { @@ -21,9 +62,13 @@ void MemoryTracker::TrackField(const char* name, const MemoryRetainer& value) { } void MemoryTracker::TrackField(const char* name, const MemoryRetainer* value) { - if (track_only_self_ || value == nullptr || seen_.count(value) > 0) return; - seen_.insert(value); - Track(value); + if (track_only_self_ || value == nullptr) return; + auto it = seen_.find(value); + if (it != seen_.end()) { + graph_->AddEdge(CurrentNode(), it->second); + } else { + Track(value, name); + } } template <typename T> @@ -36,8 +81,10 @@ template <typename T, typename Iterator> void MemoryTracker::TrackField(const char* name, const T& value) { if (value.begin() == value.end()) return; size_t index = 0; + PushNode(name); for (Iterator it = value.begin(); it != value.end(); ++it) TrackField(std::to_string(index++).c_str(), *it); + PopNode(); } template <typename T> @@ -56,13 +103,15 @@ void MemoryTracker::TrackField(const char* name, const std::queue<T>& value) { template <typename T, typename test_for_number, typename dummy> void MemoryTracker::TrackField(const char* name, const T& value) { // For numbers, creating new nodes is not worth the overhead. - TrackFieldWithSize(name, sizeof(T)); + CurrentNode()->size_ += sizeof(T); } template <typename T, typename U> void MemoryTracker::TrackField(const char* name, const std::pair<T, U>& value) { + PushNode(name); TrackField("first", value.first); TrackField("second", value.second); + PopNode(); } template <typename T> @@ -74,10 +123,13 @@ void MemoryTracker::TrackField(const char* name, template <typename T, typename Traits> void MemoryTracker::TrackField(const char* name, const v8::Persistent<T, Traits>& value) { + TrackField(name, value.Get(isolate_)); } template <typename T> void MemoryTracker::TrackField(const char* name, const v8::Local<T>& value) { + if (!value.IsEmpty()) + graph_->AddEdge(CurrentNode(), graph_->V8Node(value)); } template <typename T> @@ -96,8 +148,47 @@ void MemoryTracker::TrackField(const char* name, TrackField(name, value.GetJSArray()); } -void MemoryTracker::Track(const MemoryRetainer* value) { +void MemoryTracker::Track(const MemoryRetainer* value, const char* name) { + v8::HandleScope handle_scope(isolate_); + MemoryRetainerNode* n = PushNode(name, value); value->MemoryInfo(this); + CHECK_EQ(CurrentNode(), n); + CHECK_NE(n->size_, 0); + PopNode(); +} + +MemoryRetainerNode* MemoryTracker::CurrentNode() const { + if (node_stack_.empty()) return nullptr; + return node_stack_.top(); +} + +MemoryRetainerNode* MemoryTracker::AddNode( + const char* name, const MemoryRetainer* retainer) { + MemoryRetainerNode* n = new MemoryRetainerNode(this, retainer, name); + graph_->AddNode(std::unique_ptr<v8::EmbedderGraph::Node>(n)); + if (retainer != nullptr) + seen_[retainer] = n; + + if (CurrentNode() != nullptr) + graph_->AddEdge(CurrentNode(), n); + + if (n->JSWrapperNode() != nullptr) { + graph_->AddEdge(n, n->JSWrapperNode()); + graph_->AddEdge(n->JSWrapperNode(), n); + } + + return n; +} + +MemoryRetainerNode* MemoryTracker::PushNode( + const char* name, const MemoryRetainer* retainer) { + MemoryRetainerNode* n = AddNode(name, retainer); + node_stack_.push(n); + return n; +} + +void MemoryTracker::PopNode() { + node_stack_.pop(); } } // namespace node |