Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: src/allocation-tracker.cc

Issue 177203002: Allocation tracker: add separate entry for allocations via V8 API (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Reverted v8globals.h changes Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/allocation-tracker.h ('k') | src/heap-snapshot-generator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 18 matching lines...) Expand all
29 29
30 #include "allocation-tracker.h" 30 #include "allocation-tracker.h"
31 31
32 #include "heap-snapshot-generator.h" 32 #include "heap-snapshot-generator.h"
33 #include "frames-inl.h" 33 #include "frames-inl.h"
34 34
35 namespace v8 { 35 namespace v8 {
36 namespace internal { 36 namespace internal {
37 37
38 AllocationTraceNode::AllocationTraceNode( 38 AllocationTraceNode::AllocationTraceNode(
39 AllocationTraceTree* tree, SnapshotObjectId shared_function_info_id) 39 AllocationTraceTree* tree, unsigned function_info_index)
40 : tree_(tree), 40 : tree_(tree),
41 function_id_(shared_function_info_id), 41 function_info_index_(function_info_index),
42 total_size_(0), 42 total_size_(0),
43 allocation_count_(0), 43 allocation_count_(0),
44 id_(tree->next_node_id()) { 44 id_(tree->next_node_id()) {
45 } 45 }
46 46
47 47
48 AllocationTraceNode::~AllocationTraceNode() { 48 AllocationTraceNode::~AllocationTraceNode() {
49 for (int i = 0; i < children_.length(); i++) delete children_[i]; 49 for (int i = 0; i < children_.length(); i++) delete children_[i];
50 } 50 }
51 51
52 52
53 AllocationTraceNode* AllocationTraceNode::FindChild(SnapshotObjectId id) { 53 AllocationTraceNode* AllocationTraceNode::FindChild(
54 unsigned function_info_index) {
54 for (int i = 0; i < children_.length(); i++) { 55 for (int i = 0; i < children_.length(); i++) {
55 AllocationTraceNode* node = children_[i]; 56 AllocationTraceNode* node = children_[i];
56 if (node->function_id() == id) return node; 57 if (node->function_info_index() == function_info_index) return node;
57 } 58 }
58 return NULL; 59 return NULL;
59 } 60 }
60 61
61 62
62 AllocationTraceNode* AllocationTraceNode::FindOrAddChild(SnapshotObjectId id) { 63 AllocationTraceNode* AllocationTraceNode::FindOrAddChild(
63 AllocationTraceNode* child = FindChild(id); 64 unsigned function_info_index) {
65 AllocationTraceNode* child = FindChild(function_info_index);
64 if (child == NULL) { 66 if (child == NULL) {
65 child = new AllocationTraceNode(tree_, id); 67 child = new AllocationTraceNode(tree_, function_info_index);
66 children_.Add(child); 68 children_.Add(child);
67 } 69 }
68 return child; 70 return child;
69 } 71 }
70 72
71 73
72 void AllocationTraceNode::AddAllocation(unsigned size) { 74 void AllocationTraceNode::AddAllocation(unsigned size) {
73 total_size_ += size; 75 total_size_ += size;
74 ++allocation_count_; 76 ++allocation_count_;
75 } 77 }
76 78
77 79
78 void AllocationTraceNode::Print(int indent, AllocationTracker* tracker) { 80 void AllocationTraceNode::Print(int indent, AllocationTracker* tracker) {
79 OS::Print("%10u %10u %*c", total_size_, allocation_count_, indent, ' '); 81 OS::Print("%10u %10u %*c", total_size_, allocation_count_, indent, ' ');
80 if (tracker != NULL) { 82 if (tracker != NULL) {
81 const char* name = "<unknown function>"; 83 AllocationTracker::FunctionInfo* info =
82 if (function_id_ != 0) { 84 tracker->function_info_list()[function_info_index_];
83 AllocationTracker::FunctionInfo* info = 85 OS::Print("%s #%u", info->name, id_);
84 tracker->GetFunctionInfo(function_id_);
85 if (info != NULL) {
86 name = info->name;
87 }
88 }
89 OS::Print("%s #%u", name, id_);
90 } else { 86 } else {
91 OS::Print("%u #%u", function_id_, id_); 87 OS::Print("%u #%u", function_info_index_, id_);
92 } 88 }
93 OS::Print("\n"); 89 OS::Print("\n");
94 indent += 2; 90 indent += 2;
95 for (int i = 0; i < children_.length(); i++) { 91 for (int i = 0; i < children_.length(); i++) {
96 children_[i]->Print(indent, tracker); 92 children_[i]->Print(indent, tracker);
97 } 93 }
98 } 94 }
99 95
100 96
101 AllocationTraceTree::AllocationTraceTree() 97 AllocationTraceTree::AllocationTraceTree()
102 : next_node_id_(1), 98 : next_node_id_(1),
103 root_(this, 0) { 99 root_(this, 0) {
104 } 100 }
105 101
106 102
107 AllocationTraceTree::~AllocationTraceTree() { 103 AllocationTraceTree::~AllocationTraceTree() {
108 } 104 }
109 105
110 106
111 AllocationTraceNode* AllocationTraceTree::AddPathFromEnd( 107 AllocationTraceNode* AllocationTraceTree::AddPathFromEnd(
112 const Vector<SnapshotObjectId>& path) { 108 const Vector<unsigned>& path) {
113 AllocationTraceNode* node = root(); 109 AllocationTraceNode* node = root();
114 for (SnapshotObjectId* entry = path.start() + path.length() - 1; 110 for (unsigned* entry = path.start() + path.length() - 1;
115 entry != path.start() - 1; 111 entry != path.start() - 1;
116 --entry) { 112 --entry) {
117 node = node->FindOrAddChild(*entry); 113 node = node->FindOrAddChild(*entry);
118 } 114 }
119 return node; 115 return node;
120 } 116 }
121 117
122 118
123 void AllocationTraceTree::Print(AllocationTracker* tracker) { 119 void AllocationTraceTree::Print(AllocationTracker* tracker) {
124 OS::Print("[AllocationTraceTree:]\n"); 120 OS::Print("[AllocationTraceTree:]\n");
125 OS::Print("Total size | Allocation count | Function id | id\n"); 121 OS::Print("Total size | Allocation count | Function id | id\n");
126 root()->Print(0, tracker); 122 root()->Print(0, tracker);
127 } 123 }
128 124
125
129 void AllocationTracker::DeleteUnresolvedLocation( 126 void AllocationTracker::DeleteUnresolvedLocation(
130 UnresolvedLocation** location) { 127 UnresolvedLocation** location) {
131 delete *location; 128 delete *location;
132 } 129 }
133 130
134 131
135 AllocationTracker::FunctionInfo::FunctionInfo() 132 AllocationTracker::FunctionInfo::FunctionInfo()
136 : name(""), 133 : name(""),
134 function_id(0),
137 script_name(""), 135 script_name(""),
138 script_id(0), 136 script_id(0),
139 line(-1), 137 line(-1),
140 column(-1) { 138 column(-1) {
141 } 139 }
142 140
143 141
144 static bool AddressesMatch(void* key1, void* key2) { 142 static bool AddressesMatch(void* key1, void* key2) {
145 return key1 == key2; 143 return key1 == key2;
146 } 144 }
147 145
148 146
147 void AllocationTracker::DeleteFunctionInfo(FunctionInfo** info) {
148 delete *info;
149 }
150
151
149 AllocationTracker::AllocationTracker( 152 AllocationTracker::AllocationTracker(
150 HeapObjectsMap* ids, StringsStorage* names) 153 HeapObjectsMap* ids, StringsStorage* names)
151 : ids_(ids), 154 : ids_(ids),
152 names_(names), 155 names_(names),
153 id_to_function_info_(AddressesMatch) { 156 id_to_function_info_index_(AddressesMatch),
157 info_index_for_other_state_(0) {
158 FunctionInfo* info = new FunctionInfo();
159 info->name = "(root)";
160 function_info_list_.Add(info);
154 } 161 }
155 162
156 163
157 AllocationTracker::~AllocationTracker() { 164 AllocationTracker::~AllocationTracker() {
158 unresolved_locations_.Iterate(DeleteUnresolvedLocation); 165 unresolved_locations_.Iterate(DeleteUnresolvedLocation);
159 for (HashMap::Entry* p = id_to_function_info_.Start(); 166 function_info_list_.Iterate(&DeleteFunctionInfo);
160 p != NULL;
161 p = id_to_function_info_.Next(p)) {
162 delete reinterpret_cast<AllocationTracker::FunctionInfo* >(p->value);
163 }
164 } 167 }
165 168
166 169
167 void AllocationTracker::PrepareForSerialization() { 170 void AllocationTracker::PrepareForSerialization() {
168 List<UnresolvedLocation*> copy(unresolved_locations_.length()); 171 List<UnresolvedLocation*> copy(unresolved_locations_.length());
169 copy.AddAll(unresolved_locations_); 172 copy.AddAll(unresolved_locations_);
170 unresolved_locations_.Clear(); 173 unresolved_locations_.Clear();
171 for (int i = 0; i < copy.length(); i++) { 174 for (int i = 0; i < copy.length(); i++) {
172 copy[i]->Resolve(); 175 copy[i]->Resolve();
173 delete copy[i]; 176 delete copy[i];
(...skipping 12 matching lines...) Expand all
186 ASSERT(FreeListNode::IsFreeListNode(HeapObject::FromAddress(addr))); 189 ASSERT(FreeListNode::IsFreeListNode(HeapObject::FromAddress(addr)));
187 190
188 Isolate* isolate = heap->isolate(); 191 Isolate* isolate = heap->isolate();
189 int length = 0; 192 int length = 0;
190 StackTraceFrameIterator it(isolate); 193 StackTraceFrameIterator it(isolate);
191 while (!it.done() && length < kMaxAllocationTraceLength) { 194 while (!it.done() && length < kMaxAllocationTraceLength) {
192 JavaScriptFrame* frame = it.frame(); 195 JavaScriptFrame* frame = it.frame();
193 SharedFunctionInfo* shared = frame->function()->shared(); 196 SharedFunctionInfo* shared = frame->function()->shared();
194 SnapshotObjectId id = ids_->FindOrAddEntry( 197 SnapshotObjectId id = ids_->FindOrAddEntry(
195 shared->address(), shared->Size(), false); 198 shared->address(), shared->Size(), false);
196 allocation_trace_buffer_[length++] = id; 199 allocation_trace_buffer_[length++] = AddFunctionInfo(shared, id);
197 AddFunctionInfo(shared, id);
198 it.Advance(); 200 it.Advance();
199 } 201 }
202 if (length == 0) {
203 unsigned index = functionInfoIndexForVMState(isolate->current_vm_state());
204 if (index != 0) {
205 allocation_trace_buffer_[length++] = index;
206 }
207 }
200 AllocationTraceNode* top_node = trace_tree_.AddPathFromEnd( 208 AllocationTraceNode* top_node = trace_tree_.AddPathFromEnd(
201 Vector<SnapshotObjectId>(allocation_trace_buffer_, length)); 209 Vector<unsigned>(allocation_trace_buffer_, length));
202 top_node->AddAllocation(size); 210 top_node->AddAllocation(size);
203 } 211 }
204 212
205 213
206 static uint32_t SnapshotObjectIdHash(SnapshotObjectId id) { 214 static uint32_t SnapshotObjectIdHash(SnapshotObjectId id) {
207 return ComputeIntegerHash(static_cast<uint32_t>(id), 215 return ComputeIntegerHash(static_cast<uint32_t>(id),
208 v8::internal::kZeroHashSeed); 216 v8::internal::kZeroHashSeed);
209 } 217 }
210 218
211 219
212 AllocationTracker::FunctionInfo* AllocationTracker::GetFunctionInfo( 220 unsigned AllocationTracker::AddFunctionInfo(SharedFunctionInfo* shared,
213 SnapshotObjectId id) { 221 SnapshotObjectId id) {
214 HashMap::Entry* entry = id_to_function_info_.Lookup( 222 HashMap::Entry* entry = id_to_function_info_index_.Lookup(
215 reinterpret_cast<void*>(id), SnapshotObjectIdHash(id), false);
216 if (entry == NULL) {
217 return NULL;
218 }
219 return reinterpret_cast<FunctionInfo*>(entry->value);
220 }
221
222
223 void AllocationTracker::AddFunctionInfo(SharedFunctionInfo* shared,
224 SnapshotObjectId id) {
225 HashMap::Entry* entry = id_to_function_info_.Lookup(
226 reinterpret_cast<void*>(id), SnapshotObjectIdHash(id), true); 223 reinterpret_cast<void*>(id), SnapshotObjectIdHash(id), true);
227 if (entry->value == NULL) { 224 if (entry->value == NULL) {
228 FunctionInfo* info = new FunctionInfo(); 225 FunctionInfo* info = new FunctionInfo();
229 info->name = names_->GetFunctionName(shared->DebugName()); 226 info->name = names_->GetFunctionName(shared->DebugName());
227 info->function_id = id;
230 if (shared->script()->IsScript()) { 228 if (shared->script()->IsScript()) {
231 Script* script = Script::cast(shared->script()); 229 Script* script = Script::cast(shared->script());
232 if (script->name()->IsName()) { 230 if (script->name()->IsName()) {
233 Name* name = Name::cast(script->name()); 231 Name* name = Name::cast(script->name());
234 info->script_name = names_->GetName(name); 232 info->script_name = names_->GetName(name);
235 } 233 }
236 info->script_id = script->id()->value(); 234 info->script_id = script->id()->value();
237 // Converting start offset into line and column may cause heap 235 // Converting start offset into line and column may cause heap
238 // allocations so we postpone them until snapshot serialization. 236 // allocations so we postpone them until snapshot serialization.
239 unresolved_locations_.Add(new UnresolvedLocation( 237 unresolved_locations_.Add(new UnresolvedLocation(
240 script, 238 script,
241 shared->start_position(), 239 shared->start_position(),
242 info)); 240 info));
243 } 241 }
244 entry->value = info; 242 entry->value = reinterpret_cast<void*>(function_info_list_.length());
243 function_info_list_.Add(info);
245 } 244 }
245 return static_cast<unsigned>(reinterpret_cast<intptr_t>((entry->value)));
246 } 246 }
247 247
248 248
249 unsigned AllocationTracker::functionInfoIndexForVMState(StateTag state) {
250 if (state != OTHER) return 0;
251 if (info_index_for_other_state_ == 0) {
252 FunctionInfo* info = new FunctionInfo();
253 info->name = "(V8 API)";
254 info_index_for_other_state_ = function_info_list_.length();
255 function_info_list_.Add(info);
256 }
257 return info_index_for_other_state_;
258 }
259
260
249 AllocationTracker::UnresolvedLocation::UnresolvedLocation( 261 AllocationTracker::UnresolvedLocation::UnresolvedLocation(
250 Script* script, int start, FunctionInfo* info) 262 Script* script, int start, FunctionInfo* info)
251 : start_position_(start), 263 : start_position_(start),
252 info_(info) { 264 info_(info) {
253 script_ = Handle<Script>::cast( 265 script_ = Handle<Script>::cast(
254 script->GetIsolate()->global_handles()->Create(script)); 266 script->GetIsolate()->global_handles()->Create(script));
255 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()), 267 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
256 this, 268 this,
257 &HandleWeakScript); 269 &HandleWeakScript);
258 } 270 }
(...skipping 17 matching lines...) Expand all
276 void AllocationTracker::UnresolvedLocation::HandleWeakScript( 288 void AllocationTracker::UnresolvedLocation::HandleWeakScript(
277 const v8::WeakCallbackData<v8::Value, void>& data) { 289 const v8::WeakCallbackData<v8::Value, void>& data) {
278 UnresolvedLocation* loc = 290 UnresolvedLocation* loc =
279 reinterpret_cast<UnresolvedLocation*>(data.GetParameter()); 291 reinterpret_cast<UnresolvedLocation*>(data.GetParameter());
280 GlobalHandles::Destroy(reinterpret_cast<Object**>(loc->script_.location())); 292 GlobalHandles::Destroy(reinterpret_cast<Object**>(loc->script_.location()));
281 loc->script_ = Handle<Script>::null(); 293 loc->script_ = Handle<Script>::null();
282 } 294 }
283 295
284 296
285 } } // namespace v8::internal 297 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/allocation-tracker.h ('k') | src/heap-snapshot-generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698