| // Copyright 2015 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_ | 
 | #define BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_ | 
 |  | 
 | #include <stddef.h> | 
 |  | 
 | #include <map> | 
 | #include <unordered_map> | 
 | #include <vector> | 
 |  | 
 | #include "base/base_export.h" | 
 | #include "base/macros.h" | 
 | #include "base/memory/ref_counted.h" | 
 | #include "base/trace_event/heap_profiler_serialization_state.h" | 
 | #include "base/trace_event/memory_allocator_dump.h" | 
 | #include "base/trace_event/memory_allocator_dump_guid.h" | 
 | #include "base/trace_event/memory_dump_request_args.h" | 
 | #include "build_config.h" | 
 |  | 
 | // Define COUNT_RESIDENT_BYTES_SUPPORTED if platform supports counting of the | 
 | // resident memory. | 
 | #if !defined(OS_NACL) | 
 | #define COUNT_RESIDENT_BYTES_SUPPORTED | 
 | #endif | 
 |  | 
 | namespace base { | 
 |  | 
 | class SharedMemory; | 
 | class UnguessableToken; | 
 |  | 
 | namespace trace_event { | 
 |  | 
 | class HeapProfilerSerializationState; | 
 | class TracedValue; | 
 |  | 
 | // ProcessMemoryDump is as a strongly typed container which holds the dumps | 
 | // produced by the MemoryDumpProvider(s) for a specific process. | 
 | class BASE_EXPORT ProcessMemoryDump { | 
 |  public: | 
 |   struct BASE_EXPORT MemoryAllocatorDumpEdge { | 
 |     bool operator==(const MemoryAllocatorDumpEdge&) const; | 
 |     bool operator!=(const MemoryAllocatorDumpEdge&) const; | 
 |  | 
 |     MemoryAllocatorDumpGuid source; | 
 |     MemoryAllocatorDumpGuid target; | 
 |     int importance = 0; | 
 |     bool overridable = false; | 
 |   }; | 
 |  | 
 |   // Maps allocator dumps absolute names (allocator_name/heap/subheap) to | 
 |   // MemoryAllocatorDump instances. | 
 |   using AllocatorDumpsMap = | 
 |       std::map<std::string, std::unique_ptr<MemoryAllocatorDump>>; | 
 |  | 
 |   using HeapDumpsMap = std::map<std::string, std::unique_ptr<TracedValue>>; | 
 |  | 
 |   // Stores allocator dump edges indexed by source allocator dump GUID. | 
 |   using AllocatorDumpEdgesMap = | 
 |       std::map<MemoryAllocatorDumpGuid, MemoryAllocatorDumpEdge>; | 
 |  | 
 | #if defined(COUNT_RESIDENT_BYTES_SUPPORTED) | 
 |   // Returns the number of bytes in a kernel memory page. Some platforms may | 
 |   // have a different value for kernel page sizes from user page sizes. It is | 
 |   // important to use kernel memory page sizes for resident bytes calculation. | 
 |   // In most cases, the two are the same. | 
 |   static size_t GetSystemPageSize(); | 
 |  | 
 |   // Returns the total bytes resident for a virtual address range, with given | 
 |   // |start_address| and |mapped_size|. |mapped_size| is specified in bytes. The | 
 |   // value returned is valid only if the given range is currently mmapped by the | 
 |   // process. The |start_address| must be page-aligned. | 
 |   static size_t CountResidentBytes(void* start_address, size_t mapped_size); | 
 |  | 
 |   // The same as above, but the given mapped range should belong to the | 
 |   // shared_memory's mapped region. | 
 |   static base::Optional<size_t> CountResidentBytesInSharedMemory( | 
 |       void* start_address, | 
 |       size_t mapped_size); | 
 | #endif | 
 |  | 
 |   ProcessMemoryDump(scoped_refptr<HeapProfilerSerializationState> | 
 |                         heap_profiler_serialization_state, | 
 |                     const MemoryDumpArgs& dump_args); | 
 |   ProcessMemoryDump(ProcessMemoryDump&&); | 
 |   ~ProcessMemoryDump(); | 
 |  | 
 |   ProcessMemoryDump& operator=(ProcessMemoryDump&&); | 
 |  | 
 |   // Creates a new MemoryAllocatorDump with the given name and returns the | 
 |   // empty object back to the caller. | 
 |   // Arguments: | 
 |   //   absolute_name: a name that uniquely identifies allocator dumps produced | 
 |   //       by this provider. It is possible to specify nesting by using a | 
 |   //       path-like string (e.g., v8/isolate1/heap1, v8/isolate1/heap2). | 
 |   //       Leading or trailing slashes are not allowed. | 
 |   //   guid: an optional identifier, unique among all processes within the | 
 |   //       scope of a global dump. This is only relevant when using | 
 |   //       AddOwnershipEdge() to express memory sharing. If omitted, | 
 |   //       it will be automatically generated. | 
 |   // ProcessMemoryDump handles the memory ownership of its MemoryAllocatorDumps. | 
 |   MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name); | 
 |   MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name, | 
 |                                            const MemoryAllocatorDumpGuid& guid); | 
 |  | 
 |   // Looks up a MemoryAllocatorDump given its allocator and heap names, or | 
 |   // nullptr if not found. | 
 |   MemoryAllocatorDump* GetAllocatorDump(const std::string& absolute_name) const; | 
 |  | 
 |   // Do NOT use this method. All dump providers should use | 
 |   // CreateAllocatorDump(). Tries to create a new MemoryAllocatorDump only if it | 
 |   // doesn't already exist. Creating multiple dumps with same name using | 
 |   // GetOrCreateAllocatorDump() would override the existing scalars in MAD and | 
 |   // cause misreporting. This method is used only in rare cases multiple | 
 |   // components create allocator dumps with same name and only one of them adds | 
 |   // size. | 
 |   MemoryAllocatorDump* GetOrCreateAllocatorDump( | 
 |       const std::string& absolute_name); | 
 |  | 
 |   // Creates a shared MemoryAllocatorDump, to express cross-process sharing. | 
 |   // Shared allocator dumps are allowed to have duplicate guids within the | 
 |   // global scope, in order to reference the same dump from multiple processes. | 
 |   // See the design doc goo.gl/keU6Bf for reference usage patterns. | 
 |   MemoryAllocatorDump* CreateSharedGlobalAllocatorDump( | 
 |       const MemoryAllocatorDumpGuid& guid); | 
 |  | 
 |   // Creates a shared MemoryAllocatorDump as CreateSharedGlobalAllocatorDump, | 
 |   // but with a WEAK flag. A weak dump will be discarded unless a non-weak dump | 
 |   // is created using CreateSharedGlobalAllocatorDump by at least one process. | 
 |   // The WEAK flag does not apply if a non-weak dump with the same GUID already | 
 |   // exists or is created later. All owners and children of the discarded dump | 
 |   // will also be discarded transitively. | 
 |   MemoryAllocatorDump* CreateWeakSharedGlobalAllocatorDump( | 
 |       const MemoryAllocatorDumpGuid& guid); | 
 |  | 
 |   // Looks up a shared MemoryAllocatorDump given its guid. | 
 |   MemoryAllocatorDump* GetSharedGlobalAllocatorDump( | 
 |       const MemoryAllocatorDumpGuid& guid) const; | 
 |  | 
 |   // Returns the map of the MemoryAllocatorDumps added to this dump. | 
 |   const AllocatorDumpsMap& allocator_dumps() const { return allocator_dumps_; } | 
 |  | 
 |   AllocatorDumpsMap* mutable_allocator_dumps_for_serialization() const { | 
 |     // Mojo takes a const input argument even for move-only types that can be | 
 |     // mutate while serializing (like this one). Hence the const_cast. | 
 |     return const_cast<AllocatorDumpsMap*>(&allocator_dumps_); | 
 |   } | 
 |   void SetAllocatorDumpsForSerialization( | 
 |       std::vector<std::unique_ptr<MemoryAllocatorDump>>); | 
 |  | 
 |   // Only for mojo serialization. | 
 |   std::vector<MemoryAllocatorDumpEdge> GetAllEdgesForSerialization() const; | 
 |   void SetAllEdgesForSerialization(const std::vector<MemoryAllocatorDumpEdge>&); | 
 |  | 
 |   // Dumps heap usage with |allocator_name|. | 
 |   void DumpHeapUsage( | 
 |       const std::unordered_map<base::trace_event::AllocationContext, | 
 |                                base::trace_event::AllocationMetrics>& | 
 |           metrics_by_context, | 
 |       base::trace_event::TraceEventMemoryOverhead& overhead, | 
 |       const char* allocator_name); | 
 |  | 
 |   // Adds an ownership relationship between two MemoryAllocatorDump(s) with the | 
 |   // semantics: |source| owns |target|, and has the effect of attributing | 
 |   // the memory usage of |target| to |source|. |importance| is optional and | 
 |   // relevant only for the cases of co-ownership, where it acts as a z-index: | 
 |   // the owner with the highest importance will be attributed |target|'s memory. | 
 |   // If an edge is present, its importance will not be updated unless | 
 |   // |importance| is larger. | 
 |   void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, | 
 |                         const MemoryAllocatorDumpGuid& target, | 
 |                         int importance); | 
 |   void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, | 
 |                         const MemoryAllocatorDumpGuid& target); | 
 |  | 
 |   // Adds edges that can be overriden by a later or earlier call to | 
 |   // AddOwnershipEdge() with the same source and target with a different | 
 |   // |importance| value. | 
 |   void AddOverridableOwnershipEdge(const MemoryAllocatorDumpGuid& source, | 
 |                                    const MemoryAllocatorDumpGuid& target, | 
 |                                    int importance); | 
 |  | 
 |   // Creates ownership edges for memory backed by base::SharedMemory. Handles | 
 |   // the case of cross process sharing and importnace of ownership for the case | 
 |   // with and without the base::SharedMemory dump provider. The new version | 
 |   // should just use global dumps created by SharedMemoryTracker and this | 
 |   // function handles the transition until we get SharedMemory IDs through mojo | 
 |   // channel crbug.com/713763. The weak version creates a weak global dump. | 
 |   // |client_local_dump_guid| The guid of the local dump created by the client | 
 |   // of base::SharedMemory. | 
 |   // |shared_memory_guid| The ID of the base::SharedMemory that is assigned | 
 |   // globally, used to create global dump edges in the new model. | 
 |   // |importance| Importance of the global dump edges to say if the current | 
 |   // process owns the memory segment. | 
 |   void CreateSharedMemoryOwnershipEdge( | 
 |       const MemoryAllocatorDumpGuid& client_local_dump_guid, | 
 |       const UnguessableToken& shared_memory_guid, | 
 |       int importance); | 
 |   void CreateWeakSharedMemoryOwnershipEdge( | 
 |       const MemoryAllocatorDumpGuid& client_local_dump_guid, | 
 |       const UnguessableToken& shared_memory_guid, | 
 |       int importance); | 
 |  | 
 |   const AllocatorDumpEdgesMap& allocator_dumps_edges() const { | 
 |     return allocator_dumps_edges_; | 
 |   } | 
 |  | 
 |   // Utility method to add a suballocation relationship with the following | 
 |   // semantics: |source| is suballocated from |target_node_name|. | 
 |   // This creates a child node of |target_node_name| and adds an ownership edge | 
 |   // between |source| and the new child node. As a result, the UI will not | 
 |   // account the memory of |source| in the target node. | 
 |   void AddSuballocation(const MemoryAllocatorDumpGuid& source, | 
 |                         const std::string& target_node_name); | 
 |  | 
 |   const scoped_refptr<HeapProfilerSerializationState>& | 
 |   heap_profiler_serialization_state() const { | 
 |     return heap_profiler_serialization_state_; | 
 |   } | 
 |  | 
 |   // Removes all the MemoryAllocatorDump(s) contained in this instance. This | 
 |   // ProcessMemoryDump can be safely reused as if it was new once this returns. | 
 |   void Clear(); | 
 |  | 
 |   // Merges all MemoryAllocatorDump(s) contained in |other| inside this | 
 |   // ProcessMemoryDump, transferring their ownership to this instance. | 
 |   // |other| will be an empty ProcessMemoryDump after this method returns. | 
 |   // This is to allow dump providers to pre-populate ProcessMemoryDump instances | 
 |   // and later move their contents into the ProcessMemoryDump passed as argument | 
 |   // of the MemoryDumpProvider::OnMemoryDump(ProcessMemoryDump*) callback. | 
 |   void TakeAllDumpsFrom(ProcessMemoryDump* other); | 
 |  | 
 |   // Populate the traced value with information about the memory allocator | 
 |   // dumps. | 
 |   void SerializeAllocatorDumpsInto(TracedValue* value) const; | 
 |  | 
 |   // Populate the traced value with information about the heap profiler. | 
 |   void SerializeHeapProfilerDumpsInto(TracedValue* value) const; | 
 |  | 
 |   const HeapDumpsMap& heap_dumps() const { return heap_dumps_; } | 
 |  | 
 |   const MemoryDumpArgs& dump_args() const { return dump_args_; } | 
 |  | 
 |  private: | 
 |   FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, BackgroundModeTest); | 
 |   FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, SharedMemoryOwnershipTest); | 
 |   FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, GuidsTest); | 
 |  | 
 |   MemoryAllocatorDump* AddAllocatorDumpInternal( | 
 |       std::unique_ptr<MemoryAllocatorDump> mad); | 
 |  | 
 |   // A per-process token, valid throughout all the lifetime of the current | 
 |   // process, used to disambiguate dumps with the same name generated in | 
 |   // different processes. | 
 |   const UnguessableToken& process_token() const { return process_token_; } | 
 |   void set_process_token_for_testing(UnguessableToken token) { | 
 |     process_token_ = token; | 
 |   }; | 
 |  | 
 |   // Returns the Guid of the dump for the given |absolute_name| for | 
 |   // for the given process' token. |process_token| is used to disambiguate GUIDs | 
 |   // derived from the same name under different processes. | 
 |   MemoryAllocatorDumpGuid GetDumpId(const std::string& absolute_name); | 
 |  | 
 |   void CreateSharedMemoryOwnershipEdgeInternal( | 
 |       const MemoryAllocatorDumpGuid& client_local_dump_guid, | 
 |       const UnguessableToken& shared_memory_guid, | 
 |       int importance, | 
 |       bool is_weak); | 
 |  | 
 |   MemoryAllocatorDump* GetBlackHoleMad(); | 
 |  | 
 |   UnguessableToken process_token_; | 
 |   AllocatorDumpsMap allocator_dumps_; | 
 |   HeapDumpsMap heap_dumps_; | 
 |  | 
 |   // State shared among all PMDs instances created in a given trace session. | 
 |   scoped_refptr<HeapProfilerSerializationState> | 
 |       heap_profiler_serialization_state_; | 
 |  | 
 |   // Keeps track of relationships between MemoryAllocatorDump(s). | 
 |   AllocatorDumpEdgesMap allocator_dumps_edges_; | 
 |  | 
 |   // Level of detail of the current dump. | 
 |   MemoryDumpArgs dump_args_; | 
 |  | 
 |   // This allocator dump is returned when an invalid dump is created in | 
 |   // background mode. The attributes of the dump are ignored and not added to | 
 |   // the trace. | 
 |   std::unique_ptr<MemoryAllocatorDump> black_hole_mad_; | 
 |  | 
 |   // When set to true, the DCHECK(s) for invalid dump creations on the | 
 |   // background mode are disabled for testing. | 
 |   static bool is_black_hole_non_fatal_for_testing_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump); | 
 | }; | 
 |  | 
 | }  // namespace trace_event | 
 | }  // namespace base | 
 |  | 
 | #endif  // BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_ |