@@ -112,6 +112,29 @@ IsolateData::IsolateData(Isolate* isolate,
112112#undef V
113113}
114114
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+
115138void InitThreadLocalOnce () {
116139 CHECK_EQ (0 , uv_key_create (&Environment::thread_local_env));
117140}
@@ -707,6 +730,7 @@ void Environment::set_debug_categories(const std::string& cats, bool enabled) {
707730 }
708731
709732 DEBUG_CATEGORY_NAMES (V)
733+ #undef V
710734
711735 if (comma_pos == std::string::npos)
712736 break ;
@@ -775,6 +799,21 @@ void Environment::CollectUVExceptionInfo(Local<Value> object,
775799 syscall, message, path, dest);
776800}
777801
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+
778817void AsyncHooks::grow_async_ids_stack () {
779818 async_ids_stack_.reserve (async_ids_stack_.Length () * 3 );
780819
@@ -805,13 +844,83 @@ void Environment::stop_sub_worker_contexts() {
805844 }
806845}
807846
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+
808868void Environment::BuildEmbedderGraph (Isolate* isolate,
809869 EmbedderGraph* graph,
810870 void * data) {
811871 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.
815924}
816925
817926char * Environment::Reallocate (char * data, size_t old_size, size_t size) {
@@ -875,8 +984,4 @@ Local<Object> BaseObject::WrappedObject() const {
875984 return object ();
876985}
877986
878- bool BaseObject::IsRootNode () const {
879- return !persistent_handle_.IsWeak ();
880- }
881-
882987} // namespace node
0 commit comments