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" |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 const char* const CodeEntry::kEmptyBailoutReason = ""; | 162 const char* const CodeEntry::kEmptyBailoutReason = ""; |
163 const char* const CodeEntry::kNoDeoptReason = ""; | 163 const char* const CodeEntry::kNoDeoptReason = ""; |
164 | 164 |
165 | 165 |
166 CodeEntry::~CodeEntry() { | 166 CodeEntry::~CodeEntry() { |
167 delete no_frame_ranges_; | 167 delete no_frame_ranges_; |
168 delete line_info_; | 168 delete line_info_; |
169 } | 169 } |
170 | 170 |
171 | 171 |
172 uint32_t CodeEntry::GetCallUid() const { | 172 uint32_t CodeEntry::GetHash() const { |
173 uint32_t hash = ComputeIntegerHash(tag(), v8::internal::kZeroHashSeed); | 173 uint32_t hash = ComputeIntegerHash(tag(), v8::internal::kZeroHashSeed); |
174 if (shared_id_ != 0) { | 174 if (script_id_ != v8::UnboundScript::kNoScriptId) { |
175 hash ^= ComputeIntegerHash(static_cast<uint32_t>(shared_id_), | 175 hash ^= ComputeIntegerHash(static_cast<uint32_t>(script_id_), |
| 176 v8::internal::kZeroHashSeed); |
| 177 hash ^= ComputeIntegerHash(static_cast<uint32_t>(position_), |
176 v8::internal::kZeroHashSeed); | 178 v8::internal::kZeroHashSeed); |
177 } else { | 179 } else { |
178 hash ^= ComputeIntegerHash( | 180 hash ^= ComputeIntegerHash( |
179 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_)), | 181 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_)), |
180 v8::internal::kZeroHashSeed); | 182 v8::internal::kZeroHashSeed); |
181 hash ^= ComputeIntegerHash( | 183 hash ^= ComputeIntegerHash( |
182 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_)), | 184 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_)), |
183 v8::internal::kZeroHashSeed); | 185 v8::internal::kZeroHashSeed); |
184 hash ^= ComputeIntegerHash( | 186 hash ^= ComputeIntegerHash( |
185 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(resource_name_)), | 187 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(resource_name_)), |
186 v8::internal::kZeroHashSeed); | 188 v8::internal::kZeroHashSeed); |
187 hash ^= ComputeIntegerHash(line_number_, v8::internal::kZeroHashSeed); | 189 hash ^= ComputeIntegerHash(line_number_, v8::internal::kZeroHashSeed); |
188 } | 190 } |
189 return hash; | 191 return hash; |
190 } | 192 } |
191 | 193 |
192 | 194 |
193 bool CodeEntry::IsSameAs(CodeEntry* entry) const { | 195 bool CodeEntry::IsSameFunctionAs(CodeEntry* entry) const { |
194 return this == entry || | 196 if (this == entry) return true; |
195 (tag() == entry->tag() && shared_id_ == entry->shared_id_ && | 197 if (script_id_ != v8::UnboundScript::kNoScriptId) { |
196 (shared_id_ != 0 || | 198 return script_id_ == entry->script_id_ && position_ == entry->position_; |
197 (name_prefix_ == entry->name_prefix_ && name_ == entry->name_ && | 199 } |
198 resource_name_ == entry->resource_name_ && | 200 return name_prefix_ == entry->name_prefix_ && name_ == entry->name_ && |
199 line_number_ == entry->line_number_))); | 201 resource_name_ == entry->resource_name_ && |
| 202 line_number_ == entry->line_number_; |
200 } | 203 } |
201 | 204 |
202 | 205 |
203 void CodeEntry::SetBuiltinId(Builtins::Name id) { | 206 void CodeEntry::SetBuiltinId(Builtins::Name id) { |
204 bit_field_ = TagField::update(bit_field_, Logger::BUILTIN_TAG); | 207 bit_field_ = TagField::update(bit_field_, Logger::BUILTIN_TAG); |
205 bit_field_ = BuiltinIdField::update(bit_field_, id); | 208 bit_field_ = BuiltinIdField::update(bit_field_, id); |
206 } | 209 } |
207 | 210 |
208 | 211 |
209 int CodeEntry::GetSourceLine(int pc_offset) const { | 212 int CodeEntry::GetSourceLine(int pc_offset) const { |
210 if (line_info_ && !line_info_->empty()) { | 213 if (line_info_ && !line_info_->empty()) { |
211 return line_info_->GetSourceLineNumber(pc_offset); | 214 return line_info_->GetSourceLineNumber(pc_offset); |
212 } | 215 } |
213 return v8::CpuProfileNode::kNoLineNumberInfo; | 216 return v8::CpuProfileNode::kNoLineNumberInfo; |
214 } | 217 } |
215 | 218 |
216 | 219 |
| 220 void CodeEntry::FillFunctionInfo(SharedFunctionInfo* shared) { |
| 221 if (!shared->script()->IsScript()) return; |
| 222 Script* script = Script::cast(shared->script()); |
| 223 set_script_id(script->id()->value()); |
| 224 set_position(shared->start_position()); |
| 225 set_bailout_reason(GetBailoutReason(shared->disable_optimization_reason())); |
| 226 } |
| 227 |
| 228 |
217 void ProfileNode::CollectDeoptInfo(CodeEntry* entry) { | 229 void ProfileNode::CollectDeoptInfo(CodeEntry* entry) { |
218 deopt_infos_.Add(DeoptInfo(entry->deopt_reason(), entry->deopt_location())); | 230 deopt_infos_.Add(DeoptInfo(entry->deopt_reason(), entry->deopt_location())); |
219 entry->clear_deopt_info(); | 231 entry->clear_deopt_info(); |
220 } | 232 } |
221 | 233 |
222 | 234 |
223 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { | 235 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { |
224 HashMap::Entry* map_entry = | 236 HashMap::Entry* map_entry = |
225 children_.Lookup(entry, CodeEntryHash(entry), false); | 237 children_.Lookup(entry, CodeEntryHash(entry), false); |
226 return map_entry != NULL ? | 238 return map_entry != NULL ? |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 delete node; | 321 delete node; |
310 } | 322 } |
311 | 323 |
312 void AfterChildTraversed(ProfileNode*, ProfileNode*) { } | 324 void AfterChildTraversed(ProfileNode*, ProfileNode*) { } |
313 }; | 325 }; |
314 | 326 |
315 | 327 |
316 ProfileTree::ProfileTree() | 328 ProfileTree::ProfileTree() |
317 : root_entry_(Logger::FUNCTION_TAG, "(root)"), | 329 : root_entry_(Logger::FUNCTION_TAG, "(root)"), |
318 next_node_id_(1), | 330 next_node_id_(1), |
319 root_(new ProfileNode(this, &root_entry_)) { | 331 root_(new ProfileNode(this, &root_entry_)), |
320 } | 332 next_function_id_(1), |
| 333 function_ids_(ProfileNode::CodeEntriesMatch) {} |
321 | 334 |
322 | 335 |
323 ProfileTree::~ProfileTree() { | 336 ProfileTree::~ProfileTree() { |
324 DeleteNodesCallback cb; | 337 DeleteNodesCallback cb; |
325 TraverseDepthFirst(&cb); | 338 TraverseDepthFirst(&cb); |
326 } | 339 } |
327 | 340 |
328 | 341 |
| 342 unsigned ProfileTree::GetFunctionId(const ProfileNode* node) { |
| 343 CodeEntry* code_entry = node->entry(); |
| 344 HashMap::Entry* entry = |
| 345 function_ids_.Lookup(code_entry, code_entry->GetHash(), true); |
| 346 if (!entry->value) { |
| 347 entry->value = reinterpret_cast<void*>(next_function_id_++); |
| 348 } |
| 349 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(entry->value)); |
| 350 } |
| 351 |
| 352 |
329 ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path, | 353 ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path, |
330 int src_line) { | 354 int src_line) { |
331 ProfileNode* node = root_; | 355 ProfileNode* node = root_; |
332 CodeEntry* last_entry = NULL; | 356 CodeEntry* last_entry = NULL; |
333 for (CodeEntry** entry = path.start() + path.length() - 1; | 357 for (CodeEntry** entry = path.start() + path.length() - 1; |
334 entry != path.start() - 1; | 358 entry != path.start() - 1; |
335 --entry) { | 359 --entry) { |
336 if (*entry != NULL) { | 360 if (*entry != NULL) { |
337 node = node->FindOrAddChild(*entry); | 361 node = node->FindOrAddChild(*entry); |
338 last_entry = *entry; | 362 last_entry = *entry; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 end_time_ = base::TimeTicks::HighResolutionNow(); | 444 end_time_ = base::TimeTicks::HighResolutionNow(); |
421 } | 445 } |
422 | 446 |
423 | 447 |
424 void CpuProfile::Print() { | 448 void CpuProfile::Print() { |
425 base::OS::Print("[Top down]:\n"); | 449 base::OS::Print("[Top down]:\n"); |
426 top_down_.Print(); | 450 top_down_.Print(); |
427 } | 451 } |
428 | 452 |
429 | 453 |
430 CodeEntry* const CodeMap::kSharedFunctionCodeEntry = NULL; | |
431 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL; | 454 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL; |
432 | 455 |
433 | 456 |
434 void CodeMap::AddCode(Address addr, CodeEntry* entry, unsigned size) { | 457 void CodeMap::AddCode(Address addr, CodeEntry* entry, unsigned size) { |
435 DeleteAllCoveredCode(addr, addr + size); | 458 DeleteAllCoveredCode(addr, addr + size); |
436 CodeTree::Locator locator; | 459 CodeTree::Locator locator; |
437 tree_.Insert(addr, &locator); | 460 tree_.Insert(addr, &locator); |
438 locator.set_value(CodeEntryInfo(entry, size)); | 461 locator.set_value(CodeEntryInfo(entry, size)); |
439 } | 462 } |
440 | 463 |
(...skipping 21 matching lines...) Expand all Loading... |
462 if (start) { | 485 if (start) { |
463 *start = locator.key(); | 486 *start = locator.key(); |
464 } | 487 } |
465 return entry.entry; | 488 return entry.entry; |
466 } | 489 } |
467 } | 490 } |
468 return NULL; | 491 return NULL; |
469 } | 492 } |
470 | 493 |
471 | 494 |
472 int CodeMap::GetSharedId(Address addr) { | |
473 CodeTree::Locator locator; | |
474 // For shared function entries, 'size' field is used to store their IDs. | |
475 if (tree_.Find(addr, &locator)) { | |
476 const CodeEntryInfo& entry = locator.value(); | |
477 DCHECK(entry.entry == kSharedFunctionCodeEntry); | |
478 return entry.size; | |
479 } else { | |
480 tree_.Insert(addr, &locator); | |
481 int id = next_shared_id_++; | |
482 locator.set_value(CodeEntryInfo(kSharedFunctionCodeEntry, id)); | |
483 return id; | |
484 } | |
485 } | |
486 | |
487 | |
488 void CodeMap::MoveCode(Address from, Address to) { | 495 void CodeMap::MoveCode(Address from, Address to) { |
489 if (from == to) return; | 496 if (from == to) return; |
490 CodeTree::Locator locator; | 497 CodeTree::Locator locator; |
491 if (!tree_.Find(from, &locator)) return; | 498 if (!tree_.Find(from, &locator)) return; |
492 CodeEntryInfo entry = locator.value(); | 499 CodeEntryInfo entry = locator.value(); |
493 tree_.Remove(from); | 500 tree_.Remove(from); |
494 AddCode(to, entry.entry, entry.size); | 501 AddCode(to, entry.entry, entry.size); |
495 } | 502 } |
496 | 503 |
497 | 504 |
498 void CodeMap::CodeTreePrinter::Call( | 505 void CodeMap::CodeTreePrinter::Call( |
499 const Address& key, const CodeMap::CodeEntryInfo& value) { | 506 const Address& key, const CodeMap::CodeEntryInfo& value) { |
500 // For shared function entries, 'size' field is used to store their IDs. | 507 base::OS::Print("%p %5d %s\n", key, value.size, value.entry->name()); |
501 if (value.entry == kSharedFunctionCodeEntry) { | |
502 base::OS::Print("%p SharedFunctionInfo %d\n", key, value.size); | |
503 } else { | |
504 base::OS::Print("%p %5d %s\n", key, value.size, value.entry->name()); | |
505 } | |
506 } | 508 } |
507 | 509 |
508 | 510 |
509 void CodeMap::Print() { | 511 void CodeMap::Print() { |
510 CodeTreePrinter printer; | 512 CodeTreePrinter printer; |
511 tree_.ForEach(&printer); | 513 tree_.ForEach(&printer); |
512 } | 514 } |
513 | 515 |
514 | 516 |
515 CpuProfilesCollection::CpuProfilesCollection(Heap* heap) | 517 CpuProfilesCollection::CpuProfilesCollection(Heap* heap) |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
762 case OTHER: | 764 case OTHER: |
763 case EXTERNAL: | 765 case EXTERNAL: |
764 return program_entry_; | 766 return program_entry_; |
765 case IDLE: | 767 case IDLE: |
766 return idle_entry_; | 768 return idle_entry_; |
767 default: return NULL; | 769 default: return NULL; |
768 } | 770 } |
769 } | 771 } |
770 | 772 |
771 } } // namespace v8::internal | 773 } } // namespace v8::internal |
OLD | NEW |