1 // Copyright 2013 the V8 project 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 V8_PROFILER_ALLOCATION_TRACKER_H_
6 #define V8_PROFILER_ALLOCATION_TRACKER_H_
7 
8 #include <map>
9 #include <vector>
10 
11 #include "include/v8-persistent-handle.h"
12 #include "include/v8-profiler.h"
13 #include "include/v8-unwinder.h"
14 #include "src/base/hashmap.h"
15 #include "src/base/vector.h"
16 #include "src/handles/handles.h"
17 
18 namespace v8 {
19 namespace internal {
20 
21 // Forward declarations.
22 class AllocationTraceTree;
23 class AllocationTracker;
24 class HeapObjectsMap;
25 class SharedFunctionInfo;
26 class StringsStorage;
27 
28 class AllocationTraceNode {
29  public:
30   AllocationTraceNode(AllocationTraceTree* tree,
31                       unsigned function_info_index);
32   ~AllocationTraceNode();
33   AllocationTraceNode(const AllocationTraceNode&) = delete;
34   AllocationTraceNode& operator=(const AllocationTraceNode&) = delete;
35   AllocationTraceNode* FindChild(unsigned function_info_index);
36   AllocationTraceNode* FindOrAddChild(unsigned function_info_index);
37   void AddAllocation(unsigned size);
38 
function_info_index()39   unsigned function_info_index() const { return function_info_index_; }
allocation_size()40   unsigned allocation_size() const { return total_size_; }
allocation_count()41   unsigned allocation_count() const { return allocation_count_; }
id()42   unsigned id() const { return id_; }
children()43   const std::vector<AllocationTraceNode*>& children() const {
44     return children_;
45   }
46 
47   void Print(int indent, AllocationTracker* tracker);
48 
49  private:
50   AllocationTraceTree* tree_;
51   unsigned function_info_index_;
52   unsigned total_size_;
53   unsigned allocation_count_;
54   unsigned id_;
55   std::vector<AllocationTraceNode*> children_;
56 };
57 
58 
59 class AllocationTraceTree {
60  public:
61   AllocationTraceTree();
62   ~AllocationTraceTree() = default;
63   AllocationTraceTree(const AllocationTraceTree&) = delete;
64   AllocationTraceTree& operator=(const AllocationTraceTree&) = delete;
65   AllocationTraceNode* AddPathFromEnd(const base::Vector<unsigned>& path);
root()66   AllocationTraceNode* root() { return &root_; }
next_node_id()67   unsigned next_node_id() { return next_node_id_++; }
68   V8_EXPORT_PRIVATE void Print(AllocationTracker* tracker);
69 
70  private:
71   unsigned next_node_id_;
72   AllocationTraceNode root_;
73 };
74 
75 class V8_EXPORT_PRIVATE AddressToTraceMap {
76  public:
77   void AddRange(Address addr, int size, unsigned node_id);
78   unsigned GetTraceNodeId(Address addr);
79   void MoveObject(Address from, Address to, int size);
80   void Clear();
size()81   size_t size() { return ranges_.size(); }
82   void Print();
83 
84  private:
85   struct RangeStack {
RangeStackRangeStack86     RangeStack(Address start, unsigned node_id)
87         : start(start), trace_node_id(node_id) {}
88     Address start;
89     unsigned trace_node_id;
90   };
91   // [start, end) -> trace
92   using RangeMap = std::map<Address, RangeStack>;
93 
94   void RemoveRange(Address start, Address end);
95 
96   RangeMap ranges_;
97 };
98 
99 class AllocationTracker {
100  public:
101   struct FunctionInfo {
102     FunctionInfo();
103     const char* name;
104     SnapshotObjectId function_id;
105     const char* script_name;
106     int script_id;
107     int line;
108     int column;
109   };
110 
111   AllocationTracker(HeapObjectsMap* ids, StringsStorage* names);
112   ~AllocationTracker();
113   AllocationTracker(const AllocationTracker&) = delete;
114   AllocationTracker& operator=(const AllocationTracker&) = delete;
115 
116   V8_EXPORT_PRIVATE void PrepareForSerialization();
117   void AllocationEvent(Address addr, int size);
118 
trace_tree()119   AllocationTraceTree* trace_tree() { return &trace_tree_; }
function_info_list()120   const std::vector<FunctionInfo*>& function_info_list() const {
121     return function_info_list_;
122   }
address_to_trace()123   AddressToTraceMap* address_to_trace() { return &address_to_trace_; }
124 
125  private:
126   unsigned AddFunctionInfo(SharedFunctionInfo info, SnapshotObjectId id);
127   unsigned functionInfoIndexForVMState(StateTag state);
128 
129   class UnresolvedLocation {
130    public:
131     UnresolvedLocation(Script script, int start, FunctionInfo* info);
132     ~UnresolvedLocation();
133     void Resolve();
134 
135    private:
136     static void HandleWeakScript(const v8::WeakCallbackInfo<void>& data);
137 
138     Handle<Script> script_;
139     int start_position_;
140     FunctionInfo* info_;
141   };
142 
143   static const int kMaxAllocationTraceLength = 64;
144   HeapObjectsMap* ids_;
145   StringsStorage* names_;
146   AllocationTraceTree trace_tree_;
147   unsigned allocation_trace_buffer_[kMaxAllocationTraceLength];
148   std::vector<FunctionInfo*> function_info_list_;
149   base::HashMap id_to_function_info_index_;
150   std::vector<UnresolvedLocation*> unresolved_locations_;
151   unsigned info_index_for_other_state_;
152   AddressToTraceMap address_to_trace_;
153 };
154 
155 }  // namespace internal
156 }  // namespace v8
157 
158 #endif  // V8_PROFILER_ALLOCATION_TRACKER_H_
159