OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 13 matching lines...) Expand all Loading... |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #ifndef V8_PROFILE_GENERATOR_H_ | 28 #ifndef V8_PROFILE_GENERATOR_H_ |
29 #define V8_PROFILE_GENERATOR_H_ | 29 #define V8_PROFILE_GENERATOR_H_ |
30 | 30 |
31 #ifdef ENABLE_LOGGING_AND_PROFILING | 31 #ifdef ENABLE_LOGGING_AND_PROFILING |
32 | 32 |
33 #include "hashmap.h" | 33 #include "hashmap.h" |
| 34 #include "../include/v8-profiler.h" |
34 | 35 |
35 namespace v8 { | 36 namespace v8 { |
36 namespace internal { | 37 namespace internal { |
37 | 38 |
38 class TokenEnumerator { | 39 class TokenEnumerator { |
39 public: | 40 public: |
40 TokenEnumerator(); | 41 TokenEnumerator(); |
41 ~TokenEnumerator(); | 42 ~TokenEnumerator(); |
42 int GetTokenId(Object* token); | 43 int GetTokenId(Object* token); |
43 | 44 |
44 static const int kNoSecurityToken = -1; | 45 static const int kNoSecurityToken = -1; |
45 static const int kInheritsSecurityToken = -2; | 46 static const int kInheritsSecurityToken = -2; |
46 | 47 |
47 private: | 48 private: |
48 static void TokenRemovedCallback(v8::Persistent<v8::Value> handle, | 49 static void TokenRemovedCallback(v8::Persistent<v8::Value> handle, |
49 void* parameter); | 50 void* parameter); |
50 void TokenRemoved(Object** token_location); | 51 void TokenRemoved(Object** token_location); |
51 | 52 |
52 List<Object**> token_locations_; | 53 List<Object**> token_locations_; |
53 List<bool> token_removed_; | 54 List<bool> token_removed_; |
54 | 55 |
55 friend class TokenEnumeratorTester; | 56 friend class TokenEnumeratorTester; |
| 57 |
| 58 DISALLOW_COPY_AND_ASSIGN(TokenEnumerator); |
56 }; | 59 }; |
57 | 60 |
58 | 61 |
59 // Provides a storage of strings allocated in C++ heap, to hold them | 62 // Provides a storage of strings allocated in C++ heap, to hold them |
60 // forever, even if they disappear from JS heap or external storage. | 63 // forever, even if they disappear from JS heap or external storage. |
61 class StringsStorage { | 64 class StringsStorage { |
62 public: | 65 public: |
63 StringsStorage(); | 66 StringsStorage(); |
64 ~StringsStorage(); | 67 ~StringsStorage(); |
65 | 68 |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 // order should provide enough precision while keeping away from a | 353 // order should provide enough precision while keeping away from a |
351 // potential overflow. | 354 // potential overflow. |
352 static const int kResultScale = 100000; | 355 static const int kResultScale = 100000; |
353 | 356 |
354 AtomicWord result_; | 357 AtomicWord result_; |
355 // All other fields are accessed only from the sampler thread. | 358 // All other fields are accessed only from the sampler thread. |
356 double ticks_per_ms_; | 359 double ticks_per_ms_; |
357 unsigned measurements_count_; | 360 unsigned measurements_count_; |
358 unsigned wall_time_query_countdown_; | 361 unsigned wall_time_query_countdown_; |
359 double last_wall_time_; | 362 double last_wall_time_; |
| 363 |
| 364 DISALLOW_COPY_AND_ASSIGN(SampleRateCalculator); |
360 }; | 365 }; |
361 | 366 |
362 | 367 |
363 class ProfileGenerator { | 368 class ProfileGenerator { |
364 public: | 369 public: |
365 explicit ProfileGenerator(CpuProfilesCollection* profiles); | 370 explicit ProfileGenerator(CpuProfilesCollection* profiles); |
366 | 371 |
367 INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, | 372 INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, |
368 String* name, | 373 String* name, |
369 String* resource_name, | 374 String* resource_name, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 | 414 |
410 CpuProfilesCollection* profiles_; | 415 CpuProfilesCollection* profiles_; |
411 CodeMap code_map_; | 416 CodeMap code_map_; |
412 CodeEntry* program_entry_; | 417 CodeEntry* program_entry_; |
413 CodeEntry* gc_entry_; | 418 CodeEntry* gc_entry_; |
414 SampleRateCalculator sample_rate_calc_; | 419 SampleRateCalculator sample_rate_calc_; |
415 | 420 |
416 DISALLOW_COPY_AND_ASSIGN(ProfileGenerator); | 421 DISALLOW_COPY_AND_ASSIGN(ProfileGenerator); |
417 }; | 422 }; |
418 | 423 |
| 424 |
| 425 class HeapSnapshot; |
| 426 class HeapEntry; |
| 427 |
| 428 |
| 429 class HeapGraphEdge { |
| 430 public: |
| 431 enum Type { |
| 432 CONTEXT_VARIABLE, |
| 433 ELEMENT, |
| 434 PROPERTY |
| 435 }; |
| 436 |
| 437 HeapGraphEdge(Type type, const char* name, HeapEntry* from, HeapEntry* to); |
| 438 HeapGraphEdge(int index, HeapEntry* from, HeapEntry* to); |
| 439 |
| 440 Type type() const { return type_; } |
| 441 int index() const { |
| 442 ASSERT(type_ == ELEMENT); |
| 443 return index_; |
| 444 } |
| 445 const char* name() const { |
| 446 ASSERT(type_ == CONTEXT_VARIABLE || type_ == PROPERTY); |
| 447 return name_; |
| 448 } |
| 449 HeapEntry* from() const { return from_; } |
| 450 HeapEntry* to() const { return to_; } |
| 451 |
| 452 private: |
| 453 Type type_; |
| 454 union { |
| 455 int index_; |
| 456 const char* name_; |
| 457 }; |
| 458 HeapEntry* from_; |
| 459 HeapEntry* to_; |
| 460 |
| 461 DISALLOW_COPY_AND_ASSIGN(HeapGraphEdge); |
| 462 }; |
| 463 |
| 464 |
| 465 class HeapGraphPath; |
| 466 class CachedHeapGraphPath; |
| 467 |
| 468 class HeapEntry { |
| 469 public: |
| 470 enum Type { |
| 471 INTERNAL, |
| 472 ARRAY, |
| 473 STRING, |
| 474 JS_OBJECT, |
| 475 CODE, |
| 476 CLOSURE |
| 477 }; |
| 478 |
| 479 explicit HeapEntry(HeapSnapshot* snapshot) |
| 480 : snapshot_(snapshot), |
| 481 visited_(false), |
| 482 type_(INTERNAL), |
| 483 name_(""), |
| 484 next_auto_index_(0), |
| 485 self_size_(0), |
| 486 security_token_id_(TokenEnumerator::kNoSecurityToken), |
| 487 children_(1), |
| 488 retainers_(0), |
| 489 retaining_paths_(0), |
| 490 total_size_(kUnknownSize), |
| 491 non_shared_total_size_(kUnknownSize), |
| 492 painted_(kUnpainted) { } |
| 493 HeapEntry(HeapSnapshot* snapshot, |
| 494 Type type, |
| 495 const char* name, |
| 496 int self_size, |
| 497 int security_token_id) |
| 498 : snapshot_(snapshot), |
| 499 visited_(false), |
| 500 type_(type), |
| 501 name_(name), |
| 502 next_auto_index_(1), |
| 503 self_size_(self_size), |
| 504 security_token_id_(security_token_id), |
| 505 children_(4), |
| 506 retainers_(4), |
| 507 retaining_paths_(4), |
| 508 total_size_(kUnknownSize), |
| 509 non_shared_total_size_(kUnknownSize), |
| 510 painted_(kUnpainted) { } |
| 511 ~HeapEntry(); |
| 512 |
| 513 bool visited() const { return visited_; } |
| 514 Type type() const { return type_; } |
| 515 const char* name() const { return name_; } |
| 516 int self_size() const { return self_size_; } |
| 517 int security_token_id() const { return security_token_id_; } |
| 518 bool painted_reachable() { return painted_ == kPaintReachable; } |
| 519 bool not_painted_reachable_from_others() { |
| 520 return painted_ != kPaintReachableFromOthers; |
| 521 } |
| 522 const List<HeapGraphEdge*>* children() const { return &children_; } |
| 523 const List<HeapGraphEdge*>* retainers() const { return &retainers_; } |
| 524 const List<HeapGraphPath*>* GetRetainingPaths(); |
| 525 |
| 526 void ClearPaint() { painted_ = kUnpainted; } |
| 527 void CutEdges(); |
| 528 void MarkAsVisited() { visited_ = true; } |
| 529 void PaintReachable() { |
| 530 ASSERT(painted_ == kUnpainted); |
| 531 painted_ = kPaintReachable; |
| 532 } |
| 533 void PaintReachableFromOthers() { painted_ = kPaintReachableFromOthers; } |
| 534 void SetClosureReference(const char* name, HeapEntry* entry); |
| 535 void SetElementReference(int index, HeapEntry* entry); |
| 536 void SetPropertyReference(const char* name, HeapEntry* entry); |
| 537 void SetAutoIndexReference(HeapEntry* entry); |
| 538 |
| 539 int TotalSize(); |
| 540 int NonSharedTotalSize(); |
| 541 |
| 542 void Print(int max_depth, int indent); |
| 543 |
| 544 private: |
| 545 int CalculateTotalSize(); |
| 546 int CalculateNonSharedTotalSize(); |
| 547 void FindRetainingPaths(HeapEntry* node, CachedHeapGraphPath* prev_path); |
| 548 void RemoveChild(HeapGraphEdge* edge); |
| 549 void RemoveRetainer(HeapGraphEdge* edge); |
| 550 |
| 551 const char* TypeAsString(); |
| 552 |
| 553 HeapSnapshot* snapshot_; |
| 554 bool visited_; |
| 555 Type type_; |
| 556 const char* name_; |
| 557 int next_auto_index_; |
| 558 int self_size_; |
| 559 int security_token_id_; |
| 560 List<HeapGraphEdge*> children_; |
| 561 List<HeapGraphEdge*> retainers_; |
| 562 List<HeapGraphPath*> retaining_paths_; |
| 563 int total_size_; |
| 564 int non_shared_total_size_; |
| 565 int painted_; |
| 566 |
| 567 static const int kUnknownSize = -1; |
| 568 static const int kUnpainted = 0; |
| 569 static const int kPaintReachable = 1; |
| 570 static const int kPaintReachableFromOthers = 2; |
| 571 |
| 572 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapEntry); |
| 573 }; |
| 574 |
| 575 |
| 576 class HeapGraphPath { |
| 577 public: |
| 578 HeapGraphPath() |
| 579 : path_(8) { } |
| 580 explicit HeapGraphPath(const List<HeapGraphEdge*>& path); |
| 581 |
| 582 void Add(HeapGraphEdge* edge) { path_.Add(edge); } |
| 583 void Set(int index, HeapGraphEdge* edge) { path_[index] = edge; } |
| 584 const List<HeapGraphEdge*>* path() const { return &path_; } |
| 585 |
| 586 void Print(); |
| 587 |
| 588 private: |
| 589 List<HeapGraphEdge*> path_; |
| 590 |
| 591 DISALLOW_COPY_AND_ASSIGN(HeapGraphPath); |
| 592 }; |
| 593 |
| 594 |
| 595 class HeapEntriesMap { |
| 596 public: |
| 597 HeapEntriesMap(); |
| 598 ~HeapEntriesMap(); |
| 599 |
| 600 void Alias(HeapObject* object, HeapEntry* entry); |
| 601 void Apply(void (HeapEntry::*Func)(void)); |
| 602 template<class Visitor> |
| 603 void Apply(Visitor* visitor); |
| 604 HeapEntry* Map(HeapObject* object); |
| 605 void Pair(HeapObject* object, HeapEntry* entry); |
| 606 |
| 607 private: |
| 608 INLINE(uint32_t Hash(HeapObject* object)) { |
| 609 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(object)); |
| 610 } |
| 611 INLINE(static bool HeapObjectsMatch(void* key1, void* key2)) { |
| 612 return key1 == key2; |
| 613 } |
| 614 INLINE(bool IsAlias(void* ptr)) { |
| 615 return reinterpret_cast<intptr_t>(ptr) & kAliasTag; |
| 616 } |
| 617 |
| 618 static const intptr_t kAliasTag = 1; |
| 619 |
| 620 HashMap entries_; |
| 621 |
| 622 DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap); |
| 623 }; |
| 624 |
| 625 |
| 626 class HeapSnapshotsCollection; |
| 627 |
| 628 // HeapSnapshot represents a single heap snapshot. It is stored in |
| 629 // HeapSnapshotsCollection, which is also a factory for |
| 630 // HeapSnapshots. All HeapSnapshots share strings copied from JS heap |
| 631 // to be able to return them even if they were collected. |
| 632 // HeapSnapshotGenerator fills in a HeapSnapshot. |
| 633 class HeapSnapshot { |
| 634 public: |
| 635 HeapSnapshot(HeapSnapshotsCollection* collection, |
| 636 const char* title, |
| 637 unsigned uid); |
| 638 void ClearPaint(); |
| 639 void CutObjectsFromForeignSecurityContexts(); |
| 640 HeapEntry* GetEntry(Object* object); |
| 641 void SetClosureReference( |
| 642 HeapEntry* parent, String* reference_name, Object* child); |
| 643 void SetElementReference(HeapEntry* parent, int index, Object* child); |
| 644 void SetPropertyReference( |
| 645 HeapEntry* parent, String* reference_name, Object* child); |
| 646 |
| 647 INLINE(const char* title() const) { return title_; } |
| 648 INLINE(unsigned uid() const) { return uid_; } |
| 649 const HeapEntry* const_root() const { return &root_; } |
| 650 HeapEntry* root() { return &root_; } |
| 651 template<class Visitor> |
| 652 void IterateEntries(Visitor* visitor) { entries_.Apply(visitor); } |
| 653 |
| 654 void Print(int max_depth); |
| 655 |
| 656 private: |
| 657 HeapEntry* AddEntry(HeapObject* object, HeapEntry::Type type) { |
| 658 return AddEntry(object, type, ""); |
| 659 } |
| 660 HeapEntry* AddEntry( |
| 661 HeapObject* object, HeapEntry::Type type, const char* name); |
| 662 void AddEntryAlias(HeapObject* object, HeapEntry* entry) { |
| 663 entries_.Alias(object, entry); |
| 664 } |
| 665 HeapEntry* FindEntry(HeapObject* object) { |
| 666 return entries_.Map(object); |
| 667 } |
| 668 int GetGlobalSecurityToken(); |
| 669 int GetObjectSecurityToken(HeapObject* obj); |
| 670 static int GetObjectSize(HeapObject* obj); |
| 671 static int CalculateNetworkSize(JSObject* obj); |
| 672 |
| 673 HeapSnapshotsCollection* collection_; |
| 674 const char* title_; |
| 675 unsigned uid_; |
| 676 HeapEntry root_; |
| 677 // HeapObject* -> HeapEntry* |
| 678 HeapEntriesMap entries_; |
| 679 |
| 680 DISALLOW_COPY_AND_ASSIGN(HeapSnapshot); |
| 681 }; |
| 682 |
| 683 |
| 684 class HeapSnapshotsCollection { |
| 685 public: |
| 686 HeapSnapshotsCollection(); |
| 687 ~HeapSnapshotsCollection(); |
| 688 |
| 689 HeapSnapshot* NewSnapshot(const char* name, unsigned uid); |
| 690 List<HeapSnapshot*>* snapshots() { return &snapshots_; } |
| 691 HeapSnapshot* GetSnapshot(unsigned uid); |
| 692 |
| 693 const char* GetName(String* name) { return names_.GetName(name); } |
| 694 |
| 695 TokenEnumerator* token_enumerator() { return token_enumerator_; } |
| 696 |
| 697 private: |
| 698 INLINE(static bool HeapSnapshotsMatch(void* key1, void* key2)) { |
| 699 return key1 == key2; |
| 700 } |
| 701 |
| 702 List<HeapSnapshot*> snapshots_; |
| 703 // uid -> HeapSnapshot* |
| 704 HashMap snapshots_uids_; |
| 705 StringsStorage names_; |
| 706 TokenEnumerator* token_enumerator_; |
| 707 |
| 708 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsCollection); |
| 709 }; |
| 710 |
| 711 |
| 712 class HeapSnapshotGenerator { |
| 713 public: |
| 714 explicit HeapSnapshotGenerator(HeapSnapshot* snapshot); |
| 715 void GenerateSnapshot(); |
| 716 |
| 717 private: |
| 718 void ExtractReferences(HeapObject* obj); |
| 719 void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry); |
| 720 void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry); |
| 721 void ExtractElementReferences(JSObject* js_obj, HeapEntry* entry); |
| 722 |
| 723 HeapSnapshot* snapshot_; |
| 724 |
| 725 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator); |
| 726 }; |
| 727 |
419 } } // namespace v8::internal | 728 } } // namespace v8::internal |
420 | 729 |
421 #endif // ENABLE_LOGGING_AND_PROFILING | 730 #endif // ENABLE_LOGGING_AND_PROFILING |
422 | 731 |
423 #endif // V8_PROFILE_GENERATOR_H_ | 732 #endif // V8_PROFILE_GENERATOR_H_ |
OLD | NEW |