summaryrefslogtreecommitdiff
path: root/src/memory_tracker-inl.h
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2018-07-11 00:59:53 +0200
committerAnna Henningsen <anna@addaleax.net>2018-07-15 20:35:35 +0200
commit266a7e62585b975f2ea2d25473b21395f5ca5a3f (patch)
tree0e5229e042517620784aea2f8114c2cf3d287bb7 /src/memory_tracker-inl.h
parentd2a1408f119181675d9d3f20982ccd863443baad (diff)
downloadandroid-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.h105
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