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