OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
54 List<bool> token_removed_; | 54 List<bool> token_removed_; |
55 | 55 |
56 friend class TokenEnumeratorTester; | 56 friend class TokenEnumeratorTester; |
57 | 57 |
58 DISALLOW_COPY_AND_ASSIGN(TokenEnumerator); | 58 DISALLOW_COPY_AND_ASSIGN(TokenEnumerator); |
59 }; | 59 }; |
60 | 60 |
61 | 61 |
62 // 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 |
63 // forever, even if they disappear from JS heap or external storage. | 63 // forever, even if they disappear from JS heap or external storage. |
64 class StringsStorage { | 64 class StringsStorage { |
yurys
2013/02/21 09:07:44
StringStorage is used by both cpu profile and heap
Yang
2013/02/21 11:35:48
Or move it to utils.h
| |
65 public: | 65 public: |
66 StringsStorage(); | 66 StringsStorage(); |
67 ~StringsStorage(); | 67 ~StringsStorage(); |
68 | 68 |
69 const char* GetCopy(const char* src); | 69 const char* GetCopy(const char* src); |
70 const char* GetFormatted(const char* format, ...); | 70 const char* GetFormatted(const char* format, ...); |
71 const char* GetVFormatted(const char* format, va_list args); | 71 const char* GetVFormatted(const char* format, va_list args); |
72 const char* GetName(String* name); | 72 const char* GetName(String* name); |
73 const char* GetName(int index); | 73 const char* GetName(int index); |
74 inline const char* GetFunctionName(String* name); | 74 inline const char* GetFunctionName(String* name); |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
440 CpuProfilesCollection* profiles_; | 440 CpuProfilesCollection* profiles_; |
441 CodeMap code_map_; | 441 CodeMap code_map_; |
442 CodeEntry* program_entry_; | 442 CodeEntry* program_entry_; |
443 CodeEntry* gc_entry_; | 443 CodeEntry* gc_entry_; |
444 SampleRateCalculator sample_rate_calc_; | 444 SampleRateCalculator sample_rate_calc_; |
445 | 445 |
446 DISALLOW_COPY_AND_ASSIGN(ProfileGenerator); | 446 DISALLOW_COPY_AND_ASSIGN(ProfileGenerator); |
447 }; | 447 }; |
448 | 448 |
449 | 449 |
450 class HeapEntry; | |
451 class HeapSnapshot; | |
452 | |
453 class HeapGraphEdge BASE_EMBEDDED { | |
454 public: | |
455 enum Type { | |
456 kContextVariable = v8::HeapGraphEdge::kContextVariable, | |
457 kElement = v8::HeapGraphEdge::kElement, | |
458 kProperty = v8::HeapGraphEdge::kProperty, | |
459 kInternal = v8::HeapGraphEdge::kInternal, | |
460 kHidden = v8::HeapGraphEdge::kHidden, | |
461 kShortcut = v8::HeapGraphEdge::kShortcut, | |
462 kWeak = v8::HeapGraphEdge::kWeak | |
463 }; | |
464 | |
465 HeapGraphEdge() { } | |
466 HeapGraphEdge(Type type, const char* name, int from, int to); | |
467 HeapGraphEdge(Type type, int index, int from, int to); | |
468 void ReplaceToIndexWithEntry(HeapSnapshot* snapshot); | |
469 | |
470 Type type() const { return static_cast<Type>(type_); } | |
471 int index() const { | |
472 ASSERT(type_ == kElement || type_ == kHidden || type_ == kWeak); | |
473 return index_; | |
474 } | |
475 const char* name() const { | |
476 ASSERT(type_ == kContextVariable | |
477 || type_ == kProperty | |
478 || type_ == kInternal | |
479 || type_ == kShortcut); | |
480 return name_; | |
481 } | |
482 INLINE(HeapEntry* from() const); | |
483 HeapEntry* to() const { return to_entry_; } | |
484 | |
485 private: | |
486 INLINE(HeapSnapshot* snapshot() const); | |
487 | |
488 unsigned type_ : 3; | |
489 int from_index_ : 29; | |
490 union { | |
491 // During entries population |to_index_| is used for storing the index, | |
492 // afterwards it is replaced with a pointer to the entry. | |
493 int to_index_; | |
494 HeapEntry* to_entry_; | |
495 }; | |
496 union { | |
497 int index_; | |
498 const char* name_; | |
499 }; | |
500 }; | |
501 | |
502 | |
503 // HeapEntry instances represent an entity from the heap (or a special | |
504 // virtual node, e.g. root). | |
505 class HeapEntry BASE_EMBEDDED { | |
506 public: | |
507 enum Type { | |
508 kHidden = v8::HeapGraphNode::kHidden, | |
509 kArray = v8::HeapGraphNode::kArray, | |
510 kString = v8::HeapGraphNode::kString, | |
511 kObject = v8::HeapGraphNode::kObject, | |
512 kCode = v8::HeapGraphNode::kCode, | |
513 kClosure = v8::HeapGraphNode::kClosure, | |
514 kRegExp = v8::HeapGraphNode::kRegExp, | |
515 kHeapNumber = v8::HeapGraphNode::kHeapNumber, | |
516 kNative = v8::HeapGraphNode::kNative, | |
517 kSynthetic = v8::HeapGraphNode::kSynthetic | |
518 }; | |
519 static const int kNoEntry; | |
520 | |
521 HeapEntry() { } | |
522 HeapEntry(HeapSnapshot* snapshot, | |
523 Type type, | |
524 const char* name, | |
525 SnapshotObjectId id, | |
526 int self_size); | |
527 | |
528 HeapSnapshot* snapshot() { return snapshot_; } | |
529 Type type() { return static_cast<Type>(type_); } | |
530 const char* name() { return name_; } | |
531 void set_name(const char* name) { name_ = name; } | |
532 inline SnapshotObjectId id() { return id_; } | |
533 int self_size() { return self_size_; } | |
534 INLINE(int index() const); | |
535 int children_count() const { return children_count_; } | |
536 INLINE(int set_children_index(int index)); | |
537 void add_child(HeapGraphEdge* edge) { | |
538 children_arr()[children_count_++] = edge; | |
539 } | |
540 Vector<HeapGraphEdge*> children() { | |
541 return Vector<HeapGraphEdge*>(children_arr(), children_count_); } | |
542 | |
543 void SetIndexedReference( | |
544 HeapGraphEdge::Type type, int index, HeapEntry* entry); | |
545 void SetNamedReference( | |
546 HeapGraphEdge::Type type, const char* name, HeapEntry* entry); | |
547 | |
548 void Print( | |
549 const char* prefix, const char* edge_name, int max_depth, int indent); | |
550 | |
551 Handle<HeapObject> GetHeapObject(); | |
552 | |
553 private: | |
554 INLINE(HeapGraphEdge** children_arr()); | |
555 const char* TypeAsString(); | |
556 | |
557 unsigned type_: 4; | |
558 int children_count_: 28; | |
559 int children_index_; | |
560 int self_size_; | |
561 SnapshotObjectId id_; | |
562 HeapSnapshot* snapshot_; | |
563 const char* name_; | |
564 }; | |
565 | |
566 | |
567 class HeapSnapshotsCollection; | |
568 | |
569 // HeapSnapshot represents a single heap snapshot. It is stored in | |
570 // HeapSnapshotsCollection, which is also a factory for | |
571 // HeapSnapshots. All HeapSnapshots share strings copied from JS heap | |
572 // to be able to return them even if they were collected. | |
573 // HeapSnapshotGenerator fills in a HeapSnapshot. | |
574 class HeapSnapshot { | |
575 public: | |
576 enum Type { | |
577 kFull = v8::HeapSnapshot::kFull | |
578 }; | |
579 | |
580 HeapSnapshot(HeapSnapshotsCollection* collection, | |
581 Type type, | |
582 const char* title, | |
583 unsigned uid); | |
584 void Delete(); | |
585 | |
586 HeapSnapshotsCollection* collection() { return collection_; } | |
587 Type type() { return type_; } | |
588 const char* title() { return title_; } | |
589 unsigned uid() { return uid_; } | |
590 size_t RawSnapshotSize() const; | |
591 HeapEntry* root() { return &entries_[root_index_]; } | |
592 HeapEntry* gc_roots() { return &entries_[gc_roots_index_]; } | |
593 HeapEntry* natives_root() { return &entries_[natives_root_index_]; } | |
594 HeapEntry* gc_subroot(int index) { | |
595 return &entries_[gc_subroot_indexes_[index]]; | |
596 } | |
597 List<HeapEntry>& entries() { return entries_; } | |
598 List<HeapGraphEdge>& edges() { return edges_; } | |
599 List<HeapGraphEdge*>& children() { return children_; } | |
600 void RememberLastJSObjectId(); | |
601 SnapshotObjectId max_snapshot_js_object_id() const { | |
602 return max_snapshot_js_object_id_; | |
603 } | |
604 | |
605 HeapEntry* AddEntry(HeapEntry::Type type, | |
606 const char* name, | |
607 SnapshotObjectId id, | |
608 int size); | |
609 HeapEntry* AddRootEntry(); | |
610 HeapEntry* AddGcRootsEntry(); | |
611 HeapEntry* AddGcSubrootEntry(int tag); | |
612 HeapEntry* AddNativesRootEntry(); | |
613 HeapEntry* GetEntryById(SnapshotObjectId id); | |
614 List<HeapEntry*>* GetSortedEntriesList(); | |
615 void FillChildren(); | |
616 | |
617 void Print(int max_depth); | |
618 void PrintEntriesSize(); | |
619 | |
620 private: | |
621 HeapSnapshotsCollection* collection_; | |
622 Type type_; | |
623 const char* title_; | |
624 unsigned uid_; | |
625 int root_index_; | |
626 int gc_roots_index_; | |
627 int natives_root_index_; | |
628 int gc_subroot_indexes_[VisitorSynchronization::kNumberOfSyncTags]; | |
629 List<HeapEntry> entries_; | |
630 List<HeapGraphEdge> edges_; | |
631 List<HeapGraphEdge*> children_; | |
632 List<HeapEntry*> sorted_entries_; | |
633 SnapshotObjectId max_snapshot_js_object_id_; | |
634 | |
635 friend class HeapSnapshotTester; | |
636 | |
637 DISALLOW_COPY_AND_ASSIGN(HeapSnapshot); | |
638 }; | |
639 | |
640 | |
641 class HeapObjectsMap { | |
642 public: | |
643 explicit HeapObjectsMap(Heap* heap); | |
644 | |
645 Heap* heap() const { return heap_; } | |
646 | |
647 void SnapshotGenerationFinished(); | |
648 SnapshotObjectId FindEntry(Address addr); | |
649 SnapshotObjectId FindOrAddEntry(Address addr, unsigned int size); | |
650 void MoveObject(Address from, Address to); | |
651 SnapshotObjectId last_assigned_id() const { | |
652 return next_id_ - kObjectIdStep; | |
653 } | |
654 | |
655 void StopHeapObjectsTracking(); | |
656 SnapshotObjectId PushHeapObjectsStats(OutputStream* stream); | |
657 size_t GetUsedMemorySize() const; | |
658 | |
659 static SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info); | |
660 static inline SnapshotObjectId GetNthGcSubrootId(int delta); | |
661 | |
662 static const int kObjectIdStep = 2; | |
663 static const SnapshotObjectId kInternalRootObjectId; | |
664 static const SnapshotObjectId kGcRootsObjectId; | |
665 static const SnapshotObjectId kNativesRootObjectId; | |
666 static const SnapshotObjectId kGcRootsFirstSubrootId; | |
667 static const SnapshotObjectId kFirstAvailableObjectId; | |
668 | |
669 private: | |
670 struct EntryInfo { | |
671 EntryInfo(SnapshotObjectId id, Address addr, unsigned int size) | |
672 : id(id), addr(addr), size(size), accessed(true) { } | |
673 EntryInfo(SnapshotObjectId id, Address addr, unsigned int size, bool accessed) | |
674 : id(id), addr(addr), size(size), accessed(accessed) { } | |
675 SnapshotObjectId id; | |
676 Address addr; | |
677 unsigned int size; | |
678 bool accessed; | |
679 }; | |
680 struct TimeInterval { | |
681 explicit TimeInterval(SnapshotObjectId id) : id(id), size(0), count(0) { } | |
682 SnapshotObjectId id; | |
683 uint32_t size; | |
684 uint32_t count; | |
685 }; | |
686 | |
687 void UpdateHeapObjectsMap(); | |
688 void RemoveDeadEntries(); | |
689 | |
690 static bool AddressesMatch(void* key1, void* key2) { | |
691 return key1 == key2; | |
692 } | |
693 | |
694 static uint32_t AddressHash(Address addr) { | |
695 return ComputeIntegerHash( | |
696 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr)), | |
697 v8::internal::kZeroHashSeed); | |
698 } | |
699 | |
700 SnapshotObjectId next_id_; | |
701 HashMap entries_map_; | |
702 List<EntryInfo> entries_; | |
703 List<TimeInterval> time_intervals_; | |
704 Heap* heap_; | |
705 | |
706 DISALLOW_COPY_AND_ASSIGN(HeapObjectsMap); | |
707 }; | |
708 | |
709 | |
710 class HeapSnapshotsCollection { | |
711 public: | |
712 explicit HeapSnapshotsCollection(Heap* heap); | |
713 ~HeapSnapshotsCollection(); | |
714 | |
715 Heap* heap() const { return ids_.heap(); } | |
716 | |
717 bool is_tracking_objects() { return is_tracking_objects_; } | |
718 SnapshotObjectId PushHeapObjectsStats(OutputStream* stream) { | |
719 return ids_.PushHeapObjectsStats(stream); | |
720 } | |
721 void StartHeapObjectsTracking() { is_tracking_objects_ = true; } | |
722 void StopHeapObjectsTracking() { ids_.StopHeapObjectsTracking(); } | |
723 | |
724 HeapSnapshot* NewSnapshot( | |
725 HeapSnapshot::Type type, const char* name, unsigned uid); | |
726 void SnapshotGenerationFinished(HeapSnapshot* snapshot); | |
727 List<HeapSnapshot*>* snapshots() { return &snapshots_; } | |
728 HeapSnapshot* GetSnapshot(unsigned uid); | |
729 void RemoveSnapshot(HeapSnapshot* snapshot); | |
730 | |
731 StringsStorage* names() { return &names_; } | |
732 TokenEnumerator* token_enumerator() { return token_enumerator_; } | |
733 | |
734 SnapshotObjectId FindObjectId(Address object_addr) { | |
735 return ids_.FindEntry(object_addr); | |
736 } | |
737 SnapshotObjectId GetObjectId(Address object_addr, int object_size) { | |
738 return ids_.FindOrAddEntry(object_addr, object_size); | |
739 } | |
740 Handle<HeapObject> FindHeapObjectById(SnapshotObjectId id); | |
741 void ObjectMoveEvent(Address from, Address to) { ids_.MoveObject(from, to); } | |
742 SnapshotObjectId last_assigned_id() const { | |
743 return ids_.last_assigned_id(); | |
744 } | |
745 size_t GetUsedMemorySize() const; | |
746 | |
747 private: | |
748 INLINE(static bool HeapSnapshotsMatch(void* key1, void* key2)) { | |
749 return key1 == key2; | |
750 } | |
751 | |
752 bool is_tracking_objects_; // Whether tracking object moves is needed. | |
753 List<HeapSnapshot*> snapshots_; | |
754 // Mapping from snapshots' uids to HeapSnapshot* pointers. | |
755 HashMap snapshots_uids_; | |
756 StringsStorage names_; | |
757 TokenEnumerator* token_enumerator_; | |
758 // Mapping from HeapObject addresses to objects' uids. | |
759 HeapObjectsMap ids_; | |
760 | |
761 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsCollection); | |
762 }; | |
763 | |
764 | |
765 // A typedef for referencing anything that can be snapshotted living | |
766 // in any kind of heap memory. | |
767 typedef void* HeapThing; | |
768 | |
769 | |
770 // An interface that creates HeapEntries by HeapThings. | |
771 class HeapEntriesAllocator { | |
772 public: | |
773 virtual ~HeapEntriesAllocator() { } | |
774 virtual HeapEntry* AllocateEntry(HeapThing ptr) = 0; | |
775 }; | |
776 | |
777 | |
778 // The HeapEntriesMap instance is used to track a mapping between | |
779 // real heap objects and their representations in heap snapshots. | |
780 class HeapEntriesMap { | |
781 public: | |
782 HeapEntriesMap(); | |
783 | |
784 int Map(HeapThing thing); | |
785 void Pair(HeapThing thing, int entry); | |
786 | |
787 private: | |
788 static uint32_t Hash(HeapThing thing) { | |
789 return ComputeIntegerHash( | |
790 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)), | |
791 v8::internal::kZeroHashSeed); | |
792 } | |
793 static bool HeapThingsMatch(HeapThing key1, HeapThing key2) { | |
794 return key1 == key2; | |
795 } | |
796 | |
797 HashMap entries_; | |
798 | |
799 friend class HeapObjectsSet; | |
800 | |
801 DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap); | |
802 }; | |
803 | |
804 | |
805 class HeapObjectsSet { | |
806 public: | |
807 HeapObjectsSet(); | |
808 void Clear(); | |
809 bool Contains(Object* object); | |
810 void Insert(Object* obj); | |
811 const char* GetTag(Object* obj); | |
812 void SetTag(Object* obj, const char* tag); | |
813 bool is_empty() const { return entries_.occupancy() == 0; } | |
814 | |
815 private: | |
816 HashMap entries_; | |
817 | |
818 DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet); | |
819 }; | |
820 | |
821 | |
822 // An interface used to populate a snapshot with nodes and edges. | |
823 class SnapshotFillerInterface { | |
824 public: | |
825 virtual ~SnapshotFillerInterface() { } | |
826 virtual HeapEntry* AddEntry(HeapThing ptr, | |
827 HeapEntriesAllocator* allocator) = 0; | |
828 virtual HeapEntry* FindEntry(HeapThing ptr) = 0; | |
829 virtual HeapEntry* FindOrAddEntry(HeapThing ptr, | |
830 HeapEntriesAllocator* allocator) = 0; | |
831 virtual void SetIndexedReference(HeapGraphEdge::Type type, | |
832 int parent_entry, | |
833 int index, | |
834 HeapEntry* child_entry) = 0; | |
835 virtual void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, | |
836 int parent_entry, | |
837 HeapEntry* child_entry) = 0; | |
838 virtual void SetNamedReference(HeapGraphEdge::Type type, | |
839 int parent_entry, | |
840 const char* reference_name, | |
841 HeapEntry* child_entry) = 0; | |
842 virtual void SetNamedAutoIndexReference(HeapGraphEdge::Type type, | |
843 int parent_entry, | |
844 HeapEntry* child_entry) = 0; | |
845 }; | |
846 | |
847 | |
848 class SnapshottingProgressReportingInterface { | |
849 public: | |
850 virtual ~SnapshottingProgressReportingInterface() { } | |
851 virtual void ProgressStep() = 0; | |
852 virtual bool ProgressReport(bool force) = 0; | |
853 }; | |
854 | |
855 | |
856 // An implementation of V8 heap graph extractor. | |
857 class V8HeapExplorer : public HeapEntriesAllocator { | |
858 public: | |
859 V8HeapExplorer(HeapSnapshot* snapshot, | |
860 SnapshottingProgressReportingInterface* progress, | |
861 v8::HeapProfiler::ObjectNameResolver* resolver); | |
862 virtual ~V8HeapExplorer(); | |
863 virtual HeapEntry* AllocateEntry(HeapThing ptr); | |
864 void AddRootEntries(SnapshotFillerInterface* filler); | |
865 int EstimateObjectsCount(HeapIterator* iterator); | |
866 bool IterateAndExtractReferences(SnapshotFillerInterface* filler); | |
867 void TagGlobalObjects(); | |
868 | |
869 static String* GetConstructorName(JSObject* object); | |
870 | |
871 static HeapObject* const kInternalRootObject; | |
872 | |
873 private: | |
874 HeapEntry* AddEntry(HeapObject* object); | |
875 HeapEntry* AddEntry(HeapObject* object, | |
876 HeapEntry::Type type, | |
877 const char* name); | |
878 const char* GetSystemEntryName(HeapObject* object); | |
879 | |
880 void ExtractReferences(HeapObject* obj); | |
881 void ExtractJSGlobalProxyReferences(JSGlobalProxy* proxy); | |
882 void ExtractJSObjectReferences(int entry, JSObject* js_obj); | |
883 void ExtractStringReferences(int entry, String* obj); | |
884 void ExtractContextReferences(int entry, Context* context); | |
885 void ExtractMapReferences(int entry, Map* map); | |
886 void ExtractSharedFunctionInfoReferences(int entry, | |
887 SharedFunctionInfo* shared); | |
888 void ExtractScriptReferences(int entry, Script* script); | |
889 void ExtractCodeCacheReferences(int entry, CodeCache* code_cache); | |
890 void ExtractCodeReferences(int entry, Code* code); | |
891 void ExtractJSGlobalPropertyCellReferences(int entry, | |
892 JSGlobalPropertyCell* cell); | |
893 void ExtractClosureReferences(JSObject* js_obj, int entry); | |
894 void ExtractPropertyReferences(JSObject* js_obj, int entry); | |
895 void ExtractElementReferences(JSObject* js_obj, int entry); | |
896 void ExtractInternalReferences(JSObject* js_obj, int entry); | |
897 bool IsEssentialObject(Object* object); | |
898 void SetClosureReference(HeapObject* parent_obj, | |
899 int parent, | |
900 String* reference_name, | |
901 Object* child); | |
902 void SetNativeBindReference(HeapObject* parent_obj, | |
903 int parent, | |
904 const char* reference_name, | |
905 Object* child); | |
906 void SetElementReference(HeapObject* parent_obj, | |
907 int parent, | |
908 int index, | |
909 Object* child); | |
910 void SetInternalReference(HeapObject* parent_obj, | |
911 int parent, | |
912 const char* reference_name, | |
913 Object* child, | |
914 int field_offset = -1); | |
915 void SetInternalReference(HeapObject* parent_obj, | |
916 int parent, | |
917 int index, | |
918 Object* child, | |
919 int field_offset = -1); | |
920 void SetHiddenReference(HeapObject* parent_obj, | |
921 int parent, | |
922 int index, | |
923 Object* child); | |
924 void SetWeakReference(HeapObject* parent_obj, | |
925 int parent, | |
926 int index, | |
927 Object* child_obj, | |
928 int field_offset); | |
929 void SetPropertyReference(HeapObject* parent_obj, | |
930 int parent, | |
931 String* reference_name, | |
932 Object* child, | |
933 const char* name_format_string = NULL, | |
934 int field_offset = -1); | |
935 void SetUserGlobalReference(Object* user_global); | |
936 void SetRootGcRootsReference(); | |
937 void SetGcRootsReference(VisitorSynchronization::SyncTag tag); | |
938 void SetGcSubrootReference( | |
939 VisitorSynchronization::SyncTag tag, bool is_weak, Object* child); | |
940 const char* GetStrongGcSubrootName(Object* object); | |
941 void TagObject(Object* obj, const char* tag); | |
942 | |
943 HeapEntry* GetEntry(Object* obj); | |
944 | |
945 static inline HeapObject* GetNthGcSubrootObject(int delta); | |
946 static inline int GetGcSubrootOrder(HeapObject* subroot); | |
947 | |
948 Heap* heap_; | |
949 HeapSnapshot* snapshot_; | |
950 HeapSnapshotsCollection* collection_; | |
951 SnapshottingProgressReportingInterface* progress_; | |
952 SnapshotFillerInterface* filler_; | |
953 HeapObjectsSet objects_tags_; | |
954 HeapObjectsSet strong_gc_subroot_names_; | |
955 v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_; | |
956 | |
957 static HeapObject* const kGcRootsObject; | |
958 static HeapObject* const kFirstGcSubrootObject; | |
959 static HeapObject* const kLastGcSubrootObject; | |
960 | |
961 friend class IndexedReferencesExtractor; | |
962 friend class GcSubrootsEnumerator; | |
963 friend class RootsReferencesExtractor; | |
964 | |
965 DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer); | |
966 }; | |
967 | |
968 | |
969 class NativeGroupRetainedObjectInfo; | |
970 | |
971 | |
972 // An implementation of retained native objects extractor. | |
973 class NativeObjectsExplorer { | |
974 public: | |
975 NativeObjectsExplorer(HeapSnapshot* snapshot, | |
976 SnapshottingProgressReportingInterface* progress); | |
977 virtual ~NativeObjectsExplorer(); | |
978 void AddRootEntries(SnapshotFillerInterface* filler); | |
979 int EstimateObjectsCount(); | |
980 bool IterateAndExtractReferences(SnapshotFillerInterface* filler); | |
981 | |
982 private: | |
983 void FillRetainedObjects(); | |
984 void FillImplicitReferences(); | |
985 List<HeapObject*>* GetListMaybeDisposeInfo(v8::RetainedObjectInfo* info); | |
986 void SetNativeRootReference(v8::RetainedObjectInfo* info); | |
987 void SetRootNativeRootsReference(); | |
988 void SetWrapperNativeReferences(HeapObject* wrapper, | |
989 v8::RetainedObjectInfo* info); | |
990 void VisitSubtreeWrapper(Object** p, uint16_t class_id); | |
991 | |
992 static uint32_t InfoHash(v8::RetainedObjectInfo* info) { | |
993 return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash()), | |
994 v8::internal::kZeroHashSeed); | |
995 } | |
996 static bool RetainedInfosMatch(void* key1, void* key2) { | |
997 return key1 == key2 || | |
998 (reinterpret_cast<v8::RetainedObjectInfo*>(key1))->IsEquivalent( | |
999 reinterpret_cast<v8::RetainedObjectInfo*>(key2)); | |
1000 } | |
1001 INLINE(static bool StringsMatch(void* key1, void* key2)) { | |
1002 return strcmp(reinterpret_cast<char*>(key1), | |
1003 reinterpret_cast<char*>(key2)) == 0; | |
1004 } | |
1005 | |
1006 NativeGroupRetainedObjectInfo* FindOrAddGroupInfo(const char* label); | |
1007 | |
1008 HeapSnapshot* snapshot_; | |
1009 HeapSnapshotsCollection* collection_; | |
1010 SnapshottingProgressReportingInterface* progress_; | |
1011 bool embedder_queried_; | |
1012 HeapObjectsSet in_groups_; | |
1013 // RetainedObjectInfo* -> List<HeapObject*>* | |
1014 HashMap objects_by_info_; | |
1015 HashMap native_groups_; | |
1016 HeapEntriesAllocator* synthetic_entries_allocator_; | |
1017 HeapEntriesAllocator* native_entries_allocator_; | |
1018 // Used during references extraction. | |
1019 SnapshotFillerInterface* filler_; | |
1020 | |
1021 static HeapThing const kNativesRootObject; | |
1022 | |
1023 friend class GlobalHandlesExtractor; | |
1024 | |
1025 DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer); | |
1026 }; | |
1027 | |
1028 | |
1029 class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface { | |
1030 public: | |
1031 HeapSnapshotGenerator(HeapSnapshot* snapshot, | |
1032 v8::ActivityControl* control, | |
1033 v8::HeapProfiler::ObjectNameResolver* resolver, | |
1034 Heap* heap); | |
1035 bool GenerateSnapshot(); | |
1036 | |
1037 private: | |
1038 bool FillReferences(); | |
1039 void ProgressStep(); | |
1040 bool ProgressReport(bool force = false); | |
1041 void SetProgressTotal(int iterations_count); | |
1042 | |
1043 HeapSnapshot* snapshot_; | |
1044 v8::ActivityControl* control_; | |
1045 V8HeapExplorer v8_heap_explorer_; | |
1046 NativeObjectsExplorer dom_explorer_; | |
1047 // Mapping from HeapThing pointers to HeapEntry* pointers. | |
1048 HeapEntriesMap entries_; | |
1049 // Used during snapshot generation. | |
1050 int progress_counter_; | |
1051 int progress_total_; | |
1052 Heap* heap_; | |
1053 | |
1054 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator); | |
1055 }; | |
1056 | |
1057 class OutputStreamWriter; | |
1058 | |
1059 class HeapSnapshotJSONSerializer { | |
1060 public: | |
1061 explicit HeapSnapshotJSONSerializer(HeapSnapshot* snapshot) | |
1062 : snapshot_(snapshot), | |
1063 strings_(ObjectsMatch), | |
1064 next_node_id_(1), | |
1065 next_string_id_(1), | |
1066 writer_(NULL) { | |
1067 } | |
1068 void Serialize(v8::OutputStream* stream); | |
1069 | |
1070 private: | |
1071 INLINE(static bool ObjectsMatch(void* key1, void* key2)) { | |
1072 return key1 == key2; | |
1073 } | |
1074 | |
1075 INLINE(static uint32_t ObjectHash(const void* key)) { | |
1076 return ComputeIntegerHash( | |
1077 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)), | |
1078 v8::internal::kZeroHashSeed); | |
1079 } | |
1080 | |
1081 HeapSnapshot* CreateFakeSnapshot(); | |
1082 int GetStringId(const char* s); | |
1083 int entry_index(HeapEntry* e) { return e->index() * kNodeFieldsCount; } | |
1084 void SerializeEdge(HeapGraphEdge* edge, bool first_edge); | |
1085 void SerializeEdges(); | |
1086 void SerializeImpl(); | |
1087 void SerializeNode(HeapEntry* entry); | |
1088 void SerializeNodes(); | |
1089 void SerializeSnapshot(); | |
1090 void SerializeString(const unsigned char* s); | |
1091 void SerializeStrings(); | |
1092 void SortHashMap(HashMap* map, List<HashMap::Entry*>* sorted_entries); | |
1093 | |
1094 static const int kEdgeFieldsCount; | |
1095 static const int kNodeFieldsCount; | |
1096 | |
1097 HeapSnapshot* snapshot_; | |
1098 HashMap strings_; | |
1099 int next_node_id_; | |
1100 int next_string_id_; | |
1101 OutputStreamWriter* writer_; | |
1102 | |
1103 friend class HeapSnapshotJSONSerializerEnumerator; | |
1104 friend class HeapSnapshotJSONSerializerIterator; | |
1105 | |
1106 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer); | |
1107 }; | |
1108 | |
1109 } } // namespace v8::internal | 450 } } // namespace v8::internal |
1110 | 451 |
1111 #endif // V8_PROFILE_GENERATOR_H_ | 452 #endif // V8_PROFILE_GENERATOR_H_ |
OLD | NEW |