@@ -112,6 +112,29 @@ IsolateData::IsolateData(Isolate* isolate,
112
112
#undef V
113
113
}
114
114
115
+ void IsolateData::MemoryInfo (MemoryTracker* tracker) const {
116
+ #define V (PropertyName, StringValue ) \
117
+ tracker->TrackField (#PropertyName, PropertyName (isolate ()));
118
+ PER_ISOLATE_SYMBOL_PROPERTIES (V)
119
+ #undef V
120
+
121
+ #define V (PropertyName, StringValue ) \
122
+ tracker->TrackField (#PropertyName, PropertyName (isolate ()));
123
+ PER_ISOLATE_STRING_PROPERTIES (V)
124
+ #undef V
125
+
126
+ if (node_allocator_ != nullptr ) {
127
+ tracker->TrackFieldWithSize (
128
+ " node_allocator" , sizeof (*node_allocator_), " NodeArrayBufferAllocator" );
129
+ } else {
130
+ tracker->TrackFieldWithSize (
131
+ " allocator" , sizeof (*allocator_), " v8::ArrayBuffer::Allocator" );
132
+ }
133
+ tracker->TrackFieldWithSize (
134
+ " platform" , sizeof (*platform_), " MultiIsolatePlatform" );
135
+ // TODO(joyeecheung): implement MemoryRetainer in the option classes.
136
+ }
137
+
115
138
void InitThreadLocalOnce () {
116
139
CHECK_EQ (0 , uv_key_create (&Environment::thread_local_env));
117
140
}
@@ -707,6 +730,7 @@ void Environment::set_debug_categories(const std::string& cats, bool enabled) {
707
730
}
708
731
709
732
DEBUG_CATEGORY_NAMES (V)
733
+ #undef V
710
734
711
735
if (comma_pos == std::string::npos)
712
736
break ;
@@ -775,6 +799,21 @@ void Environment::CollectUVExceptionInfo(Local<Value> object,
775
799
syscall , message, path, dest);
776
800
}
777
801
802
+ void ImmediateInfo::MemoryInfo (MemoryTracker* tracker) const {
803
+ tracker->TrackField (" fields" , fields_);
804
+ }
805
+
806
+ void TickInfo::MemoryInfo (MemoryTracker* tracker) const {
807
+ tracker->TrackField (" fields" , fields_);
808
+ }
809
+
810
+ void AsyncHooks::MemoryInfo (MemoryTracker* tracker) const {
811
+ tracker->TrackField (" providers" , providers_);
812
+ tracker->TrackField (" async_ids_stack" , async_ids_stack_);
813
+ tracker->TrackField (" fields" , fields_);
814
+ tracker->TrackField (" async_id_fields" , async_id_fields_);
815
+ }
816
+
778
817
void AsyncHooks::grow_async_ids_stack () {
779
818
async_ids_stack_.reserve (async_ids_stack_.Length () * 3 );
780
819
@@ -805,13 +844,83 @@ void Environment::stop_sub_worker_contexts() {
805
844
}
806
845
}
807
846
847
+ void MemoryTracker::TrackField (const char * edge_name,
848
+ const CleanupHookCallback& value,
849
+ const char * node_name) {
850
+ v8::HandleScope handle_scope (isolate_);
851
+ // Here, we utilize the fact that CleanupHookCallback instances
852
+ // are all unique and won't be tracked twice in one BuildEmbedderGraph
853
+ // callback.
854
+ MemoryRetainerNode* n =
855
+ PushNode (" CleanupHookCallback" , sizeof (value), edge_name);
856
+ // TODO(joyeecheung): at the moment only arguments of type BaseObject will be
857
+ // identified and tracked here (based on their deleters),
858
+ // but we may convert and track other known types here.
859
+ BaseObject* obj = value.GetBaseObject ();
860
+ if (obj != nullptr ) {
861
+ this ->TrackField (" arg" , obj);
862
+ }
863
+ CHECK_EQ (CurrentNode (), n);
864
+ CHECK_NE (n->size_ , 0 );
865
+ PopNode ();
866
+ }
867
+
808
868
void Environment::BuildEmbedderGraph (Isolate* isolate,
809
869
EmbedderGraph* graph,
810
870
void * data) {
811
871
MemoryTracker tracker (isolate, graph);
812
- static_cast <Environment*>(data)->ForEachBaseObject ([&](BaseObject* obj) {
813
- tracker.Track (obj);
814
- });
872
+ Environment* env = static_cast <Environment*>(data);
873
+ tracker.Track (env);
874
+ }
875
+
876
+ inline size_t Environment::SelfSize () const {
877
+ size_t size = sizeof (*this );
878
+ // Remove non pointer fields that will be tracked in MemoryInfo()
879
+ // TODO(joyeecheung): refactor the MemoryTracker interface so
880
+ // this can be done for common types within the Track* calls automatically
881
+ // if a certain scope is entered.
882
+ size -= sizeof (thread_stopper_);
883
+ size -= sizeof (async_hooks_);
884
+ size -= sizeof (tick_info_);
885
+ size -= sizeof (immediate_info_);
886
+ return size;
887
+ }
888
+
889
+ void Environment::MemoryInfo (MemoryTracker* tracker) const {
890
+ // Iteratable STLs have their own sizes subtracted from the parent
891
+ // by default.
892
+ tracker->TrackField (" isolate_data" , isolate_data_);
893
+ tracker->TrackField (" native_modules_with_cache" , native_modules_with_cache);
894
+ tracker->TrackField (" native_modules_without_cache" ,
895
+ native_modules_without_cache);
896
+ tracker->TrackField (" destroy_async_id_list" , destroy_async_id_list_);
897
+ tracker->TrackField (" exec_argv" , exec_argv_);
898
+ tracker->TrackField (" should_abort_on_uncaught_toggle" ,
899
+ should_abort_on_uncaught_toggle_);
900
+ tracker->TrackField (" stream_base_state" , stream_base_state_);
901
+ tracker->TrackField (" fs_stats_field_array" , fs_stats_field_array_);
902
+ tracker->TrackField (" fs_stats_field_bigint_array" ,
903
+ fs_stats_field_bigint_array_);
904
+ tracker->TrackField (" thread_stopper" , thread_stopper_);
905
+ tracker->TrackField (" cleanup_hooks" , cleanup_hooks_);
906
+ tracker->TrackField (" async_hooks" , async_hooks_);
907
+ tracker->TrackField (" immediate_info" , immediate_info_);
908
+ tracker->TrackField (" tick_info" , tick_info_);
909
+
910
+ #define V (PropertyName, TypeName ) \
911
+ tracker->TrackField (#PropertyName, PropertyName ());
912
+ ENVIRONMENT_STRONG_PERSISTENT_VALUES (V)
913
+ #undef V
914
+
915
+ // FIXME(joyeecheung): track other fields in Environment.
916
+ // Currently MemoryTracker is unable to track these
917
+ // correctly:
918
+ // - Internal types that do not implement MemoryRetainer yet
919
+ // - STL containers with MemoryRetainer* inside
920
+ // - STL containers with numeric types inside that should not have their
921
+ // nodes elided e.g. numeric keys in maps.
922
+ // We also need to make sure that when we add a non-pointer field as its own
923
+ // node, we shift its sizeof() size out of the Environment node.
815
924
}
816
925
817
926
char * Environment::Reallocate (char * data, size_t old_size, size_t size) {
@@ -875,8 +984,4 @@ Local<Object> BaseObject::WrappedObject() const {
875
984
return object ();
876
985
}
877
986
878
- bool BaseObject::IsRootNode () const {
879
- return !persistent_handle_.IsWeak ();
880
- }
881
-
882
987
} // namespace node
0 commit comments