|  | // 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 <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_allocation_context.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/build_config.h" | 
|  | #include "starboard/types.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 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>>; | 
|  |  | 
|  | // 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 | 
|  |  | 
|  | explicit ProcessMemoryDump(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); | 
|  |  | 
|  | // 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; | 
|  |  | 
|  | 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_; | 
|  |  | 
|  | // 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_ |