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

Side by Side Diff: src/profile-generator.cc

Issue 3060008: Heap profiler: reduce heap snapshots size. (Closed)
Patch Set: Comments addressed Created 10 years, 4 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
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('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 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 780 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 // If no frames were symbolized, put the VM state entry in. 791 // If no frames were symbolized, put the VM state entry in.
792 if (no_symbolized_entries) { 792 if (no_symbolized_entries) {
793 *entry++ = EntryForVMState(sample.state); 793 *entry++ = EntryForVMState(sample.state);
794 } 794 }
795 } 795 }
796 796
797 profiles_->AddPathToCurrentProfiles(entries); 797 profiles_->AddPathToCurrentProfiles(entries);
798 } 798 }
799 799
800 800
801 HeapGraphEdge::HeapGraphEdge(Type type, 801 void HeapGraphEdge::Init(
802 const char* name, 802 int child_index, Type type, const char* name, HeapEntry* to) {
803 HeapEntry* from, 803 ASSERT(type == kContextVariable || type == kProperty || type == kInternal);
804 HeapEntry* to) 804 child_index_ = child_index;
805 : type_(type), name_(name), from_(from), to_(to) { 805 type_ = type;
806 ASSERT(type_ == CONTEXT_VARIABLE || type_ == PROPERTY || type_ == INTERNAL); 806 name_ = name;
807 to_ = to;
807 } 808 }
808 809
809 810
810 HeapGraphEdge::HeapGraphEdge(int index, 811 void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) {
811 HeapEntry* from, 812 child_index_ = child_index;
812 HeapEntry* to) 813 type_ = kElement;
813 : type_(ELEMENT), index_(index), from_(from), to_(to) { 814 index_ = index;
815 to_ = to;
814 } 816 }
815 817
816 818
817 static void DeleteHeapGraphEdge(HeapGraphEdge** edge_ptr) { 819 HeapEntry* HeapGraphEdge::From() {
818 delete *edge_ptr; 820 return reinterpret_cast<HeapEntry*>(this - child_index_) - 1;
819 } 821 }
820 822
821 823
822 static void DeleteHeapGraphPath(HeapGraphPath** path_ptr) { 824 void HeapEntry::Init(HeapSnapshot* snapshot,
823 delete *path_ptr; 825 int children_count,
826 int retainers_count) {
827 Init(snapshot, kInternal, "", 0, 0, children_count, retainers_count);
824 } 828 }
825 829
826 830
827 HeapEntry::~HeapEntry() { 831 void HeapEntry::Init(HeapSnapshot* snapshot,
828 children_.Iterate(DeleteHeapGraphEdge); 832 Type type,
829 retaining_paths_.Iterate(DeleteHeapGraphPath); 833 const char* name,
834 uint64_t id,
835 int self_size,
836 int children_count,
837 int retainers_count) {
838 snapshot_ = snapshot;
839 type_ = type;
840 painted_ = kUnpainted;
841 calculated_data_index_ = kNoCalculatedData;
842 name_ = name;
843 id_ = id;
844 self_size_ = self_size;
845 children_count_ = children_count;
846 retainers_count_ = retainers_count;
830 } 847 }
831 848
832 849
833 void HeapEntry::AddEdge(HeapGraphEdge* edge) { 850 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type,
834 children_.Add(edge); 851 int child_index,
835 edge->to()->retainers_.Add(edge); 852 const char* name,
853 HeapEntry* entry,
854 int retainer_index) {
855 children_arr()[child_index].Init(child_index, type, name, entry);
856 entry->retainers_arr()[retainer_index] = children_arr() + child_index;
836 } 857 }
837 858
838 859
839 void HeapEntry::SetClosureReference(const char* name, HeapEntry* entry) { 860 void HeapEntry::SetElementReference(
840 AddEdge( 861 int child_index, int index, HeapEntry* entry, int retainer_index) {
841 new HeapGraphEdge(HeapGraphEdge::CONTEXT_VARIABLE, name, this, entry)); 862 children_arr()[child_index].Init(child_index, index, entry);
863 entry->retainers_arr()[retainer_index] = children_arr() + child_index;
842 } 864 }
843 865
844 866
845 void HeapEntry::SetElementReference(int index, HeapEntry* entry) { 867 void HeapEntry::SetUnidirElementReference(
846 AddEdge(new HeapGraphEdge(index, this, entry)); 868 int child_index, int index, HeapEntry* entry) {
869 children_arr()[child_index].Init(child_index, index, entry);
847 } 870 }
848 871
849 872
850 void HeapEntry::SetInternalReference(const char* name, HeapEntry* entry) { 873 int HeapEntry::ReachableSize() {
851 AddEdge(new HeapGraphEdge(HeapGraphEdge::INTERNAL, name, this, entry)); 874 if (calculated_data_index_ == kNoCalculatedData) {
875 calculated_data_index_ = snapshot_->AddCalculatedData();
876 }
877 return snapshot_->GetCalculatedData(
878 calculated_data_index_).ReachableSize(this);
852 } 879 }
853 880
854 881
855 void HeapEntry::SetPropertyReference(const char* name, HeapEntry* entry) { 882 int HeapEntry::RetainedSize() {
856 AddEdge(new HeapGraphEdge(HeapGraphEdge::PROPERTY, name, this, entry)); 883 if (calculated_data_index_ == kNoCalculatedData) {
884 calculated_data_index_ = snapshot_->AddCalculatedData();
885 }
886 return snapshot_->GetCalculatedData(
887 calculated_data_index_).RetainedSize(this);
857 } 888 }
858 889
859 890
860 void HeapEntry::SetAutoIndexReference(HeapEntry* entry) { 891 List<HeapGraphPath*>* HeapEntry::GetRetainingPaths() {
861 SetElementReference(next_auto_index_++, entry); 892 if (calculated_data_index_ == kNoCalculatedData) {
893 calculated_data_index_ = snapshot_->AddCalculatedData();
894 }
895 return snapshot_->GetCalculatedData(
896 calculated_data_index_).GetRetainingPaths(this);
862 } 897 }
863 898
864 899
865 void HeapEntry::SetUnidirAutoIndexReference(HeapEntry* entry) {
866 children_.Add(new HeapGraphEdge(next_auto_index_++, this, entry));
867 }
868
869
870 int HeapEntry::TotalSize() {
871 return total_size_ != kUnknownSize ? total_size_ : CalculateTotalSize();
872 }
873
874
875 int HeapEntry::NonSharedTotalSize() {
876 return non_shared_total_size_ != kUnknownSize ?
877 non_shared_total_size_ : CalculateNonSharedTotalSize();
878 }
879
880
881 template<class Visitor> 900 template<class Visitor>
882 void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) { 901 void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) {
883 List<HeapEntry*> list(10); 902 List<HeapEntry*> list(10);
884 list.Add(this); 903 list.Add(this);
885 this->PaintReachable(); 904 this->paint_reachable();
886 visitor->Apply(this); 905 visitor->Apply(this);
887 while (!list.is_empty()) { 906 while (!list.is_empty()) {
888 HeapEntry* entry = list.RemoveLast(); 907 HeapEntry* entry = list.RemoveLast();
889 const int children_count = entry->children_.length(); 908 Vector<HeapGraphEdge> children = entry->children();
890 for (int i = 0; i < children_count; ++i) { 909 for (int i = 0; i < children.length(); ++i) {
891 HeapEntry* child = entry->children_[i]->to(); 910 HeapEntry* child = children[i].to();
892 if (!child->painted_reachable()) { 911 if (!child->painted_reachable()) {
893 list.Add(child); 912 list.Add(child);
894 child->PaintReachable(); 913 child->paint_reachable();
895 visitor->Apply(child); 914 visitor->Apply(child);
896 } 915 }
897 } 916 }
898 } 917 }
899 } 918 }
900 919
901 920
902 class NullClass { 921 class NullClass {
903 public: 922 public:
904 void Apply(HeapEntry* entry) { } 923 void Apply(HeapEntry* entry) { }
905 }; 924 };
906 925
907 void HeapEntry::PaintAllReachable() { 926 void HeapEntry::PaintAllReachable() {
908 NullClass null; 927 NullClass null;
909 ApplyAndPaintAllReachable(&null); 928 ApplyAndPaintAllReachable(&null);
910 } 929 }
911 930
912 931
913 class TotalSizeCalculator { 932 void HeapEntry::Print(int max_depth, int indent) {
933 OS::Print("%6d %6d %6d [%ld] ",
934 self_size(), ReachableSize(), RetainedSize(), id_);
935 if (type() != kString) {
936 OS::Print("%s %.40s\n", TypeAsString(), name_);
937 } else {
938 OS::Print("\"");
939 const char* c = name_;
940 while (*c && (c - name_) <= 40) {
941 if (*c != '\n')
942 OS::Print("%c", *c);
943 else
944 OS::Print("\\n");
945 ++c;
946 }
947 OS::Print("\"\n");
948 }
949 if (--max_depth == 0) return;
950 Vector<HeapGraphEdge> ch = children();
951 for (int i = 0; i < ch.length(); ++i) {
952 HeapGraphEdge& edge = ch[i];
953 switch (edge.type()) {
954 case HeapGraphEdge::kContextVariable:
955 OS::Print(" %*c #%s: ", indent, ' ', edge.name());
956 break;
957 case HeapGraphEdge::kElement:
958 OS::Print(" %*c %d: ", indent, ' ', edge.index());
959 break;
960 case HeapGraphEdge::kInternal:
961 OS::Print(" %*c $%s: ", indent, ' ', edge.name());
962 break;
963 case HeapGraphEdge::kProperty:
964 OS::Print(" %*c %s: ", indent, ' ', edge.name());
965 break;
966 default:
967 OS::Print("!!! unknown edge type: %d ", edge.type());
968 }
969 edge.to()->Print(max_depth, indent + 2);
970 }
971 }
972
973
974 const char* HeapEntry::TypeAsString() {
975 switch (type()) {
976 case kInternal: return "/internal/";
977 case kObject: return "/object/";
978 case kClosure: return "/closure/";
979 case kString: return "/string/";
980 case kCode: return "/code/";
981 case kArray: return "/array/";
982 default: return "???";
983 }
984 }
985
986
987 int HeapEntry::EntriesSize(int entries_count,
988 int children_count,
989 int retainers_count) {
990 return sizeof(HeapEntry) * entries_count // NOLINT
991 + sizeof(HeapGraphEdge) * children_count // NOLINT
992 + sizeof(HeapGraphEdge*) * retainers_count; // NOLINT
993 }
994
995
996 static void DeleteHeapGraphPath(HeapGraphPath** path_ptr) {
997 delete *path_ptr;
998 }
999
1000 void HeapEntryCalculatedData::Dispose() {
1001 if (retaining_paths_ != NULL) retaining_paths_->Iterate(DeleteHeapGraphPath);
1002 delete retaining_paths_;
1003 }
1004
1005
1006 int HeapEntryCalculatedData::ReachableSize(HeapEntry* entry) {
1007 if (reachable_size_ == kUnknownSize) CalculateSizes(entry);
1008 return reachable_size_;
1009 }
1010
1011
1012 int HeapEntryCalculatedData::RetainedSize(HeapEntry* entry) {
1013 if (retained_size_ == kUnknownSize) CalculateSizes(entry);
1014 return retained_size_;
1015 }
1016
1017
1018 class ReachableSizeCalculator {
914 public: 1019 public:
915 TotalSizeCalculator() 1020 ReachableSizeCalculator()
916 : total_size_(0) { 1021 : reachable_size_(0) {
917 } 1022 }
918 1023
919 int total_size() const { return total_size_; } 1024 int reachable_size() const { return reachable_size_; }
920 1025
921 void Apply(HeapEntry* entry) { 1026 void Apply(HeapEntry* entry) {
922 total_size_ += entry->self_size(); 1027 reachable_size_ += entry->self_size();
923 } 1028 }
924 1029
925 private: 1030 private:
926 int total_size_; 1031 int reachable_size_;
927 }; 1032 };
928 1033
929 int HeapEntry::CalculateTotalSize() { 1034 class RetainedSizeCalculator {
930 snapshot_->ClearPaint();
931 TotalSizeCalculator calc;
932 ApplyAndPaintAllReachable(&calc);
933 total_size_ = calc.total_size();
934 return total_size_;
935 }
936
937
938 class NonSharedSizeCalculator {
939 public: 1035 public:
940 NonSharedSizeCalculator() 1036 RetainedSizeCalculator()
941 : non_shared_total_size_(0) { 1037 : retained_size_(0) {
942 } 1038 }
943 1039
944 int non_shared_total_size() const { return non_shared_total_size_; } 1040 int reained_size() const { return retained_size_; }
945 1041
946 void Apply(HeapEntry* entry) { 1042 void Apply(HeapEntry** entry_ptr) {
947 if (entry->painted_reachable()) { 1043 if ((*entry_ptr)->painted_reachable()) {
948 non_shared_total_size_ += entry->self_size(); 1044 retained_size_ += (*entry_ptr)->self_size();
949 } 1045 }
950 } 1046 }
951 1047
952 private: 1048 private:
953 int non_shared_total_size_; 1049 int retained_size_;
954 }; 1050 };
955 1051
956 int HeapEntry::CalculateNonSharedTotalSize() { 1052 void HeapEntryCalculatedData::CalculateSizes(HeapEntry* entry) {
957 // To calculate non-shared total size, first we paint all reachable 1053 // To calculate retained size, first we paint all reachable nodes in
958 // nodes in one color, then we paint all nodes reachable from other 1054 // one color (and calculate reachable size as a byproduct), then we
959 // nodes with a different color. Then we consider only nodes painted 1055 // paint (or re-paint) all nodes reachable from other nodes with a
960 // with the first color for calculating the total size. 1056 // different color. Then we consider only nodes painted with the
961 snapshot_->ClearPaint(); 1057 // first color for calculating the retained size.
962 PaintAllReachable(); 1058 entry->snapshot()->ClearPaint();
1059 ReachableSizeCalculator rch_size_calc;
1060 entry->ApplyAndPaintAllReachable(&rch_size_calc);
1061 reachable_size_ = rch_size_calc.reachable_size();
963 1062
964 List<HeapEntry*> list(10); 1063 List<HeapEntry*> list(10);
965 if (this != snapshot_->root()) { 1064 HeapEntry* root = entry->snapshot()->root();
966 list.Add(snapshot_->root()); 1065 if (entry != root) {
967 snapshot_->root()->PaintReachableFromOthers(); 1066 list.Add(root);
1067 root->paint_reachable_from_others();
968 } 1068 }
969 while (!list.is_empty()) { 1069 while (!list.is_empty()) {
970 HeapEntry* entry = list.RemoveLast(); 1070 HeapEntry* curr = list.RemoveLast();
971 const int children_count = entry->children_.length(); 1071 Vector<HeapGraphEdge> children = curr->children();
972 for (int i = 0; i < children_count; ++i) { 1072 for (int i = 0; i < children.length(); ++i) {
973 HeapEntry* child = entry->children_[i]->to(); 1073 HeapEntry* child = children[i].to();
974 if (child != this && child->not_painted_reachable_from_others()) { 1074 if (child != entry && child->not_painted_reachable_from_others()) {
975 list.Add(child); 1075 list.Add(child);
976 child->PaintReachableFromOthers(); 1076 child->paint_reachable_from_others();
977 } 1077 }
978 } 1078 }
979 } 1079 }
980 1080
981 NonSharedSizeCalculator calculator; 1081 RetainedSizeCalculator ret_size_calc;
982 snapshot_->IterateEntries(&calculator); 1082 entry->snapshot()->IterateEntries(&ret_size_calc);
983 non_shared_total_size_ = calculator.non_shared_total_size(); 1083 retained_size_ = ret_size_calc.reained_size();
984 return non_shared_total_size_;
985 } 1084 }
986 1085
987 1086
988 class CachedHeapGraphPath { 1087 class CachedHeapGraphPath {
989 public: 1088 public:
990 CachedHeapGraphPath() 1089 CachedHeapGraphPath()
991 : nodes_(NodesMatch) { } 1090 : nodes_(NodesMatch) { }
992 CachedHeapGraphPath(const CachedHeapGraphPath& src) 1091 CachedHeapGraphPath(const CachedHeapGraphPath& src)
993 : nodes_(NodesMatch, &HashMap::DefaultAllocator, src.nodes_.capacity()), 1092 : nodes_(NodesMatch, &HashMap::DefaultAllocator, src.nodes_.capacity()),
994 path_(src.path_.length() + 1) { 1093 path_(src.path_.length() + 1) {
(...skipping 17 matching lines...) Expand all
1012 static uint32_t Hash(HeapEntry* entry) { 1111 static uint32_t Hash(HeapEntry* entry) {
1013 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry)); 1112 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry));
1014 } 1113 }
1015 static bool NodesMatch(void* key1, void* key2) { return key1 == key2; } 1114 static bool NodesMatch(void* key1, void* key2) { return key1 == key2; }
1016 1115
1017 HashMap nodes_; 1116 HashMap nodes_;
1018 List<HeapGraphEdge*> path_; 1117 List<HeapGraphEdge*> path_;
1019 }; 1118 };
1020 1119
1021 1120
1022 const List<HeapGraphPath*>* HeapEntry::GetRetainingPaths() { 1121 List<HeapGraphPath*>* HeapEntryCalculatedData::GetRetainingPaths(
1023 if (retaining_paths_.length() == 0 && retainers_.length() != 0) { 1122 HeapEntry* entry) {
1123 if (retaining_paths_ == NULL) retaining_paths_ = new List<HeapGraphPath*>(4);
1124 if (retaining_paths_->length() == 0 && entry->retainers().length() != 0) {
1024 CachedHeapGraphPath path; 1125 CachedHeapGraphPath path;
1025 FindRetainingPaths(this, &path); 1126 FindRetainingPaths(entry, &path);
1026 } 1127 }
1027 return &retaining_paths_; 1128 return retaining_paths_;
1028 } 1129 }
1029 1130
1030 1131
1031 void HeapEntry::FindRetainingPaths(HeapEntry* node, 1132 void HeapEntryCalculatedData::FindRetainingPaths(
1032 CachedHeapGraphPath* prev_path) { 1133 HeapEntry* entry,
1033 for (int i = 0; i < node->retainers_.length(); ++i) { 1134 CachedHeapGraphPath* prev_path) {
1034 HeapGraphEdge* ret_edge = node->retainers_[i]; 1135 Vector<HeapGraphEdge*> retainers = entry->retainers();
1035 if (prev_path->ContainsNode(ret_edge->from())) continue; 1136 for (int i = 0; i < retainers.length(); ++i) {
1036 if (ret_edge->from() != snapshot_->root()) { 1137 HeapGraphEdge* ret_edge = retainers[i];
1138 if (prev_path->ContainsNode(ret_edge->From())) continue;
1139 if (ret_edge->From() != entry->snapshot()->root()) {
1037 CachedHeapGraphPath path(*prev_path); 1140 CachedHeapGraphPath path(*prev_path);
1038 path.Add(ret_edge); 1141 path.Add(ret_edge);
1039 FindRetainingPaths(ret_edge->from(), &path); 1142 FindRetainingPaths(ret_edge->From(), &path);
1040 } else { 1143 } else {
1041 HeapGraphPath* ret_path = new HeapGraphPath(*prev_path->path()); 1144 HeapGraphPath* ret_path = new HeapGraphPath(*prev_path->path());
1042 ret_path->Set(0, ret_edge); 1145 ret_path->Set(0, ret_edge);
1043 retaining_paths_.Add(ret_path); 1146 retaining_paths_->Add(ret_path);
1044 } 1147 }
1045 } 1148 }
1046 } 1149 }
1047 1150
1048
1049 static void RemoveEdge(List<HeapGraphEdge*>* list, HeapGraphEdge* edge) {
1050 for (int i = 0; i < list->length(); ) {
1051 if (list->at(i) == edge) {
1052 list->Remove(i);
1053 return;
1054 } else {
1055 ++i;
1056 }
1057 }
1058 UNREACHABLE();
1059 }
1060
1061
1062 void HeapEntry::RemoveChild(HeapGraphEdge* edge) {
1063 RemoveEdge(&children_, edge);
1064 delete edge;
1065 }
1066
1067
1068 void HeapEntry::RemoveRetainer(HeapGraphEdge* edge) {
1069 RemoveEdge(&retainers_, edge);
1070 }
1071
1072
1073 void HeapEntry::CutEdges() {
1074 for (int i = 0; i < children_.length(); ++i) {
1075 HeapGraphEdge* edge = children_[i];
1076 edge->to()->RemoveRetainer(edge);
1077 }
1078 children_.Iterate(DeleteHeapGraphEdge);
1079 children_.Clear();
1080
1081 for (int i = 0; i < retainers_.length(); ++i) {
1082 HeapGraphEdge* edge = retainers_[i];
1083 edge->from()->RemoveChild(edge);
1084 }
1085 retainers_.Clear();
1086 }
1087
1088
1089 void HeapEntry::Print(int max_depth, int indent) {
1090 OS::Print("%6d %6d %6d [%ld] ",
1091 self_size_, TotalSize(), NonSharedTotalSize(), id_);
1092 if (type_ != STRING) {
1093 OS::Print("%s %.40s\n", TypeAsString(), name_);
1094 } else {
1095 OS::Print("\"");
1096 const char* c = name_;
1097 while (*c && (c - name_) <= 40) {
1098 if (*c != '\n')
1099 OS::Print("%c", *c);
1100 else
1101 OS::Print("\\n");
1102 ++c;
1103 }
1104 OS::Print("\"\n");
1105 }
1106 if (--max_depth == 0) return;
1107 const int children_count = children_.length();
1108 for (int i = 0; i < children_count; ++i) {
1109 HeapGraphEdge* edge = children_[i];
1110 switch (edge->type()) {
1111 case HeapGraphEdge::CONTEXT_VARIABLE:
1112 OS::Print(" %*c #%s: ", indent, ' ', edge->name());
1113 break;
1114 case HeapGraphEdge::ELEMENT:
1115 OS::Print(" %*c %d: ", indent, ' ', edge->index());
1116 break;
1117 case HeapGraphEdge::INTERNAL:
1118 OS::Print(" %*c $%s: ", indent, ' ', edge->name());
1119 break;
1120 case HeapGraphEdge::PROPERTY:
1121 OS::Print(" %*c %s: ", indent, ' ', edge->name());
1122 break;
1123 default:
1124 OS::Print("!!! unknown edge type: %d ", edge->type());
1125 }
1126 edge->to()->Print(max_depth, indent + 2);
1127 }
1128 }
1129
1130
1131 const char* HeapEntry::TypeAsString() {
1132 switch (type_) {
1133 case INTERNAL: return "/internal/";
1134 case OBJECT: return "/object/";
1135 case CLOSURE: return "/closure/";
1136 case STRING: return "/string/";
1137 case CODE: return "/code/";
1138 case ARRAY: return "/array/";
1139 default: return "???";
1140 }
1141 }
1142
1143 1151
1144 HeapGraphPath::HeapGraphPath(const List<HeapGraphEdge*>& path) 1152 HeapGraphPath::HeapGraphPath(const List<HeapGraphEdge*>& path)
1145 : path_(path.length() + 1) { 1153 : path_(path.length() + 1) {
1146 Add(NULL); 1154 Add(NULL);
1147 for (int i = path.length() - 1; i >= 0; --i) { 1155 for (int i = path.length() - 1; i >= 0; --i) {
1148 Add(path[i]); 1156 Add(path[i]);
1149 } 1157 }
1150 } 1158 }
1151 1159
1152 1160
1153 void HeapGraphPath::Print() { 1161 void HeapGraphPath::Print() {
1154 path_[0]->from()->Print(1, 0); 1162 path_[0]->From()->Print(1, 0);
1155 for (int i = 0; i < path_.length(); ++i) { 1163 for (int i = 0; i < path_.length(); ++i) {
1156 OS::Print(" -> "); 1164 OS::Print(" -> ");
1157 HeapGraphEdge* edge = path_[i]; 1165 HeapGraphEdge* edge = path_[i];
1158 switch (edge->type()) { 1166 switch (edge->type()) {
1159 case HeapGraphEdge::CONTEXT_VARIABLE: 1167 case HeapGraphEdge::kContextVariable:
1160 OS::Print("[#%s] ", edge->name()); 1168 OS::Print("[#%s] ", edge->name());
1161 break; 1169 break;
1162 case HeapGraphEdge::ELEMENT: 1170 case HeapGraphEdge::kElement:
1163 OS::Print("[%d] ", edge->index()); 1171 OS::Print("[%d] ", edge->index());
1164 break; 1172 break;
1165 case HeapGraphEdge::INTERNAL: 1173 case HeapGraphEdge::kInternal:
1166 OS::Print("[$%s] ", edge->name()); 1174 OS::Print("[$%s] ", edge->name());
1167 break; 1175 break;
1168 case HeapGraphEdge::PROPERTY: 1176 case HeapGraphEdge::kProperty:
1169 OS::Print("[%s] ", edge->name()); 1177 OS::Print("[%s] ", edge->name());
1170 break; 1178 break;
1171 default: 1179 default:
1172 OS::Print("!!! unknown edge type: %d ", edge->type()); 1180 OS::Print("!!! unknown edge type: %d ", edge->type());
1173 } 1181 }
1174 edge->to()->Print(1, 0); 1182 edge->to()->Print(1, 0);
1175 } 1183 }
1176 OS::Print("\n"); 1184 OS::Print("\n");
1177 } 1185 }
1178 1186
1179 1187
1180 class IndexedReferencesExtractor : public ObjectVisitor { 1188 HeapObject *const HeapSnapshot::kInternalRootObject =
1181 public: 1189 reinterpret_cast<HeapObject*>(1);
1182 IndexedReferencesExtractor(HeapSnapshot* snapshot, HeapEntry* parent)
1183 : snapshot_(snapshot),
1184 parent_(parent) {
1185 }
1186
1187 void VisitPointer(Object** o) {
1188 if (!(*o)->IsHeapObject()) return;
1189 HeapEntry* entry = snapshot_->GetEntry(HeapObject::cast(*o));
1190 if (entry != NULL) {
1191 parent_->SetAutoIndexReference(entry);
1192 }
1193 }
1194
1195 void VisitPointers(Object** start, Object** end) {
1196 for (Object** p = start; p < end; p++) VisitPointer(p);
1197 }
1198
1199 private:
1200 HeapSnapshot* snapshot_;
1201 HeapEntry* parent_;
1202 };
1203
1204
1205 HeapEntriesMap::HeapEntriesMap()
1206 : entries_(HeapObjectsMatch) {
1207 }
1208
1209
1210 HeapEntriesMap::~HeapEntriesMap() {
1211 for (HashMap::Entry* p = entries_.Start();
1212 p != NULL;
1213 p = entries_.Next(p)) {
1214 if (!IsAlias(p->value)) delete reinterpret_cast<HeapEntry*>(p->value);
1215 }
1216 }
1217
1218
1219 void HeapEntriesMap::Alias(HeapObject* object, HeapEntry* entry) {
1220 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), true);
1221 if (cache_entry->value == NULL)
1222 cache_entry->value = reinterpret_cast<void*>(
1223 reinterpret_cast<intptr_t>(entry) | kAliasTag);
1224 }
1225
1226
1227 void HeapEntriesMap::Apply(void (HeapEntry::*Func)(void)) {
1228 for (HashMap::Entry* p = entries_.Start();
1229 p != NULL;
1230 p = entries_.Next(p)) {
1231 if (!IsAlias(p->value)) (reinterpret_cast<HeapEntry*>(p->value)->*Func)();
1232 }
1233 }
1234
1235
1236 HeapEntry* HeapEntriesMap::Map(HeapObject* object) {
1237 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false);
1238 return cache_entry != NULL ?
1239 reinterpret_cast<HeapEntry*>(
1240 reinterpret_cast<intptr_t>(cache_entry->value) & (~kAliasTag)) : NULL;
1241 }
1242
1243
1244 void HeapEntriesMap::Pair(HeapObject* object, HeapEntry* entry) {
1245 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), true);
1246 ASSERT(cache_entry->value == NULL);
1247 cache_entry->value = entry;
1248 }
1249
1250 1190
1251 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, 1191 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1252 const char* title, 1192 const char* title,
1253 unsigned uid) 1193 unsigned uid)
1254 : collection_(collection), 1194 : collection_(collection),
1255 title_(title), 1195 title_(title),
1256 uid_(uid), 1196 uid_(uid),
1257 root_(this), 1197 root_entry_index_(-1),
1258 sorted_entries_(NULL) { 1198 raw_entries_(NULL),
1199 entries_sorted_(false) {
1259 } 1200 }
1260 1201
1261 1202
1203 static void DisposeCalculatedData(HeapEntryCalculatedData* cdata) {
1204 cdata->Dispose();
1205 }
1206
1262 HeapSnapshot::~HeapSnapshot() { 1207 HeapSnapshot::~HeapSnapshot() {
1263 delete sorted_entries_; 1208 DeleteArray(raw_entries_);
1209 calculated_data_.Iterate(DisposeCalculatedData);
1264 } 1210 }
1265 1211
1266 1212
1267 void HeapSnapshot::ClearPaint() { 1213 void HeapSnapshot::AllocateEntries(int entries_count,
1268 root_.ClearPaint(); 1214 int children_count,
1269 entries_.Apply(&HeapEntry::ClearPaint); 1215 int retainers_count) {
1216 ASSERT(raw_entries_ == NULL);
1217 raw_entries_ = NewArray<char>(
1218 HeapEntry::EntriesSize(entries_count, children_count, retainers_count));
1270 } 1219 }
1271 1220
1272 1221
1273 HeapEntry* HeapSnapshot::GetEntry(Object* obj) { 1222 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
1274 if (!obj->IsHeapObject()) return NULL; 1223 int children_count,
1275 HeapObject* object = HeapObject::cast(obj); 1224 int retainers_count) {
1276 1225 if (object == kInternalRootObject) {
1277 { 1226 ASSERT(root_entry_index_ == -1);
1278 HeapEntry* existing = FindEntry(object); 1227 root_entry_index_ = entries_.length();
1279 if (existing != NULL) return existing; 1228 HeapEntry* entry = GetNextEntryToInit();
1280 } 1229 entry->Init(this, children_count, retainers_count);
1281 1230 return entry;
1282 // Add new entry. 1231 } else if (object->IsJSFunction()) {
1283 if (object->IsJSFunction()) {
1284 JSFunction* func = JSFunction::cast(object); 1232 JSFunction* func = JSFunction::cast(object);
1285 SharedFunctionInfo* shared = func->shared(); 1233 SharedFunctionInfo* shared = func->shared();
1286 String* name = String::cast(shared->name())->length() > 0 ? 1234 String* name = String::cast(shared->name())->length() > 0 ?
1287 String::cast(shared->name()) : shared->inferred_name(); 1235 String::cast(shared->name()) : shared->inferred_name();
1288 return AddEntry(object, HeapEntry::CLOSURE, collection_->GetName(name)); 1236 return AddEntry(object,
1237 HeapEntry::kClosure,
1238 collection_->GetName(name),
1239 children_count,
1240 retainers_count);
1289 } else if (object->IsJSObject()) { 1241 } else if (object->IsJSObject()) {
1290 return AddEntry(object, 1242 return AddEntry(object,
1291 HeapEntry::OBJECT, 1243 HeapEntry::kObject,
1292 collection_->GetName( 1244 collection_->GetName(
1293 JSObject::cast(object)->constructor_name())); 1245 JSObject::cast(object)->constructor_name()),
1294 } else if (object->IsJSGlobalPropertyCell()) { 1246 children_count,
1295 HeapEntry* value = GetEntry(JSGlobalPropertyCell::cast(object)->value()); 1247 retainers_count);
1296 // If GPC references an object that we have interest in, add the object.
1297 // We don't store HeapEntries for GPCs. Instead, we make our hash map
1298 // to point to object's HeapEntry by GPCs address.
1299 if (value != NULL) AddEntryAlias(object, value);
1300 return value;
1301 } else if (object->IsString()) { 1248 } else if (object->IsString()) {
1302 return AddEntry(object, 1249 return AddEntry(object,
1303 HeapEntry::STRING, 1250 HeapEntry::kString,
1304 collection_->GetName(String::cast(object))); 1251 collection_->GetName(String::cast(object)),
1252 children_count,
1253 retainers_count);
1305 } else if (object->IsCode()) { 1254 } else if (object->IsCode()) {
1306 return AddEntry(object, HeapEntry::CODE); 1255 return AddEntry(object,
1256 HeapEntry::kCode,
1257 "",
1258 children_count,
1259 retainers_count);
1307 } else if (object->IsSharedFunctionInfo()) { 1260 } else if (object->IsSharedFunctionInfo()) {
1308 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); 1261 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
1309 String* name = String::cast(shared->name())->length() > 0 ? 1262 String* name = String::cast(shared->name())->length() > 0 ?
1310 String::cast(shared->name()) : shared->inferred_name(); 1263 String::cast(shared->name()) : shared->inferred_name();
1311 return AddEntry(object, HeapEntry::CODE, collection_->GetName(name)); 1264 return AddEntry(object,
1265 HeapEntry::kCode,
1266 collection_->GetName(name),
1267 children_count,
1268 retainers_count);
1312 } else if (object->IsScript()) { 1269 } else if (object->IsScript()) {
1313 Script* script = Script::cast(object); 1270 Script* script = Script::cast(object);
1314 return AddEntry(object, 1271 return AddEntry(object,
1315 HeapEntry::CODE, 1272 HeapEntry::kCode,
1316 script->name()->IsString() ? 1273 script->name()->IsString() ?
1317 collection_->GetName(String::cast(script->name())) : ""); 1274 collection_->GetName(String::cast(script->name())) : "",
1275 children_count,
1276 retainers_count);
1318 } else if (object->IsFixedArray()) { 1277 } else if (object->IsFixedArray()) {
1319 return AddEntry(object, HeapEntry::ARRAY); 1278 return AddEntry(object,
1279 HeapEntry::kArray,
1280 "",
1281 children_count,
1282 retainers_count);
1320 } 1283 }
1321 // No interest in this object. 1284 // No interest in this object.
1322 return NULL; 1285 return NULL;
1323 } 1286 }
1324 1287
1325 1288
1326 void HeapSnapshot::SetClosureReference(HeapEntry* parent, 1289 bool HeapSnapshot::WillAddEntry(HeapObject* object) {
1327 String* reference_name, 1290 return object == kInternalRootObject
1328 Object* child) { 1291 || object->IsJSFunction()
1329 HeapEntry* child_entry = GetEntry(child); 1292 || object->IsJSObject()
1330 if (child_entry != NULL) { 1293 || object->IsString()
1331 parent->SetClosureReference( 1294 || object->IsCode()
1332 collection_->GetName(reference_name), child_entry); 1295 || object->IsSharedFunctionInfo()
1333 } 1296 || object->IsScript()
1297 || object->IsFixedArray();
1334 } 1298 }
1335 1299
1336 1300
1337 void HeapSnapshot::SetElementReference(HeapEntry* parent, 1301 static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1338 int index, 1302 (*entry_ptr)->clear_paint();
1339 Object* child) { 1303 }
1340 HeapEntry* child_entry = GetEntry(child); 1304
1341 if (child_entry != NULL) { 1305 void HeapSnapshot::ClearPaint() {
1342 parent->SetElementReference(index, child_entry); 1306 entries_.Iterate(HeapEntryClearPaint);
1343 }
1344 } 1307 }
1345 1308
1346 1309
1347 void HeapSnapshot::SetInternalReference(HeapEntry* parent, 1310 int HeapSnapshot::AddCalculatedData() {
1348 const char* reference_name, 1311 calculated_data_.Add(HeapEntryCalculatedData());
1349 Object* child) { 1312 return calculated_data_.length() - 1;
1350 HeapEntry* child_entry = GetEntry(child);
1351 if (child_entry != NULL) {
1352 parent->SetInternalReference(reference_name, child_entry);
1353 }
1354 }
1355
1356
1357 void HeapSnapshot::SetPropertyReference(HeapEntry* parent,
1358 String* reference_name,
1359 Object* child) {
1360 HeapEntry* child_entry = GetEntry(child);
1361 if (child_entry != NULL) {
1362 parent->SetPropertyReference(
1363 collection_->GetName(reference_name), child_entry);
1364 }
1365 } 1313 }
1366 1314
1367 1315
1368 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, 1316 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
1369 HeapEntry::Type type, 1317 HeapEntry::Type type,
1370 const char* name) { 1318 const char* name,
1371 HeapEntry* entry = new HeapEntry(this, 1319 int children_count,
1372 type, 1320 int retainers_count) {
1373 name, 1321 HeapEntry* entry = GetNextEntryToInit();
1374 collection_->GetObjectId(object->address()), 1322 entry->Init(this,
1375 GetObjectSize(object), 1323 type,
1376 GetObjectSecurityToken(object)); 1324 name,
1377 entries_.Pair(object, entry); 1325 collection_->GetObjectId(object->address()),
1378 1326 GetObjectSize(object),
1379 // Detect, if this is a JS global object of the current context, and 1327 children_count,
1380 // add it to snapshot's roots. There can be several JS global objects 1328 retainers_count);
1381 // in a context.
1382 if (object->IsJSGlobalProxy()) {
1383 int global_security_token = GetGlobalSecurityToken();
1384 int object_security_token =
1385 collection_->token_enumerator()->GetTokenId(
1386 Context::cast(
1387 JSGlobalProxy::cast(object)->context())->security_token());
1388 if (object_security_token == TokenEnumerator::kNoSecurityToken
1389 || object_security_token == global_security_token) {
1390 HeapEntry* global_object_entry =
1391 GetEntry(HeapObject::cast(object->map()->prototype()));
1392 ASSERT(global_object_entry != NULL);
1393 root_.SetAutoIndexReference(global_object_entry);
1394 }
1395 }
1396
1397 return entry; 1329 return entry;
1398 } 1330 }
1399 1331
1400 1332
1401 class EdgesCutter { 1333 HeapEntry* HeapSnapshot::GetNextEntryToInit() {
1402 public: 1334 if (entries_.length() > 0) {
1403 explicit EdgesCutter(int global_security_token) 1335 HeapEntry* last_entry = entries_.last();
1404 : global_security_token_(global_security_token) { 1336 entries_.Add(reinterpret_cast<HeapEntry*>(
1337 reinterpret_cast<char*>(last_entry) + last_entry->EntrySize()));
1338 } else {
1339 entries_.Add(reinterpret_cast<HeapEntry*>(raw_entries_));
1405 } 1340 }
1406 1341 return entries_.last();
1407 void Apply(HeapEntry* entry) {
1408 if (entry->security_token_id() != TokenEnumerator::kNoSecurityToken
1409 && entry->security_token_id() != global_security_token_) {
1410 entry->CutEdges();
1411 }
1412 }
1413
1414 private:
1415 const int global_security_token_;
1416 };
1417
1418 void HeapSnapshot::CutObjectsFromForeignSecurityContexts() {
1419 EdgesCutter cutter(GetGlobalSecurityToken());
1420 entries_.Apply(&cutter);
1421 } 1342 }
1422 1343
1423 1344
1424 int HeapSnapshot::GetGlobalSecurityToken() {
1425 return collection_->token_enumerator()->GetTokenId(
1426 Top::context()->global()->global_context()->security_token());
1427 }
1428
1429
1430 int HeapSnapshot::GetObjectSize(HeapObject* obj) { 1345 int HeapSnapshot::GetObjectSize(HeapObject* obj) {
1431 return obj->IsJSObject() ? 1346 return obj->IsJSObject() ?
1432 CalculateNetworkSize(JSObject::cast(obj)) : obj->Size(); 1347 CalculateNetworkSize(JSObject::cast(obj)) : obj->Size();
1433 } 1348 }
1434 1349
1435 1350
1436 int HeapSnapshot::GetObjectSecurityToken(HeapObject* obj) {
1437 if (obj->IsGlobalContext()) {
1438 return collection_->token_enumerator()->GetTokenId(
1439 Context::cast(obj)->security_token());
1440 } else {
1441 return TokenEnumerator::kNoSecurityToken;
1442 }
1443 }
1444
1445
1446 int HeapSnapshot::CalculateNetworkSize(JSObject* obj) { 1351 int HeapSnapshot::CalculateNetworkSize(JSObject* obj) {
1447 int size = obj->Size(); 1352 int size = obj->Size();
1448 // If 'properties' and 'elements' are non-empty (thus, non-shared), 1353 // If 'properties' and 'elements' are non-empty (thus, non-shared),
1449 // take their size into account. 1354 // take their size into account.
1450 if (FixedArray::cast(obj->properties())->length() != 0) { 1355 if (FixedArray::cast(obj->properties())->length() != 0) {
1451 size += obj->properties()->Size(); 1356 size += obj->properties()->Size();
1452 } 1357 }
1453 if (FixedArray::cast(obj->elements())->length() != 0) { 1358 if (FixedArray::cast(obj->elements())->length() != 0) {
1454 size += obj->elements()->Size(); 1359 size += obj->elements()->Size();
1455 } 1360 }
1456 // For functions, also account non-empty context and literals sizes. 1361 // For functions, also account non-empty context and literals sizes.
1457 if (obj->IsJSFunction()) { 1362 if (obj->IsJSFunction()) {
1458 JSFunction* f = JSFunction::cast(obj); 1363 JSFunction* f = JSFunction::cast(obj);
1459 if (f->unchecked_context()->IsContext()) { 1364 if (f->unchecked_context()->IsContext()) {
1460 size += f->context()->Size(); 1365 size += f->context()->Size();
1461 } 1366 }
1462 if (f->literals()->length() != 0) { 1367 if (f->literals()->length() != 0) {
1463 size += f->literals()->Size(); 1368 size += f->literals()->Size();
1464 } 1369 }
1465 } 1370 }
1466 return size; 1371 return size;
1467 } 1372 }
1468 1373
1469 1374
1470 class EntriesCollector { 1375 HeapSnapshotsDiff* HeapSnapshot::CompareWith(HeapSnapshot* snapshot) {
1471 public: 1376 return collection_->CompareSnapshots(this, snapshot);
1472 explicit EntriesCollector(List<HeapEntry*>* list) : list_(list) { } 1377 }
1473 void Apply(HeapEntry* entry) { 1378
1474 list_->Add(entry);
1475 }
1476 private:
1477 List<HeapEntry*>* list_;
1478 };
1479 1379
1480 template<class T> 1380 template<class T>
1481 static int SortByIds(const T* entry1_ptr, 1381 static int SortByIds(const T* entry1_ptr,
1482 const T* entry2_ptr) { 1382 const T* entry2_ptr) {
1483 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0; 1383 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0;
1484 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1; 1384 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1;
1485 } 1385 }
1486 1386
1487 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() { 1387 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() {
1488 if (sorted_entries_ != NULL) return sorted_entries_; 1388 if (!entries_sorted_) {
1489 sorted_entries_ = new List<HeapEntry*>(entries_.capacity()); 1389 entries_.Sort(SortByIds);
1490 EntriesCollector collector(sorted_entries_); 1390 entries_sorted_ = true;
1491 entries_.Apply(&collector); 1391 }
1492 sorted_entries_->Sort(SortByIds); 1392 return &entries_;
1493 return sorted_entries_;
1494 }
1495
1496
1497 HeapSnapshotsDiff* HeapSnapshot::CompareWith(HeapSnapshot* snapshot) {
1498 return collection_->CompareSnapshots(this, snapshot);
1499 } 1393 }
1500 1394
1501 1395
1502 void HeapSnapshot::Print(int max_depth) { 1396 void HeapSnapshot::Print(int max_depth) {
1503 root_.Print(max_depth, 0); 1397 root()->Print(max_depth, 0);
1504 } 1398 }
1505 1399
1506 1400
1507 HeapObjectsMap::HeapObjectsMap() 1401 HeapObjectsMap::HeapObjectsMap()
1508 : initial_fill_mode_(true), 1402 : initial_fill_mode_(true),
1509 next_id_(1), 1403 next_id_(1),
1510 entries_map_(AddressesMatch), 1404 entries_map_(AddressesMatch),
1511 entries_(new List<EntryInfo>()) { } 1405 entries_(new List<EntryInfo>()) { }
1512 1406
1513 1407
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 } 1522 }
1629 1523
1630 1524
1631 HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots( 1525 HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots(
1632 HeapSnapshot* snapshot1, 1526 HeapSnapshot* snapshot1,
1633 HeapSnapshot* snapshot2) { 1527 HeapSnapshot* snapshot2) {
1634 return comparator_.Compare(snapshot1, snapshot2); 1528 return comparator_.Compare(snapshot1, snapshot2);
1635 } 1529 }
1636 1530
1637 1531
1532 HeapEntriesMap::HeapEntriesMap()
1533 : entries_(HeapObjectsMatch),
1534 entries_count_(0),
1535 total_children_count_(0),
1536 total_retainers_count_(0) {
1537 }
1538
1539
1540 HeapEntriesMap::~HeapEntriesMap() {
1541 for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) {
1542 if (!IsAlias(p->value)) delete reinterpret_cast<EntryInfo*>(p->value);
1543 }
1544 }
1545
1546
1547 void HeapEntriesMap::Alias(HeapObject* from, HeapObject* to) {
1548 HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), true);
1549 HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false);
1550 if (from_cache_entry->value == NULL) {
1551 ASSERT(to_cache_entry != NULL);
1552 from_cache_entry->value = MakeAlias(to_cache_entry->value);
1553 }
1554 }
1555
1556
1557 HeapEntry* HeapEntriesMap::Map(HeapObject* object) {
1558 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false);
1559 if (cache_entry != NULL) {
1560 EntryInfo* entry_info =
1561 reinterpret_cast<EntryInfo*>(Unalias(cache_entry->value));
1562 return entry_info->entry;
1563 } else {
1564 return NULL;
1565 }
1566 }
1567
1568
1569 void HeapEntriesMap::Pair(HeapObject* object, HeapEntry* entry) {
1570 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), true);
1571 ASSERT(cache_entry->value == NULL);
1572 cache_entry->value = new EntryInfo(entry);
1573 ++entries_count_;
1574 }
1575
1576
1577 void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to,
1578 int* prev_children_count,
1579 int* prev_retainers_count) {
1580 HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), true);
1581 HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false);
1582 ASSERT(from_cache_entry != NULL);
1583 ASSERT(to_cache_entry != NULL);
1584 EntryInfo* from_entry_info =
1585 reinterpret_cast<EntryInfo*>(Unalias(from_cache_entry->value));
1586 EntryInfo* to_entry_info =
1587 reinterpret_cast<EntryInfo*>(Unalias(to_cache_entry->value));
1588 if (prev_children_count)
1589 *prev_children_count = from_entry_info->children_count;
1590 if (prev_retainers_count)
1591 *prev_retainers_count = to_entry_info->retainers_count;
1592 ++from_entry_info->children_count;
1593 ++to_entry_info->retainers_count;
1594 ++total_children_count_;
1595 ++total_retainers_count_;
1596 }
1597
1598
1599 template<class Visitor>
1600 void HeapEntriesMap::UpdateEntries(Visitor* visitor) {
1601 for (HashMap::Entry* p = entries_.Start();
1602 p != NULL;
1603 p = entries_.Next(p)) {
1604 if (!IsAlias(p->value)) {
1605 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
1606 entry_info->entry = visitor->GetEntry(
1607 reinterpret_cast<HeapObject*>(p->key),
1608 entry_info->children_count,
1609 entry_info->retainers_count);
1610 entry_info->children_count = 0;
1611 entry_info->retainers_count = 0;
1612 }
1613 }
1614 }
1615
1616
1638 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot) 1617 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot)
1639 : snapshot_(snapshot) { 1618 : snapshot_(snapshot),
1640 } 1619 collection_(snapshot->collection()),
1641 1620 filler_(NULL) {
1621 }
1622
1623
1624 HeapEntry *const
1625 HeapSnapshotGenerator::SnapshotFillerInterface::kHeapEntryPlaceholder =
1626 reinterpret_cast<HeapEntry*>(1);
1627
1628 class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface {
1629 public:
1630 explicit SnapshotCounter(HeapEntriesMap* entries)
1631 : entries_(entries) { }
1632 HeapEntry* AddEntry(HeapObject* obj) {
1633 entries_->Pair(obj, kHeapEntryPlaceholder);
1634 return kHeapEntryPlaceholder;
1635 }
1636 void SetElementReference(HeapObject* parent_obj,
1637 HeapEntry*,
1638 int,
1639 Object* child_obj,
1640 HeapEntry*) {
1641 entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
1642 }
1643 void SetNamedReference(HeapGraphEdge::Type,
1644 HeapObject* parent_obj,
1645 HeapEntry*,
1646 const char*,
1647 Object* child_obj,
1648 HeapEntry*) {
1649 entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
1650 }
1651 void SetRootReference(Object* child_obj, HeapEntry*) {
1652 entries_->CountReference(
1653 HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj));
1654 }
1655 private:
1656 HeapEntriesMap* entries_;
1657 };
1658
1659
1660 class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface {
1661 public:
1662 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
1663 : snapshot_(snapshot),
1664 collection_(snapshot->collection()),
1665 entries_(entries) { }
1666 HeapEntry* AddEntry(HeapObject* obj) {
1667 UNREACHABLE();
1668 return NULL;
1669 }
1670 void SetElementReference(HeapObject* parent_obj,
1671 HeapEntry* parent_entry,
1672 int index,
1673 Object* child_obj,
1674 HeapEntry* child_entry) {
1675 int child_index, retainer_index;
1676 entries_->CountReference(parent_obj, HeapObject::cast(child_obj),
1677 &child_index, &retainer_index);
1678 parent_entry->SetElementReference(
1679 child_index, index, child_entry, retainer_index);
1680 }
1681 void SetNamedReference(HeapGraphEdge::Type type,
1682 HeapObject* parent_obj,
1683 HeapEntry* parent_entry,
1684 const char* reference_name,
1685 Object* child_obj,
1686 HeapEntry* child_entry) {
1687 int child_index, retainer_index;
1688 entries_->CountReference(parent_obj, HeapObject::cast(child_obj),
1689 &child_index, &retainer_index);
1690 parent_entry->SetNamedReference(type,
1691 child_index,
1692 reference_name,
1693 child_entry,
1694 retainer_index);
1695 }
1696 void SetRootReference(Object* child_obj, HeapEntry* child_entry) {
1697 int child_index, retainer_index;
1698 entries_->CountReference(
1699 HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj),
1700 &child_index, &retainer_index);
1701 snapshot_->root()->SetElementReference(
1702 child_index, child_index + 1, child_entry, retainer_index);
1703 }
1704 private:
1705 HeapSnapshot* snapshot_;
1706 HeapSnapshotsCollection* collection_;
1707 HeapEntriesMap* entries_;
1708 };
1709
1710 class SnapshotAllocator {
1711 public:
1712 explicit SnapshotAllocator(HeapSnapshot* snapshot)
1713 : snapshot_(snapshot) { }
1714 HeapEntry* GetEntry(
1715 HeapObject* obj, int children_count, int retainers_count) {
1716 HeapEntry* entry =
1717 snapshot_->AddEntry(obj, children_count, retainers_count);
1718 ASSERT(entry != NULL);
1719 return entry;
1720 }
1721 private:
1722 HeapSnapshot* snapshot_;
1723 };
1642 1724
1643 void HeapSnapshotGenerator::GenerateSnapshot() { 1725 void HeapSnapshotGenerator::GenerateSnapshot() {
1644 AssertNoAllocation no_alloc; 1726 AssertNoAllocation no_alloc;
1645 1727
1646 // Iterate heap contents. 1728 // Pass 1. Iterate heap contents to count entries and references.
1647 HeapIterator iterator; 1729 SnapshotCounter counter(&entries_);
1648 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { 1730 filler_ = &counter;
1731 filler_->AddEntry(HeapSnapshot::kInternalRootObject);
1732 HeapIterator iterator1;
1733 for (HeapObject* obj = iterator1.next();
1734 obj != NULL;
1735 obj = iterator1.next()) {
1649 ExtractReferences(obj); 1736 ExtractReferences(obj);
1650 } 1737 }
1651 1738
1652 snapshot_->CutObjectsFromForeignSecurityContexts(); 1739 // Allocate and fill entries in the snapshot, allocate references.
1653 } 1740 snapshot_->AllocateEntries(entries_.entries_count(),
1741 entries_.total_children_count(),
1742 entries_.total_retainers_count());
1743 SnapshotAllocator allocator(snapshot_);
1744 entries_.UpdateEntries(&allocator);
1745
1746 // Pass 2. Fill references.
1747 SnapshotFiller filler(snapshot_, &entries_);
1748 filler_ = &filler;
1749 HeapIterator iterator2;
1750 for (HeapObject* obj = iterator2.next();
1751 obj != NULL;
1752 obj = iterator2.next()) {
1753 ExtractReferences(obj);
1754 }
1755 }
1756
1757
1758 HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) {
1759 if (!obj->IsHeapObject()) return NULL;
1760 HeapObject* object = HeapObject::cast(obj);
1761 HeapEntry* entry = entries_.Map(object);
1762
1763 // A new entry.
1764 if (entry == NULL) {
1765 if (obj->IsJSGlobalPropertyCell()) {
1766 Object* cell_target = JSGlobalPropertyCell::cast(obj)->value();
1767 entry = GetEntry(cell_target);
1768 // If GPC references an object that we have interest in (see
1769 // HeapSnapshot::AddEntry, WillAddEntry), add the object. We
1770 // don't store HeapEntries for GPCs. Instead, we make our hash
1771 // map to point to object's HeapEntry by GPCs address.
1772 if (entry != NULL) {
1773 entries_.Alias(object, HeapObject::cast(cell_target));
1774 }
1775 return entry;
1776 }
1777
1778 if (snapshot_->WillAddEntry(object)) entry = filler_->AddEntry(object);
1779 }
1780
1781 return entry;
1782 }
1783
1784
1785 int HeapSnapshotGenerator::GetGlobalSecurityToken() {
1786 return collection_->token_enumerator()->GetTokenId(
1787 Top::context()->global()->global_context()->security_token());
1788 }
1789
1790
1791 int HeapSnapshotGenerator::GetObjectSecurityToken(HeapObject* obj) {
1792 if (obj->IsGlobalContext()) {
1793 return collection_->token_enumerator()->GetTokenId(
1794 Context::cast(obj)->security_token());
1795 } else {
1796 return TokenEnumerator::kNoSecurityToken;
1797 }
1798 }
1799
1800
1801 class IndexedReferencesExtractor : public ObjectVisitor {
1802 public:
1803 IndexedReferencesExtractor(HeapSnapshotGenerator* generator,
1804 HeapObject* parent_obj,
1805 HeapEntry* parent_entry)
1806 : generator_(generator),
1807 parent_obj_(parent_obj),
1808 parent_(parent_entry),
1809 next_index_(1) {
1810 }
1811
1812 void VisitPointer(Object** o) {
1813 generator_->SetElementReference(parent_obj_, parent_, next_index_++, *o);
1814 }
1815
1816 void VisitPointers(Object** start, Object** end) {
1817 for (Object** p = start; p < end; p++) VisitPointer(p);
1818 }
1819
1820 private:
1821 HeapSnapshotGenerator* generator_;
1822 HeapObject* parent_obj_;
1823 HeapEntry* parent_;
1824 int next_index_;
1825 };
1654 1826
1655 1827
1656 void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) { 1828 void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
1657 HeapEntry* entry = snapshot_->GetEntry(obj); 1829 // We need to reference JS global objects from snapshot's root.
1658 if (entry == NULL) return; 1830 // We also need to only include global objects from the current
1659 if (entry->visited()) return; 1831 // security context. And we don't want to add the global proxy,
1832 // as we don't have a special type for it.
1833 if (obj->IsJSGlobalProxy()) {
1834 int global_security_token = GetGlobalSecurityToken();
1835 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj);
1836 int object_security_token =
1837 collection_->token_enumerator()->GetTokenId(
1838 Context::cast(proxy->context())->security_token());
1839 if (object_security_token == TokenEnumerator::kNoSecurityToken
1840 || object_security_token == global_security_token) {
1841 SetRootReference(proxy->map()->prototype());
1842 }
1843 return;
1844 }
1845
1846 HeapEntry* entry = GetEntry(obj);
1847 if (entry == NULL) return; // No interest in this object.
1660 1848
1661 if (obj->IsJSObject()) { 1849 if (obj->IsJSObject()) {
1662 JSObject* js_obj = JSObject::cast(obj); 1850 JSObject* js_obj = JSObject::cast(obj);
1663 ExtractClosureReferences(js_obj, entry); 1851 ExtractClosureReferences(js_obj, entry);
1664 ExtractPropertyReferences(js_obj, entry); 1852 ExtractPropertyReferences(js_obj, entry);
1665 ExtractElementReferences(js_obj, entry); 1853 ExtractElementReferences(js_obj, entry);
1666 snapshot_->SetPropertyReference( 1854 SetPropertyReference(
1667 entry, Heap::prototype_symbol(), js_obj->map()->prototype()); 1855 obj, entry, Heap::prototype_symbol(), js_obj->map()->prototype());
1668 } else if (obj->IsJSGlobalPropertyCell()) {
1669 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(obj);
1670 snapshot_->SetElementReference(entry, 0, cell->value());
1671 } else if (obj->IsString()) { 1856 } else if (obj->IsString()) {
1672 if (obj->IsConsString()) { 1857 if (obj->IsConsString()) {
1673 ConsString* cs = ConsString::cast(obj); 1858 ConsString* cs = ConsString::cast(obj);
1674 snapshot_->SetElementReference(entry, 0, cs->first()); 1859 SetElementReference(obj, entry, 0, cs->first());
1675 snapshot_->SetElementReference(entry, 1, cs->second()); 1860 SetElementReference(obj, entry, 1, cs->second());
1676 } 1861 }
1677 } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) { 1862 } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
1678 IndexedReferencesExtractor refs_extractor(snapshot_, entry); 1863 IndexedReferencesExtractor refs_extractor(this, obj, entry);
1679 obj->Iterate(&refs_extractor); 1864 obj->Iterate(&refs_extractor);
1680 } else if (obj->IsFixedArray()) { 1865 } else if (obj->IsFixedArray()) {
1681 IndexedReferencesExtractor refs_extractor(snapshot_, entry); 1866 IndexedReferencesExtractor refs_extractor(this, obj, entry);
1682 obj->Iterate(&refs_extractor); 1867 obj->Iterate(&refs_extractor);
1683 } 1868 }
1684 entry->MarkAsVisited(); 1869 }
1685 } 1870
1686 1871
1687
1688 void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj, 1872 void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj,
1689 HeapEntry* entry) { 1873 HeapEntry* entry) {
1690 if (js_obj->IsJSFunction()) { 1874 if (js_obj->IsJSFunction()) {
1691 HandleScope hs; 1875 HandleScope hs;
1692 JSFunction* func = JSFunction::cast(js_obj); 1876 JSFunction* func = JSFunction::cast(js_obj);
1693 Context* context = func->context(); 1877 Context* context = func->context();
1694 ZoneScope zscope(DELETE_ON_EXIT); 1878 ZoneScope zscope(DELETE_ON_EXIT);
1695 SerializedScopeInfo* serialized_scope_info = 1879 SerializedScopeInfo* serialized_scope_info =
1696 context->closure()->shared()->scope_info(); 1880 context->closure()->shared()->scope_info();
1697 ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(serialized_scope_info); 1881 ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(serialized_scope_info);
1698 int locals_number = zone_scope_info.NumberOfLocals(); 1882 int locals_number = zone_scope_info.NumberOfLocals();
1699 for (int i = 0; i < locals_number; ++i) { 1883 for (int i = 0; i < locals_number; ++i) {
1700 String* local_name = *zone_scope_info.LocalName(i); 1884 String* local_name = *zone_scope_info.LocalName(i);
1701 int idx = serialized_scope_info->ContextSlotIndex(local_name, NULL); 1885 int idx = serialized_scope_info->ContextSlotIndex(local_name, NULL);
1702 if (idx >= 0 && idx < context->length()) { 1886 if (idx >= 0 && idx < context->length()) {
1703 snapshot_->SetClosureReference(entry, local_name, context->get(idx)); 1887 SetClosureReference(js_obj, entry, local_name, context->get(idx));
1704 } 1888 }
1705 } 1889 }
1706 snapshot_->SetInternalReference(entry, "code", func->shared()); 1890 SetInternalReference(js_obj, entry, "code", func->shared());
1707 } 1891 }
1708 } 1892 }
1709 1893
1710 1894
1711 void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj, 1895 void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj,
1712 HeapEntry* entry) { 1896 HeapEntry* entry) {
1713 if (js_obj->HasFastProperties()) { 1897 if (js_obj->HasFastProperties()) {
1714 DescriptorArray* descs = js_obj->map()->instance_descriptors(); 1898 DescriptorArray* descs = js_obj->map()->instance_descriptors();
1715 for (int i = 0; i < descs->number_of_descriptors(); i++) { 1899 for (int i = 0; i < descs->number_of_descriptors(); i++) {
1716 switch (descs->GetType(i)) { 1900 switch (descs->GetType(i)) {
1717 case FIELD: { 1901 case FIELD: {
1718 int index = descs->GetFieldIndex(i); 1902 int index = descs->GetFieldIndex(i);
1719 snapshot_->SetPropertyReference( 1903 SetPropertyReference(
1720 entry, descs->GetKey(i), js_obj->FastPropertyAt(index)); 1904 js_obj, entry, descs->GetKey(i), js_obj->FastPropertyAt(index));
1721 break; 1905 break;
1722 } 1906 }
1723 case CONSTANT_FUNCTION: 1907 case CONSTANT_FUNCTION:
1724 snapshot_->SetPropertyReference( 1908 SetPropertyReference(
1725 entry, descs->GetKey(i), descs->GetConstantFunction(i)); 1909 js_obj, entry, descs->GetKey(i), descs->GetConstantFunction(i));
1726 break; 1910 break;
1727 default: ; 1911 default: ;
1728 } 1912 }
1729 } 1913 }
1730 } else { 1914 } else {
1731 StringDictionary* dictionary = js_obj->property_dictionary(); 1915 StringDictionary* dictionary = js_obj->property_dictionary();
1732 int length = dictionary->Capacity(); 1916 int length = dictionary->Capacity();
1733 for (int i = 0; i < length; ++i) { 1917 for (int i = 0; i < length; ++i) {
1734 Object* k = dictionary->KeyAt(i); 1918 Object* k = dictionary->KeyAt(i);
1735 if (dictionary->IsKey(k)) { 1919 if (dictionary->IsKey(k)) {
1736 snapshot_->SetPropertyReference( 1920 SetPropertyReference(
1737 entry, String::cast(k), dictionary->ValueAt(i)); 1921 js_obj, entry, String::cast(k), dictionary->ValueAt(i));
1738 } 1922 }
1739 } 1923 }
1740 } 1924 }
1741 } 1925 }
1742 1926
1743 1927
1744 void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj, 1928 void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj,
1745 HeapEntry* entry) { 1929 HeapEntry* entry) {
1746 if (js_obj->HasFastElements()) { 1930 if (js_obj->HasFastElements()) {
1747 FixedArray* elements = FixedArray::cast(js_obj->elements()); 1931 FixedArray* elements = FixedArray::cast(js_obj->elements());
1748 int length = js_obj->IsJSArray() ? 1932 int length = js_obj->IsJSArray() ?
1749 Smi::cast(JSArray::cast(js_obj)->length())->value() : 1933 Smi::cast(JSArray::cast(js_obj)->length())->value() :
1750 elements->length(); 1934 elements->length();
1751 for (int i = 0; i < length; ++i) { 1935 for (int i = 0; i < length; ++i) {
1752 if (!elements->get(i)->IsTheHole()) { 1936 if (!elements->get(i)->IsTheHole()) {
1753 snapshot_->SetElementReference(entry, i, elements->get(i)); 1937 SetElementReference(js_obj, entry, i, elements->get(i));
1754 } 1938 }
1755 } 1939 }
1756 } else if (js_obj->HasDictionaryElements()) { 1940 } else if (js_obj->HasDictionaryElements()) {
1757 NumberDictionary* dictionary = js_obj->element_dictionary(); 1941 NumberDictionary* dictionary = js_obj->element_dictionary();
1758 int length = dictionary->Capacity(); 1942 int length = dictionary->Capacity();
1759 for (int i = 0; i < length; ++i) { 1943 for (int i = 0; i < length; ++i) {
1760 Object* k = dictionary->KeyAt(i); 1944 Object* k = dictionary->KeyAt(i);
1761 if (dictionary->IsKey(k)) { 1945 if (dictionary->IsKey(k)) {
1762 ASSERT(k->IsNumber()); 1946 ASSERT(k->IsNumber());
1763 uint32_t index = static_cast<uint32_t>(k->Number()); 1947 uint32_t index = static_cast<uint32_t>(k->Number());
1764 snapshot_->SetElementReference(entry, index, dictionary->ValueAt(i)); 1948 SetElementReference(js_obj, entry, index, dictionary->ValueAt(i));
1765 } 1949 }
1766 } 1950 }
1767 } 1951 }
1768 } 1952 }
1769 1953
1770 1954
1955 void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj,
1956 HeapEntry* parent_entry,
1957 String* reference_name,
1958 Object* child_obj) {
1959 HeapEntry* child_entry = GetEntry(child_obj);
1960 if (child_entry != NULL) {
1961 filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
1962 parent_obj,
1963 parent_entry,
1964 collection_->GetName(reference_name),
1965 child_obj,
1966 child_entry);
1967 }
1968 }
1969
1970
1971 void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj,
1972 HeapEntry* parent_entry,
1973 int index,
1974 Object* child_obj) {
1975 HeapEntry* child_entry = GetEntry(child_obj);
1976 if (child_entry != NULL) {
1977 filler_->SetElementReference(
1978 parent_obj, parent_entry, index, child_obj, child_entry);
1979 }
1980 }
1981
1982
1983 void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
1984 HeapEntry* parent_entry,
1985 const char* reference_name,
1986 Object* child_obj) {
1987 HeapEntry* child_entry = GetEntry(child_obj);
1988 if (child_entry != NULL) {
1989 filler_->SetNamedReference(HeapGraphEdge::kInternal,
1990 parent_obj,
1991 parent_entry,
1992 reference_name,
1993 child_obj,
1994 child_entry);
1995 }
1996 }
1997
1998
1999 void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
2000 HeapEntry* parent_entry,
2001 String* reference_name,
2002 Object* child_obj) {
2003 HeapEntry* child_entry = GetEntry(child_obj);
2004 if (child_entry != NULL) {
2005 filler_->SetNamedReference(HeapGraphEdge::kProperty,
2006 parent_obj,
2007 parent_entry,
2008 collection_->GetName(reference_name),
2009 child_obj,
2010 child_entry);
2011 }
2012 }
2013
2014
2015 void HeapSnapshotGenerator::SetRootReference(Object* child_obj) {
2016 HeapEntry* child_entry = GetEntry(child_obj);
2017 ASSERT(child_entry != NULL);
2018 filler_->SetRootReference(child_obj, child_entry);
2019 }
2020
2021
2022 void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) {
2023 raw_additions_root_ =
2024 NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0));
2025 additions_root()->Init(snapshot2_, additions_count, 0);
2026 raw_deletions_root_ =
2027 NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0));
2028 deletions_root()->Init(snapshot1_, deletions_count, 0);
2029 }
2030
2031
1771 static void DeleteHeapSnapshotsDiff(HeapSnapshotsDiff** diff_ptr) { 2032 static void DeleteHeapSnapshotsDiff(HeapSnapshotsDiff** diff_ptr) {
1772 delete *diff_ptr; 2033 delete *diff_ptr;
1773 } 2034 }
1774 2035
1775 HeapSnapshotsComparator::~HeapSnapshotsComparator() { 2036 HeapSnapshotsComparator::~HeapSnapshotsComparator() {
1776 diffs_.Iterate(DeleteHeapSnapshotsDiff); 2037 diffs_.Iterate(DeleteHeapSnapshotsDiff);
1777 } 2038 }
1778 2039
1779 2040
1780 HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1, 2041 HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
1781 HeapSnapshot* snapshot2) { 2042 HeapSnapshot* snapshot2) {
1782 HeapSnapshotsDiff* diff = new HeapSnapshotsDiff(snapshot1, snapshot2);
1783 diffs_.Add(diff);
1784 List<HeapEntry*>* entries1 = snapshot1->GetSortedEntriesList(); 2043 List<HeapEntry*>* entries1 = snapshot1->GetSortedEntriesList();
1785 List<HeapEntry*>* entries2 = snapshot2->GetSortedEntriesList(); 2044 List<HeapEntry*>* entries2 = snapshot2->GetSortedEntriesList();
1786 int i = 0, j = 0; 2045 int i = 0, j = 0;
1787 List<HeapEntry*> added_entries, deleted_entries; 2046 List<HeapEntry*> added_entries, deleted_entries;
1788 while (i < entries1->length() && j < entries2->length()) { 2047 while (i < entries1->length() && j < entries2->length()) {
1789 uint64_t id1 = entries1->at(i)->id(); 2048 uint64_t id1 = entries1->at(i)->id();
1790 uint64_t id2 = entries2->at(j)->id(); 2049 uint64_t id2 = entries2->at(j)->id();
1791 if (id1 == id2) { 2050 if (id1 == id2) {
1792 i++; 2051 i++;
1793 j++; 2052 j++;
1794 } else if (id1 < id2) { 2053 } else if (id1 < id2) {
1795 HeapEntry* entry = entries1->at(i++); 2054 HeapEntry* entry = entries1->at(i++);
1796 deleted_entries.Add(entry); 2055 deleted_entries.Add(entry);
1797 } else { 2056 } else {
1798 HeapEntry* entry = entries2->at(j++); 2057 HeapEntry* entry = entries2->at(j++);
1799 added_entries.Add(entry); 2058 added_entries.Add(entry);
1800 } 2059 }
1801 } 2060 }
1802 while (i < entries1->length()) { 2061 while (i < entries1->length()) {
1803 HeapEntry* entry = entries1->at(i++); 2062 HeapEntry* entry = entries1->at(i++);
1804 deleted_entries.Add(entry); 2063 deleted_entries.Add(entry);
1805 } 2064 }
1806 while (j < entries2->length()) { 2065 while (j < entries2->length()) {
1807 HeapEntry* entry = entries2->at(j++); 2066 HeapEntry* entry = entries2->at(j++);
1808 added_entries.Add(entry); 2067 added_entries.Add(entry);
1809 } 2068 }
1810 2069
1811 snapshot1->ClearPaint(); 2070 snapshot1->ClearPaint();
1812 snapshot1->root()->PaintAllReachable(); 2071 snapshot1->root()->PaintAllReachable();
2072 snapshot2->ClearPaint();
2073 snapshot2->root()->PaintAllReachable();
2074 int reachable_deleted_entries = 0, reachable_added_entries = 0;
2075 for (int i = 0; i < deleted_entries.length(); ++i) {
2076 HeapEntry* entry = deleted_entries[i];
2077 if (entry->painted_reachable()) ++reachable_deleted_entries;
2078 }
2079 for (int i = 0; i < added_entries.length(); ++i) {
2080 HeapEntry* entry = added_entries[i];
2081 if (entry->painted_reachable()) ++reachable_added_entries;
2082 }
2083
2084 HeapSnapshotsDiff* diff = new HeapSnapshotsDiff(snapshot1, snapshot2);
2085 diffs_.Add(diff);
2086 diff->CreateRoots(reachable_added_entries, reachable_deleted_entries);
2087
2088 int del_child_index = 0, deleted_entry_index = 1;
1813 for (int i = 0; i < deleted_entries.length(); ++i) { 2089 for (int i = 0; i < deleted_entries.length(); ++i) {
1814 HeapEntry* entry = deleted_entries[i]; 2090 HeapEntry* entry = deleted_entries[i];
1815 if (entry->painted_reachable()) 2091 if (entry->painted_reachable())
1816 diff->AddDeletedEntry(entry); 2092 diff->AddDeletedEntry(del_child_index++, deleted_entry_index++, entry);
1817 } 2093 }
1818 snapshot2->ClearPaint(); 2094 int add_child_index = 0, added_entry_index = 1;
1819 snapshot2->root()->PaintAllReachable();
1820 for (int i = 0; i < added_entries.length(); ++i) { 2095 for (int i = 0; i < added_entries.length(); ++i) {
1821 HeapEntry* entry = added_entries[i]; 2096 HeapEntry* entry = added_entries[i];
1822 if (entry->painted_reachable()) 2097 if (entry->painted_reachable())
1823 diff->AddAddedEntry(entry); 2098 diff->AddAddedEntry(add_child_index++, added_entry_index++, entry);
1824 } 2099 }
1825 return diff; 2100 return diff;
1826 } 2101 }
1827 2102
1828 } } // namespace v8::internal 2103 } } // namespace v8::internal
1829 2104
1830 #endif // ENABLE_LOGGING_AND_PROFILING 2105 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698