OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/profile-generator-inl.h" | 7 #include "src/profile-generator-inl.h" |
8 | 8 |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
| 11 #include "src/deoptimizer.h" |
11 #include "src/global-handles.h" | 12 #include "src/global-handles.h" |
12 #include "src/sampler.h" | 13 #include "src/sampler.h" |
13 #include "src/scopeinfo.h" | 14 #include "src/scopeinfo.h" |
14 #include "src/unicode.h" | 15 #include "src/unicode.h" |
15 | 16 |
16 namespace v8 { | 17 namespace v8 { |
17 namespace internal { | 18 namespace internal { |
18 | 19 |
19 | 20 |
20 bool StringsStorage::StringsMatch(void* key1, void* key2) { | 21 bool StringsStorage::StringsMatch(void* key1, void* key2) { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 if (pc_offset_map_.empty()) return v8::CpuProfileNode::kNoLineNumberInfo; | 153 if (pc_offset_map_.empty()) return v8::CpuProfileNode::kNoLineNumberInfo; |
153 return (--pc_offset_map_.end())->second; | 154 return (--pc_offset_map_.end())->second; |
154 } | 155 } |
155 return it->second; | 156 return it->second; |
156 } | 157 } |
157 | 158 |
158 | 159 |
159 const char* const CodeEntry::kEmptyNamePrefix = ""; | 160 const char* const CodeEntry::kEmptyNamePrefix = ""; |
160 const char* const CodeEntry::kEmptyResourceName = ""; | 161 const char* const CodeEntry::kEmptyResourceName = ""; |
161 const char* const CodeEntry::kEmptyBailoutReason = ""; | 162 const char* const CodeEntry::kEmptyBailoutReason = ""; |
| 163 const char* const CodeEntry::kNoDeoptReason = ""; |
162 | 164 |
163 | 165 |
164 CodeEntry::~CodeEntry() { | 166 CodeEntry::~CodeEntry() { |
165 delete no_frame_ranges_; | 167 delete no_frame_ranges_; |
166 delete line_info_; | 168 delete line_info_; |
167 } | 169 } |
168 | 170 |
169 | 171 |
170 uint32_t CodeEntry::GetCallUid() const { | 172 uint32_t CodeEntry::GetCallUid() const { |
171 uint32_t hash = ComputeIntegerHash(tag(), v8::internal::kZeroHashSeed); | 173 uint32_t hash = ComputeIntegerHash(tag(), v8::internal::kZeroHashSeed); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 | 207 |
206 | 208 |
207 int CodeEntry::GetSourceLine(int pc_offset) const { | 209 int CodeEntry::GetSourceLine(int pc_offset) const { |
208 if (line_info_ && !line_info_->empty()) { | 210 if (line_info_ && !line_info_->empty()) { |
209 return line_info_->GetSourceLineNumber(pc_offset); | 211 return line_info_->GetSourceLineNumber(pc_offset); |
210 } | 212 } |
211 return v8::CpuProfileNode::kNoLineNumberInfo; | 213 return v8::CpuProfileNode::kNoLineNumberInfo; |
212 } | 214 } |
213 | 215 |
214 | 216 |
| 217 void ProfileNode::CollectDeoptInfo(CodeEntry* entry) { |
| 218 deopt_infos_.Add(DeoptInfo(entry->deopt_reason(), entry->deopt_location())); |
| 219 entry->clear_deopt_info(); |
| 220 } |
| 221 |
| 222 |
215 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { | 223 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { |
216 HashMap::Entry* map_entry = | 224 HashMap::Entry* map_entry = |
217 children_.Lookup(entry, CodeEntryHash(entry), false); | 225 children_.Lookup(entry, CodeEntryHash(entry), false); |
218 return map_entry != NULL ? | 226 return map_entry != NULL ? |
219 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; | 227 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; |
220 } | 228 } |
221 | 229 |
222 | 230 |
223 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { | 231 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { |
224 HashMap::Entry* map_entry = | 232 HashMap::Entry* map_entry = |
225 children_.Lookup(entry, CodeEntryHash(entry), true); | 233 children_.Lookup(entry, CodeEntryHash(entry), true); |
226 if (map_entry->value == NULL) { | 234 ProfileNode* node = reinterpret_cast<ProfileNode*>(map_entry->value); |
| 235 if (node == NULL) { |
227 // New node added. | 236 // New node added. |
228 ProfileNode* new_node = new ProfileNode(tree_, entry); | 237 node = new ProfileNode(tree_, entry); |
229 map_entry->value = new_node; | 238 map_entry->value = node; |
230 children_list_.Add(new_node); | 239 children_list_.Add(node); |
231 } | 240 } |
232 return reinterpret_cast<ProfileNode*>(map_entry->value); | 241 return node; |
233 } | 242 } |
234 | 243 |
235 | 244 |
236 void ProfileNode::IncrementLineTicks(int src_line) { | 245 void ProfileNode::IncrementLineTicks(int src_line) { |
237 if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) return; | 246 if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) return; |
238 // Increment a hit counter of a certain source line. | 247 // Increment a hit counter of a certain source line. |
239 // Add a new source line if not found. | 248 // Add a new source line if not found. |
240 HashMap::Entry* e = | 249 HashMap::Entry* e = |
241 line_ticks_.Lookup(reinterpret_cast<void*>(src_line), src_line, true); | 250 line_ticks_.Lookup(reinterpret_cast<void*>(src_line), src_line, true); |
242 DCHECK(e); | 251 DCHECK(e); |
(...skipping 18 matching lines...) Expand all Loading... |
261 static_cast<unsigned int>(reinterpret_cast<uintptr_t>(p->key)); | 270 static_cast<unsigned int>(reinterpret_cast<uintptr_t>(p->key)); |
262 entry->hit_count = | 271 entry->hit_count = |
263 static_cast<unsigned int>(reinterpret_cast<uintptr_t>(p->value)); | 272 static_cast<unsigned int>(reinterpret_cast<uintptr_t>(p->value)); |
264 } | 273 } |
265 | 274 |
266 return true; | 275 return true; |
267 } | 276 } |
268 | 277 |
269 | 278 |
270 void ProfileNode::Print(int indent) { | 279 void ProfileNode::Print(int indent) { |
271 base::OS::Print("%5u %*s %s%s %d #%d %s", self_ticks_, indent, "", | 280 base::OS::Print("%5u %*s %s%s %d #%d", self_ticks_, indent, "", |
272 entry_->name_prefix(), entry_->name(), entry_->script_id(), | 281 entry_->name_prefix(), entry_->name(), entry_->script_id(), |
273 id(), entry_->bailout_reason()); | 282 id()); |
274 if (entry_->resource_name()[0] != '\0') | 283 if (entry_->resource_name()[0] != '\0') |
275 base::OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number()); | 284 base::OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number()); |
276 base::OS::Print("\n"); | 285 base::OS::Print("\n"); |
| 286 for (auto info : deopt_infos_) { |
| 287 base::OS::Print("%*s deopted at %d with reason '%s'\n", indent + 10, "", |
| 288 info.deopt_location, info.deopt_reason); |
| 289 } |
| 290 const char* bailout_reason = entry_->bailout_reason(); |
| 291 if (bailout_reason != GetBailoutReason(BailoutReason::kNoReason) && |
| 292 bailout_reason != CodeEntry::kEmptyBailoutReason) { |
| 293 base::OS::Print("%*s bailed out due to '%s'\n", indent + 10, "", |
| 294 bailout_reason); |
| 295 } |
277 for (HashMap::Entry* p = children_.Start(); | 296 for (HashMap::Entry* p = children_.Start(); |
278 p != NULL; | 297 p != NULL; |
279 p = children_.Next(p)) { | 298 p = children_.Next(p)) { |
280 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2); | 299 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2); |
281 } | 300 } |
282 } | 301 } |
283 | 302 |
284 | 303 |
285 class DeleteNodesCallback { | 304 class DeleteNodesCallback { |
286 public: | 305 public: |
(...skipping 16 matching lines...) Expand all Loading... |
303 | 322 |
304 ProfileTree::~ProfileTree() { | 323 ProfileTree::~ProfileTree() { |
305 DeleteNodesCallback cb; | 324 DeleteNodesCallback cb; |
306 TraverseDepthFirst(&cb); | 325 TraverseDepthFirst(&cb); |
307 } | 326 } |
308 | 327 |
309 | 328 |
310 ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path, | 329 ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path, |
311 int src_line) { | 330 int src_line) { |
312 ProfileNode* node = root_; | 331 ProfileNode* node = root_; |
| 332 CodeEntry* last_entry = NULL; |
313 for (CodeEntry** entry = path.start() + path.length() - 1; | 333 for (CodeEntry** entry = path.start() + path.length() - 1; |
314 entry != path.start() - 1; | 334 entry != path.start() - 1; |
315 --entry) { | 335 --entry) { |
316 if (*entry != NULL) { | 336 if (*entry != NULL) { |
317 node = node->FindOrAddChild(*entry); | 337 node = node->FindOrAddChild(*entry); |
| 338 last_entry = *entry; |
318 } | 339 } |
319 } | 340 } |
| 341 if (last_entry && last_entry->has_deopt_info()) { |
| 342 node->CollectDeoptInfo(last_entry); |
| 343 } |
320 node->IncrementSelfTicks(); | 344 node->IncrementSelfTicks(); |
321 if (src_line != v8::CpuProfileNode::kNoLineNumberInfo) { | 345 if (src_line != v8::CpuProfileNode::kNoLineNumberInfo) { |
322 node->IncrementLineTicks(src_line); | 346 node->IncrementLineTicks(src_line); |
323 } | 347 } |
324 return node; | 348 return node; |
325 } | 349 } |
326 | 350 |
327 | 351 |
328 struct NodesPair { | 352 struct NodesPair { |
329 NodesPair(ProfileNode* src, ProfileNode* dst) | 353 NodesPair(ProfileNode* src, ProfileNode* dst) |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 case OTHER: | 762 case OTHER: |
739 case EXTERNAL: | 763 case EXTERNAL: |
740 return program_entry_; | 764 return program_entry_; |
741 case IDLE: | 765 case IDLE: |
742 return idle_entry_; | 766 return idle_entry_; |
743 default: return NULL; | 767 default: return NULL; |
744 } | 768 } |
745 } | 769 } |
746 | 770 |
747 } } // namespace v8::internal | 771 } } // namespace v8::internal |
OLD | NEW |