1// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
6#define BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
7
8#include <stddef.h>
9
10#include <vector>
11
12#include "base/base_export.h"
13#include "base/containers/hash_tables.h"
14#include "base/containers/small_map.h"
15#include "base/macros.h"
16#include "base/memory/ref_counted.h"
17#include "base/memory/scoped_vector.h"
18#include "base/trace_event/memory_allocator_dump.h"
19#include "base/trace_event/memory_allocator_dump_guid.h"
20#include "base/trace_event/memory_dump_session_state.h"
21#include "base/trace_event/process_memory_maps.h"
22#include "base/trace_event/process_memory_totals.h"
23#include "build/build_config.h"
24
25// Define COUNT_RESIDENT_BYTES_SUPPORTED if platform supports counting of the
26// resident memory.
27// TODO(crbug.com/542671): COUNT_RESIDENT_BYTES_SUPPORTED is disabled on iOS
28// as it cause memory corruption on iOS 9.0+ devices.
29#if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_IOS)
30#define COUNT_RESIDENT_BYTES_SUPPORTED
31#endif
32
33namespace base {
34namespace trace_event {
35
36class ConvertableToTraceFormat;
37class MemoryDumpManager;
38class MemoryDumpSessionState;
39class TracedValue;
40
41// ProcessMemoryDump is as a strongly typed container which holds the dumps
42// produced by the MemoryDumpProvider(s) for a specific process.
43class BASE_EXPORT ProcessMemoryDump {
44 public:
45  struct MemoryAllocatorDumpEdge {
46    MemoryAllocatorDumpGuid source;
47    MemoryAllocatorDumpGuid target;
48    int importance;
49    const char* type;
50  };
51
52  // Maps allocator dumps absolute names (allocator_name/heap/subheap) to
53  // MemoryAllocatorDump instances.
54  using AllocatorDumpsMap =
55      SmallMap<hash_map<std::string, MemoryAllocatorDump*>>;
56
57  using HeapDumpsMap =
58      SmallMap<hash_map<std::string, scoped_refptr<TracedValue>>>;
59
60#if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
61  // Returns the total bytes resident for a virtual address range, with given
62  // |start_address| and |mapped_size|. |mapped_size| is specified in bytes. The
63  // value returned is valid only if the given range is currently mmapped by the
64  // process. The |start_address| must be page-aligned.
65  static size_t CountResidentBytes(void* start_address, size_t mapped_size);
66#endif
67
68  ProcessMemoryDump(const scoped_refptr<MemoryDumpSessionState>& session_state);
69  ~ProcessMemoryDump();
70
71  // Creates a new MemoryAllocatorDump with the given name and returns the
72  // empty object back to the caller.
73  // Arguments:
74  //   absolute_name: a name that uniquely identifies allocator dumps produced
75  //       by this provider. It is possible to specify nesting by using a
76  //       path-like string (e.g., v8/isolate1/heap1, v8/isolate1/heap2).
77  //       Leading or trailing slashes are not allowed.
78  //   guid: an optional identifier, unique among all processes within the
79  //       scope of a global dump. This is only relevant when using
80  //       AddOwnershipEdge() to express memory sharing. If omitted,
81  //       it will be automatically generated.
82  // ProcessMemoryDump handles the memory ownership of its MemoryAllocatorDumps.
83  MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name);
84  MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name,
85                                           const MemoryAllocatorDumpGuid& guid);
86
87  // Looks up a MemoryAllocatorDump given its allocator and heap names, or
88  // nullptr if not found.
89  MemoryAllocatorDump* GetAllocatorDump(const std::string& absolute_name) const;
90
91  MemoryAllocatorDump* GetOrCreateAllocatorDump(
92      const std::string& absolute_name);
93
94  // Creates a shared MemoryAllocatorDump, to express cross-process sharing.
95  // Shared allocator dumps are allowed to have duplicate guids within the
96  // global scope, in order to reference the same dump from multiple processes.
97  // See the design doc goo.gl/keU6Bf for reference usage patterns.
98  MemoryAllocatorDump* CreateSharedGlobalAllocatorDump(
99      const MemoryAllocatorDumpGuid& guid);
100
101  // Looks up a shared MemoryAllocatorDump given its guid.
102  MemoryAllocatorDump* GetSharedGlobalAllocatorDump(
103      const MemoryAllocatorDumpGuid& guid) const;
104
105  // Returns the map of the MemoryAllocatorDumps added to this dump.
106  const AllocatorDumpsMap& allocator_dumps() const { return allocator_dumps_; }
107
108  // Adds a heap dump for the allocator with |absolute_name|. The |TracedValue|
109  // must have the correct format. |trace_event::HeapDumper| will generate such
110  // a value from a |trace_event::AllocationRegister|.
111  void AddHeapDump(const std::string& absolute_name,
112                   scoped_refptr<TracedValue> heap_dump);
113
114  // Adds an ownership relationship between two MemoryAllocatorDump(s) with the
115  // semantics: |source| owns |target|, and has the effect of attributing
116  // the memory usage of |target| to |source|. |importance| is optional and
117  // relevant only for the cases of co-ownership, where it acts as a z-index:
118  // the owner with the highest importance will be attributed |target|'s memory.
119  void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source,
120                        const MemoryAllocatorDumpGuid& target,
121                        int importance);
122  void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source,
123                        const MemoryAllocatorDumpGuid& target);
124
125  const std::vector<MemoryAllocatorDumpEdge>& allocator_dumps_edges() const {
126    return allocator_dumps_edges_;
127  }
128
129  // Utility method to add a suballocation relationship with the following
130  // semantics: |source| is suballocated from |target_node_name|.
131  // This creates a child node of |target_node_name| and adds an ownership edge
132  // between |source| and the new child node. As a result, the UI will not
133  // account the memory of |source| in the target node.
134  void AddSuballocation(const MemoryAllocatorDumpGuid& source,
135                        const std::string& target_node_name);
136
137  const scoped_refptr<MemoryDumpSessionState>& session_state() const {
138    return session_state_;
139  }
140
141  // Removes all the MemoryAllocatorDump(s) contained in this instance. This
142  // ProcessMemoryDump can be safely reused as if it was new once this returns.
143  void Clear();
144
145  // Merges all MemoryAllocatorDump(s) contained in |other| inside this
146  // ProcessMemoryDump, transferring their ownership to this instance.
147  // |other| will be an empty ProcessMemoryDump after this method returns.
148  // This is to allow dump providers to pre-populate ProcessMemoryDump instances
149  // and later move their contents into the ProcessMemoryDump passed as argument
150  // of the MemoryDumpProvider::OnMemoryDump(ProcessMemoryDump*) callback.
151  void TakeAllDumpsFrom(ProcessMemoryDump* other);
152
153  // Called at trace generation time to populate the TracedValue.
154  void AsValueInto(TracedValue* value) const;
155
156  ProcessMemoryTotals* process_totals() { return &process_totals_; }
157  bool has_process_totals() const { return has_process_totals_; }
158  void set_has_process_totals() { has_process_totals_ = true; }
159
160  ProcessMemoryMaps* process_mmaps() { return &process_mmaps_; }
161  bool has_process_mmaps() const { return has_process_mmaps_; }
162  void set_has_process_mmaps() { has_process_mmaps_ = true; }
163
164 private:
165  void AddAllocatorDumpInternal(MemoryAllocatorDump* mad);
166
167  ProcessMemoryTotals process_totals_;
168  bool has_process_totals_;
169
170  ProcessMemoryMaps process_mmaps_;
171  bool has_process_mmaps_;
172
173  AllocatorDumpsMap allocator_dumps_;
174  HeapDumpsMap heap_dumps_;
175
176  // ProcessMemoryDump handles the memory ownership of all its belongings.
177  ScopedVector<MemoryAllocatorDump> allocator_dumps_storage_;
178
179  // State shared among all PMDs instances created in a given trace session.
180  scoped_refptr<MemoryDumpSessionState> session_state_;
181
182  // Keeps track of relationships between MemoryAllocatorDump(s).
183  std::vector<MemoryAllocatorDumpEdge> allocator_dumps_edges_;
184
185  DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump);
186};
187
188}  // namespace trace_event
189}  // namespace base
190
191#endif  // BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
192