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

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

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 9 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 | Annotate | Revision Log
« 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 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #ifdef ENABLE_LOGGING_AND_PROFILING 28 #ifdef ENABLE_LOGGING_AND_PROFILING
29 29
30 #include "v8.h" 30 #include "v8.h"
31 #include "global-handles.h" 31 #include "global-handles.h"
32 #include "heap-profiler.h"
32 #include "scopeinfo.h" 33 #include "scopeinfo.h"
33 #include "top.h" 34 #include "top.h"
34 #include "unicode.h" 35 #include "unicode.h"
35 #include "zone-inl.h" 36 #include "zone-inl.h"
36 37
37 #include "profile-generator-inl.h" 38 #include "profile-generator-inl.h"
38 39
39 namespace v8 { 40 namespace v8 {
40 namespace internal { 41 namespace internal {
41 42
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 } 88 }
88 } 89 }
89 } 90 }
90 91
91 92
92 StringsStorage::StringsStorage() 93 StringsStorage::StringsStorage()
93 : names_(StringsMatch) { 94 : names_(StringsMatch) {
94 } 95 }
95 96
96 97
97 static void DeleteIndexName(char** name_ptr) {
98 DeleteArray(*name_ptr);
99 }
100
101
102 StringsStorage::~StringsStorage() { 98 StringsStorage::~StringsStorage() {
103 for (HashMap::Entry* p = names_.Start(); 99 for (HashMap::Entry* p = names_.Start();
104 p != NULL; 100 p != NULL;
105 p = names_.Next(p)) { 101 p = names_.Next(p)) {
106 DeleteArray(reinterpret_cast<const char*>(p->value)); 102 DeleteArray(reinterpret_cast<const char*>(p->value));
107 } 103 }
108 index_names_.Iterate(DeleteIndexName); 104 }
105
106
107 const char* StringsStorage::GetCopy(const char* src) {
108 int len = static_cast<int>(strlen(src));
109 Vector<char> dst = Vector<char>::New(len + 1);
110 OS::StrNCpy(dst, src, len);
111 dst[len] = '\0';
112 uint32_t hash = HashSequentialString(dst.start(), len);
113 return AddOrDisposeString(dst.start(), hash);
114 }
115
116
117 const char* StringsStorage::GetFormatted(const char* format, ...) {
118 va_list args;
119 va_start(args, format);
120 const char* result = GetVFormatted(format, args);
121 va_end(args);
122 return result;
123 }
124
125
126 const char* StringsStorage::AddOrDisposeString(char* str, uint32_t hash) {
127 HashMap::Entry* cache_entry = names_.Lookup(str, hash, true);
128 if (cache_entry->value == NULL) {
129 // New entry added.
130 cache_entry->value = str;
131 } else {
132 DeleteArray(str);
133 }
134 return reinterpret_cast<const char*>(cache_entry->value);
135 }
136
137
138 const char* StringsStorage::GetVFormatted(const char* format, va_list args) {
139 Vector<char> str = Vector<char>::New(1024);
140 int len = OS::VSNPrintF(str, format, args);
141 if (len == -1) {
142 DeleteArray(str.start());
143 return format;
144 }
145 uint32_t hash = HashSequentialString(str.start(), len);
146 return AddOrDisposeString(str.start(), hash);
109 } 147 }
110 148
111 149
112 const char* StringsStorage::GetName(String* name) { 150 const char* StringsStorage::GetName(String* name) {
113 if (name->IsString()) { 151 if (name->IsString()) {
114 char* c_name = 152 return AddOrDisposeString(
115 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); 153 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(),
116 HashMap::Entry* cache_entry = names_.Lookup(c_name, name->Hash(), true); 154 name->Hash());
117 if (cache_entry->value == NULL) {
118 // New entry added.
119 cache_entry->value = c_name;
120 } else {
121 DeleteArray(c_name);
122 }
123 return reinterpret_cast<const char*>(cache_entry->value);
124 } 155 }
125 return ""; 156 return "";
126 } 157 }
127 158
128 159
129 const char* StringsStorage::GetName(int index) { 160 const char* StringsStorage::GetName(int index) {
130 ASSERT(index >= 0); 161 return GetFormatted("%d", index);
131 if (index_names_.length() <= index) {
132 index_names_.AddBlock(
133 NULL, index - index_names_.length() + 1);
134 }
135 if (index_names_[index] == NULL) {
136 const int kMaximumNameLength = 32;
137 char* name = NewArray<char>(kMaximumNameLength);
138 OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", index);
139 index_names_[index] = name;
140 }
141 return index_names_[index];
142 } 162 }
143 163
144 164
145 const char* CodeEntry::kEmptyNamePrefix = ""; 165 const char* CodeEntry::kEmptyNamePrefix = "";
146 166
147 167
148 void CodeEntry::CopyData(const CodeEntry& source) { 168 void CodeEntry::CopyData(const CodeEntry& source) {
149 tag_ = source.tag_; 169 tag_ = source.tag_;
150 name_prefix_ = source.name_prefix_; 170 name_prefix_ = source.name_prefix_;
151 name_ = source.name_; 171 name_ = source.name_;
152 resource_name_ = source.resource_name_; 172 resource_name_ = source.resource_name_;
153 line_number_ = source.line_number_; 173 line_number_ = source.line_number_;
154 } 174 }
155 175
156 176
157 uint32_t CodeEntry::GetCallUid() const { 177 uint32_t CodeEntry::GetCallUid() const {
158 uint32_t hash = ComputeIntegerHash(tag_); 178 uint32_t hash = ComputeIntegerHash(tag_);
159 hash ^= ComputeIntegerHash( 179 if (shared_id_ != 0) {
160 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_))); 180 hash ^= ComputeIntegerHash(
161 hash ^= ComputeIntegerHash( 181 static_cast<uint32_t>(shared_id_));
162 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_))); 182 } else {
163 hash ^= ComputeIntegerHash( 183 hash ^= ComputeIntegerHash(
164 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(resource_name_))); 184 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_)));
165 hash ^= ComputeIntegerHash(line_number_); 185 hash ^= ComputeIntegerHash(
186 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_)));
187 hash ^= ComputeIntegerHash(
188 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(resource_name_)));
189 hash ^= ComputeIntegerHash(line_number_);
190 }
166 return hash; 191 return hash;
167 } 192 }
168 193
169 194
170 bool CodeEntry::IsSameAs(CodeEntry* entry) const { 195 bool CodeEntry::IsSameAs(CodeEntry* entry) const {
171 return this == entry 196 return this == entry
172 || (tag_ == entry->tag_ 197 || (tag_ == entry->tag_
173 && name_prefix_ == entry->name_prefix_ 198 && shared_id_ == entry->shared_id_
174 && name_ == entry->name_ 199 && (shared_id_ != 0
175 && resource_name_ == entry->resource_name_ 200 || (name_prefix_ == entry->name_prefix_
176 && line_number_ == entry->line_number_); 201 && name_ == entry->name_
202 && resource_name_ == entry->resource_name_
203 && line_number_ == entry->line_number_)));
177 } 204 }
178 205
179 206
180 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { 207 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
181 HashMap::Entry* map_entry = 208 HashMap::Entry* map_entry =
182 children_.Lookup(entry, CodeEntryHash(entry), false); 209 children_.Lookup(entry, CodeEntryHash(entry), false);
183 return map_entry != NULL ? 210 return map_entry != NULL ?
184 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; 211 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL;
185 } 212 }
186 213
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 478
452 479
453 void CpuProfile::Print() { 480 void CpuProfile::Print() {
454 OS::Print("[Top down]:\n"); 481 OS::Print("[Top down]:\n");
455 top_down_.Print(); 482 top_down_.Print();
456 OS::Print("[Bottom up]:\n"); 483 OS::Print("[Bottom up]:\n");
457 bottom_up_.Print(); 484 bottom_up_.Print();
458 } 485 }
459 486
460 487
488 CodeEntry* const CodeMap::kSharedFunctionCodeEntry = NULL;
461 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL; 489 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL;
462 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue = 490 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue =
463 CodeMap::CodeEntryInfo(NULL, 0); 491 CodeMap::CodeEntryInfo(NULL, 0);
464 492
465 493
466 void CodeMap::AddAlias(Address start, CodeEntry* entry, Address code_start) {
467 CodeTree::Locator locator;
468 if (tree_.Find(code_start, &locator)) {
469 const CodeEntryInfo& code_info = locator.value();
470 if (tree_.Insert(start, &locator)) {
471 entry->CopyData(*code_info.entry);
472 locator.set_value(CodeEntryInfo(entry, code_info.size));
473 }
474 }
475 }
476
477
478 CodeEntry* CodeMap::FindEntry(Address addr) { 494 CodeEntry* CodeMap::FindEntry(Address addr) {
479 CodeTree::Locator locator; 495 CodeTree::Locator locator;
480 if (tree_.FindGreatestLessThan(addr, &locator)) { 496 if (tree_.FindGreatestLessThan(addr, &locator)) {
481 // locator.key() <= addr. Need to check that addr is within entry. 497 // locator.key() <= addr. Need to check that addr is within entry.
482 const CodeEntryInfo& entry = locator.value(); 498 const CodeEntryInfo& entry = locator.value();
483 if (addr < (locator.key() + entry.size)) 499 if (addr < (locator.key() + entry.size))
484 return entry.entry; 500 return entry.entry;
485 } 501 }
486 return NULL; 502 return NULL;
487 } 503 }
488 504
489 505
506 int CodeMap::GetSharedId(Address addr) {
507 CodeTree::Locator locator;
508 // For shared function entries, 'size' field is used to store their IDs.
509 if (tree_.Find(addr, &locator)) {
510 const CodeEntryInfo& entry = locator.value();
511 ASSERT(entry.entry == kSharedFunctionCodeEntry);
512 return entry.size;
513 } else {
514 tree_.Insert(addr, &locator);
515 int id = next_shared_id_++;
516 locator.set_value(CodeEntryInfo(kSharedFunctionCodeEntry, id));
517 return id;
518 }
519 }
520
521
490 void CodeMap::CodeTreePrinter::Call( 522 void CodeMap::CodeTreePrinter::Call(
491 const Address& key, const CodeMap::CodeEntryInfo& value) { 523 const Address& key, const CodeMap::CodeEntryInfo& value) {
492 OS::Print("%p %5d %s\n", key, value.size, value.entry->name()); 524 OS::Print("%p %5d %s\n", key, value.size, value.entry->name());
493 } 525 }
494 526
495 527
496 void CodeMap::Print() { 528 void CodeMap::Print() {
497 CodeTreePrinter printer; 529 CodeTreePrinter printer;
498 tree_.ForEach(&printer); 530 tree_.ForEach(&printer);
499 } 531 }
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 "args_count: ", 740 "args_count: ",
709 GetName(args_count), 741 GetName(args_count),
710 "", 742 "",
711 v8::CpuProfileNode::kNoLineNumberInfo, 743 v8::CpuProfileNode::kNoLineNumberInfo,
712 TokenEnumerator::kInheritsSecurityToken); 744 TokenEnumerator::kInheritsSecurityToken);
713 code_entries_.Add(entry); 745 code_entries_.Add(entry);
714 return entry; 746 return entry;
715 } 747 }
716 748
717 749
718 CodeEntry* CpuProfilesCollection::NewCodeEntry(int security_token_id) {
719 CodeEntry* entry = new CodeEntry(security_token_id);
720 code_entries_.Add(entry);
721 return entry;
722 }
723
724
725 void CpuProfilesCollection::AddPathToCurrentProfiles( 750 void CpuProfilesCollection::AddPathToCurrentProfiles(
726 const Vector<CodeEntry*>& path) { 751 const Vector<CodeEntry*>& path) {
727 // As starting / stopping profiles is rare relatively to this 752 // As starting / stopping profiles is rare relatively to this
728 // method, we don't bother minimizing the duration of lock holding, 753 // method, we don't bother minimizing the duration of lock holding,
729 // e.g. copying contents of the list to a local vector. 754 // e.g. copying contents of the list to a local vector.
730 current_profiles_semaphore_->Wait(); 755 current_profiles_semaphore_->Wait();
731 for (int i = 0; i < current_profiles_.length(); ++i) { 756 for (int i = 0; i < current_profiles_.length(); ++i) {
732 current_profiles_[i]->AddPath(path); 757 current_profiles_[i]->AddPath(path);
733 } 758 }
734 current_profiles_semaphore_->Signal(); 759 current_profiles_semaphore_->Signal();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 void ProfileGenerator::RecordTickSample(const TickSample& sample) { 802 void ProfileGenerator::RecordTickSample(const TickSample& sample) {
778 // Allocate space for stack frames + pc + function + vm-state. 803 // Allocate space for stack frames + pc + function + vm-state.
779 ScopedVector<CodeEntry*> entries(sample.frames_count + 3); 804 ScopedVector<CodeEntry*> entries(sample.frames_count + 3);
780 // As actual number of decoded code entries may vary, initialize 805 // As actual number of decoded code entries may vary, initialize
781 // entries vector with NULL values. 806 // entries vector with NULL values.
782 CodeEntry** entry = entries.start(); 807 CodeEntry** entry = entries.start();
783 memset(entry, 0, entries.length() * sizeof(*entry)); 808 memset(entry, 0, entries.length() * sizeof(*entry));
784 if (sample.pc != NULL) { 809 if (sample.pc != NULL) {
785 *entry++ = code_map_.FindEntry(sample.pc); 810 *entry++ = code_map_.FindEntry(sample.pc);
786 811
787 if (sample.function != NULL) { 812 if (sample.tos != NULL) {
788 *entry = code_map_.FindEntry(sample.function); 813 *entry = code_map_.FindEntry(sample.tos);
789 if (*entry != NULL && !(*entry)->is_js_function()) { 814 if (*entry != NULL && !(*entry)->is_js_function()) {
790 *entry = NULL; 815 *entry = NULL;
791 } else {
792 CodeEntry* pc_entry = *entries.start();
793 if (pc_entry == NULL) {
794 *entry = NULL;
795 } else if (pc_entry->is_js_function()) {
796 // Use function entry in favor of pc entry, as function
797 // entry has security token.
798 *entries.start() = NULL;
799 }
800 } 816 }
801 entry++; 817 entry++;
802 } 818 }
803 819
804 for (const Address *stack_pos = sample.stack, 820 for (const Address *stack_pos = sample.stack,
805 *stack_end = stack_pos + sample.frames_count; 821 *stack_end = stack_pos + sample.frames_count;
806 stack_pos != stack_end; 822 stack_pos != stack_end;
807 ++stack_pos) { 823 ++stack_pos) {
808 *entry++ = code_map_.FindEntry(*stack_pos); 824 *entry++ = code_map_.FindEntry(*stack_pos);
809 } 825 }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 const char* HeapEntry::TypeAsString() { 1022 const char* HeapEntry::TypeAsString() {
1007 switch (type()) { 1023 switch (type()) {
1008 case kHidden: return "/hidden/"; 1024 case kHidden: return "/hidden/";
1009 case kObject: return "/object/"; 1025 case kObject: return "/object/";
1010 case kClosure: return "/closure/"; 1026 case kClosure: return "/closure/";
1011 case kString: return "/string/"; 1027 case kString: return "/string/";
1012 case kCode: return "/code/"; 1028 case kCode: return "/code/";
1013 case kArray: return "/array/"; 1029 case kArray: return "/array/";
1014 case kRegExp: return "/regexp/"; 1030 case kRegExp: return "/regexp/";
1015 case kHeapNumber: return "/number/"; 1031 case kHeapNumber: return "/number/";
1032 case kNative: return "/native/";
1016 default: return "???"; 1033 default: return "???";
1017 } 1034 }
1018 } 1035 }
1019 1036
1020 1037
1021 int HeapEntry::EntriesSize(int entries_count, 1038 int HeapEntry::EntriesSize(int entries_count,
1022 int children_count, 1039 int children_count,
1023 int retainers_count) { 1040 int retainers_count) {
1024 return sizeof(HeapEntry) * entries_count // NOLINT 1041 return sizeof(HeapEntry) * entries_count // NOLINT
1025 + sizeof(HeapGraphEdge) * children_count // NOLINT 1042 + sizeof(HeapGraphEdge) * children_count // NOLINT
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1174 break; 1191 break;
1175 default: 1192 default:
1176 OS::Print("!!! unknown edge type: %d ", edge->type()); 1193 OS::Print("!!! unknown edge type: %d ", edge->type());
1177 } 1194 }
1178 edge->to()->Print(1, 0); 1195 edge->to()->Print(1, 0);
1179 } 1196 }
1180 OS::Print("\n"); 1197 OS::Print("\n");
1181 } 1198 }
1182 1199
1183 1200
1184 HeapObject *const HeapSnapshot::kInternalRootObject =
1185 reinterpret_cast<HeapObject*>(1);
1186 HeapObject *const HeapSnapshot::kGcRootsObject =
1187 reinterpret_cast<HeapObject*>(2);
1188
1189
1190 // It is very important to keep objects that form a heap snapshot 1201 // It is very important to keep objects that form a heap snapshot
1191 // as small as possible. 1202 // as small as possible.
1192 namespace { // Avoid littering the global namespace. 1203 namespace { // Avoid littering the global namespace.
1193 1204
1194 template <size_t ptr_size> struct SnapshotSizeConstants; 1205 template <size_t ptr_size> struct SnapshotSizeConstants;
1195 1206
1196 template <> struct SnapshotSizeConstants<4> { 1207 template <> struct SnapshotSizeConstants<4> {
1197 static const int kExpectedHeapGraphEdgeSize = 12; 1208 static const int kExpectedHeapGraphEdgeSize = 12;
1198 static const int kExpectedHeapEntrySize = 36; 1209 static const int kExpectedHeapEntrySize = 36;
1199 }; 1210 };
1200 1211
1201 template <> struct SnapshotSizeConstants<8> { 1212 template <> struct SnapshotSizeConstants<8> {
1202 static const int kExpectedHeapGraphEdgeSize = 24; 1213 static const int kExpectedHeapGraphEdgeSize = 24;
1203 static const int kExpectedHeapEntrySize = 48; 1214 static const int kExpectedHeapEntrySize = 48;
1204 }; 1215 };
1205 1216
1206 } // namespace 1217 } // namespace
1207 1218
1208 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, 1219 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1209 HeapSnapshot::Type type, 1220 HeapSnapshot::Type type,
1210 const char* title, 1221 const char* title,
1211 unsigned uid) 1222 unsigned uid)
1212 : collection_(collection), 1223 : collection_(collection),
1213 type_(type), 1224 type_(type),
1214 title_(title), 1225 title_(title),
1215 uid_(uid), 1226 uid_(uid),
1216 root_entry_(NULL), 1227 root_entry_(NULL),
1217 gc_roots_entry_(NULL), 1228 gc_roots_entry_(NULL),
1229 natives_root_entry_(NULL),
1218 raw_entries_(NULL), 1230 raw_entries_(NULL),
1219 entries_sorted_(false), 1231 entries_sorted_(false),
1220 retaining_paths_(HeapEntry::Match) { 1232 retaining_paths_(HeapEntry::Match) {
1221 STATIC_ASSERT( 1233 STATIC_ASSERT(
1222 sizeof(HeapGraphEdge) == 1234 sizeof(HeapGraphEdge) ==
1223 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL INT 1235 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL INT
1224 STATIC_ASSERT( 1236 STATIC_ASSERT(
1225 sizeof(HeapEntry) == 1237 sizeof(HeapEntry) ==
1226 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT 1238 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT
1227 } 1239 }
(...skipping 22 matching lines...) Expand all
1250 ASSERT(raw_entries_ == NULL); 1262 ASSERT(raw_entries_ == NULL);
1251 raw_entries_ = NewArray<char>( 1263 raw_entries_ = NewArray<char>(
1252 HeapEntry::EntriesSize(entries_count, children_count, retainers_count)); 1264 HeapEntry::EntriesSize(entries_count, children_count, retainers_count));
1253 #ifdef DEBUG 1265 #ifdef DEBUG
1254 raw_entries_size_ = 1266 raw_entries_size_ =
1255 HeapEntry::EntriesSize(entries_count, children_count, retainers_count); 1267 HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
1256 #endif 1268 #endif
1257 } 1269 }
1258 1270
1259 1271
1260 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
1261 int children_count,
1262 int retainers_count) {
1263 if (object == kInternalRootObject) {
1264 ASSERT(root_entry_ == NULL);
1265 ASSERT(retainers_count == 0);
1266 return (root_entry_ = AddEntry(HeapEntry::kObject,
1267 "",
1268 HeapObjectsMap::kInternalRootObjectId,
1269 0,
1270 children_count,
1271 retainers_count));
1272 } else if (object == kGcRootsObject) {
1273 ASSERT(gc_roots_entry_ == NULL);
1274 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
1275 "(GC roots)",
1276 HeapObjectsMap::kGcRootsObjectId,
1277 0,
1278 children_count,
1279 retainers_count));
1280 } else if (object->IsJSFunction()) {
1281 JSFunction* func = JSFunction::cast(object);
1282 SharedFunctionInfo* shared = func->shared();
1283 return AddEntry(object,
1284 HeapEntry::kClosure,
1285 collection_->GetName(String::cast(shared->name())),
1286 children_count,
1287 retainers_count);
1288 } else if (object->IsJSRegExp()) {
1289 JSRegExp* re = JSRegExp::cast(object);
1290 return AddEntry(object,
1291 HeapEntry::kRegExp,
1292 collection_->GetName(re->Pattern()),
1293 children_count,
1294 retainers_count);
1295 } else if (object->IsJSObject()) {
1296 return AddEntry(object,
1297 HeapEntry::kObject,
1298 collection_->GetName(GetConstructorNameForHeapProfile(
1299 JSObject::cast(object))),
1300 children_count,
1301 retainers_count);
1302 } else if (object->IsString()) {
1303 return AddEntry(object,
1304 HeapEntry::kString,
1305 collection_->GetName(String::cast(object)),
1306 children_count,
1307 retainers_count);
1308 } else if (object->IsCode()) {
1309 return AddEntry(object,
1310 HeapEntry::kCode,
1311 "",
1312 children_count,
1313 retainers_count);
1314 } else if (object->IsSharedFunctionInfo()) {
1315 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
1316 return AddEntry(object,
1317 HeapEntry::kCode,
1318 collection_->GetName(String::cast(shared->name())),
1319 children_count,
1320 retainers_count);
1321 } else if (object->IsScript()) {
1322 Script* script = Script::cast(object);
1323 return AddEntry(object,
1324 HeapEntry::kCode,
1325 script->name()->IsString() ?
1326 collection_->GetName(String::cast(script->name())) : "",
1327 children_count,
1328 retainers_count);
1329 } else if (object->IsFixedArray()) {
1330 return AddEntry(object,
1331 HeapEntry::kArray,
1332 "",
1333 children_count,
1334 retainers_count);
1335 } else if (object->IsHeapNumber()) {
1336 return AddEntry(object,
1337 HeapEntry::kHeapNumber,
1338 "number",
1339 children_count,
1340 retainers_count);
1341 }
1342 return AddEntry(object,
1343 HeapEntry::kHidden,
1344 "system",
1345 children_count,
1346 retainers_count);
1347 }
1348
1349
1350 static void HeapEntryClearPaint(HeapEntry** entry_ptr) { 1272 static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1351 (*entry_ptr)->clear_paint(); 1273 (*entry_ptr)->clear_paint();
1352 } 1274 }
1353 1275
1354 void HeapSnapshot::ClearPaint() { 1276 void HeapSnapshot::ClearPaint() {
1355 entries_.Iterate(HeapEntryClearPaint); 1277 entries_.Iterate(HeapEntryClearPaint);
1356 } 1278 }
1357 1279
1358 1280
1359 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, 1281 HeapEntry* HeapSnapshot::AddRootEntry(int children_count) {
1360 HeapEntry::Type type, 1282 ASSERT(root_entry_ == NULL);
1361 const char* name, 1283 return (root_entry_ = AddEntry(HeapEntry::kObject,
1362 int children_count, 1284 "",
1363 int retainers_count) { 1285 HeapObjectsMap::kInternalRootObjectId,
1364 return AddEntry(type, 1286 0,
1365 name, 1287 children_count,
1366 collection_->GetObjectId(object->address()), 1288 0));
1367 object->Size(), 1289 }
1368 children_count, 1290
1369 retainers_count); 1291
1292 HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count,
1293 int retainers_count) {
1294 ASSERT(gc_roots_entry_ == NULL);
1295 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
1296 "(GC roots)",
1297 HeapObjectsMap::kGcRootsObjectId,
1298 0,
1299 children_count,
1300 retainers_count));
1301 }
1302
1303
1304 HeapEntry* HeapSnapshot::AddNativesRootEntry(int children_count,
1305 int retainers_count) {
1306 ASSERT(natives_root_entry_ == NULL);
1307 return (natives_root_entry_ = AddEntry(
1308 HeapEntry::kObject,
1309 "(Native objects)",
1310 HeapObjectsMap::kNativesRootObjectId,
1311 0,
1312 children_count,
1313 retainers_count));
1370 } 1314 }
1371 1315
1372 1316
1373 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, 1317 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
1374 const char* name, 1318 const char* name,
1375 uint64_t id, 1319 uint64_t id,
1376 int size, 1320 int size,
1377 int children_count, 1321 int children_count,
1378 int retainers_count) { 1322 int retainers_count) {
1379 HeapEntry* entry = GetNextEntryToInit(); 1323 HeapEntry* entry = GetNextEntryToInit();
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1456 } 1400 }
1457 return &entries_; 1401 return &entries_;
1458 } 1402 }
1459 1403
1460 1404
1461 void HeapSnapshot::Print(int max_depth) { 1405 void HeapSnapshot::Print(int max_depth) {
1462 root()->Print(max_depth, 0); 1406 root()->Print(max_depth, 0);
1463 } 1407 }
1464 1408
1465 1409
1466 const uint64_t HeapObjectsMap::kInternalRootObjectId = 0; 1410 // We split IDs on evens for embedder objects (see
1467 const uint64_t HeapObjectsMap::kGcRootsObjectId = 1; 1411 // HeapObjectsMap::GenerateId) and odds for native objects.
1412 const uint64_t HeapObjectsMap::kInternalRootObjectId = 1;
1413 const uint64_t HeapObjectsMap::kGcRootsObjectId = 3;
1414 const uint64_t HeapObjectsMap::kNativesRootObjectId = 5;
1468 // Increase kFirstAvailableObjectId if new 'special' objects appear. 1415 // Increase kFirstAvailableObjectId if new 'special' objects appear.
1469 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 2; 1416 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 7;
1470 1417
1471 HeapObjectsMap::HeapObjectsMap() 1418 HeapObjectsMap::HeapObjectsMap()
1472 : initial_fill_mode_(true), 1419 : initial_fill_mode_(true),
1473 next_id_(kFirstAvailableObjectId), 1420 next_id_(kFirstAvailableObjectId),
1474 entries_map_(AddressesMatch), 1421 entries_map_(AddressesMatch),
1475 entries_(new List<EntryInfo>()) { } 1422 entries_(new List<EntryInfo>()) { }
1476 1423
1477 1424
1478 HeapObjectsMap::~HeapObjectsMap() { 1425 HeapObjectsMap::~HeapObjectsMap() {
1479 delete entries_; 1426 delete entries_;
1480 } 1427 }
1481 1428
1482 1429
1483 void HeapObjectsMap::SnapshotGenerationFinished() { 1430 void HeapObjectsMap::SnapshotGenerationFinished() {
1484 initial_fill_mode_ = false; 1431 initial_fill_mode_ = false;
1485 RemoveDeadEntries(); 1432 RemoveDeadEntries();
1486 } 1433 }
1487 1434
1488 1435
1489 uint64_t HeapObjectsMap::FindObject(Address addr) { 1436 uint64_t HeapObjectsMap::FindObject(Address addr) {
1490 if (!initial_fill_mode_) { 1437 if (!initial_fill_mode_) {
1491 uint64_t existing = FindEntry(addr); 1438 uint64_t existing = FindEntry(addr);
1492 if (existing != 0) return existing; 1439 if (existing != 0) return existing;
1493 } 1440 }
1494 uint64_t id = next_id_++; 1441 uint64_t id = next_id_;
1442 next_id_ += 2;
1495 AddEntry(addr, id); 1443 AddEntry(addr, id);
1496 return id; 1444 return id;
1497 } 1445 }
1498 1446
1499 1447
1500 void HeapObjectsMap::MoveObject(Address from, Address to) { 1448 void HeapObjectsMap::MoveObject(Address from, Address to) {
1501 if (from == to) return; 1449 if (from == to) return;
1502 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false); 1450 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false);
1503 if (entry != NULL) { 1451 if (entry != NULL) {
1504 void* value = entry->value; 1452 void* value = entry->value;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1552 for (int i = 0; i < dead_entries.length(); ++i) { 1500 for (int i = 0; i < dead_entries.length(); ++i) {
1553 void* raw_entry = dead_entries[i]; 1501 void* raw_entry = dead_entries[i];
1554 entries_map_.Remove( 1502 entries_map_.Remove(
1555 raw_entry, AddressHash(reinterpret_cast<Address>(raw_entry))); 1503 raw_entry, AddressHash(reinterpret_cast<Address>(raw_entry)));
1556 } 1504 }
1557 delete entries_; 1505 delete entries_;
1558 entries_ = new_entries; 1506 entries_ = new_entries;
1559 } 1507 }
1560 1508
1561 1509
1510 uint64_t HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) {
1511 uint64_t id = static_cast<uint64_t>(info->GetHash());
1512 const char* label = info->GetLabel();
1513 id ^= HashSequentialString(label, static_cast<int>(strlen(label)));
1514 intptr_t element_count = info->GetElementCount();
1515 if (element_count != -1)
1516 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count));
1517 return id << 1;
1518 }
1519
1520
1562 HeapSnapshotsCollection::HeapSnapshotsCollection() 1521 HeapSnapshotsCollection::HeapSnapshotsCollection()
1563 : is_tracking_objects_(false), 1522 : is_tracking_objects_(false),
1564 snapshots_uids_(HeapSnapshotsMatch), 1523 snapshots_uids_(HeapSnapshotsMatch),
1565 token_enumerator_(new TokenEnumerator()) { 1524 token_enumerator_(new TokenEnumerator()) {
1566 } 1525 }
1567 1526
1568 1527
1569 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) { 1528 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) {
1570 delete *snapshot_ptr; 1529 delete *snapshot_ptr;
1571 } 1530 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1612 HeapSnapshot* snapshot1, 1571 HeapSnapshot* snapshot1,
1613 HeapSnapshot* snapshot2) { 1572 HeapSnapshot* snapshot2) {
1614 return comparator_.Compare(snapshot1, snapshot2); 1573 return comparator_.Compare(snapshot1, snapshot2);
1615 } 1574 }
1616 1575
1617 1576
1618 HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder = 1577 HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder =
1619 reinterpret_cast<HeapEntry*>(1); 1578 reinterpret_cast<HeapEntry*>(1);
1620 1579
1621 HeapEntriesMap::HeapEntriesMap() 1580 HeapEntriesMap::HeapEntriesMap()
1622 : entries_(HeapObjectsMatch), 1581 : entries_(HeapThingsMatch),
1623 entries_count_(0), 1582 entries_count_(0),
1624 total_children_count_(0), 1583 total_children_count_(0),
1625 total_retainers_count_(0) { 1584 total_retainers_count_(0) {
1626 } 1585 }
1627 1586
1628 1587
1629 HeapEntriesMap::~HeapEntriesMap() { 1588 HeapEntriesMap::~HeapEntriesMap() {
1630 for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) { 1589 for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) {
1631 delete reinterpret_cast<EntryInfo*>(p->value); 1590 delete reinterpret_cast<EntryInfo*>(p->value);
1632 } 1591 }
1633 } 1592 }
1634 1593
1635 1594
1636 HeapEntry* HeapEntriesMap::Map(HeapObject* object) { 1595 void HeapEntriesMap::AllocateEntries() {
1637 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false); 1596 for (HashMap::Entry* p = entries_.Start();
1597 p != NULL;
1598 p = entries_.Next(p)) {
1599 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
1600 entry_info->entry = entry_info->allocator->AllocateEntry(
1601 p->key,
1602 entry_info->children_count,
1603 entry_info->retainers_count);
1604 ASSERT(entry_info->entry != NULL);
1605 ASSERT(entry_info->entry != kHeapEntryPlaceholder);
1606 entry_info->children_count = 0;
1607 entry_info->retainers_count = 0;
1608 }
1609 }
1610
1611
1612 HeapEntry* HeapEntriesMap::Map(HeapThing thing) {
1613 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
1638 if (cache_entry != NULL) { 1614 if (cache_entry != NULL) {
1639 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value); 1615 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value);
1640 return entry_info->entry; 1616 return entry_info->entry;
1641 } else { 1617 } else {
1642 return NULL; 1618 return NULL;
1643 } 1619 }
1644 } 1620 }
1645 1621
1646 1622
1647 void HeapEntriesMap::Pair(HeapObject* object, HeapEntry* entry) { 1623 void HeapEntriesMap::Pair(
1648 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), true); 1624 HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry) {
1625 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true);
1649 ASSERT(cache_entry->value == NULL); 1626 ASSERT(cache_entry->value == NULL);
1650 cache_entry->value = new EntryInfo(entry); 1627 cache_entry->value = new EntryInfo(entry, allocator);
1651 ++entries_count_; 1628 ++entries_count_;
1652 } 1629 }
1653 1630
1654 1631
1655 void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to, 1632 void HeapEntriesMap::CountReference(HeapThing from, HeapThing to,
1656 int* prev_children_count, 1633 int* prev_children_count,
1657 int* prev_retainers_count) { 1634 int* prev_retainers_count) {
1658 HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false); 1635 HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false);
1659 HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false); 1636 HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false);
1660 ASSERT(from_cache_entry != NULL); 1637 ASSERT(from_cache_entry != NULL);
1661 ASSERT(to_cache_entry != NULL); 1638 ASSERT(to_cache_entry != NULL);
1662 EntryInfo* from_entry_info = 1639 EntryInfo* from_entry_info =
1663 reinterpret_cast<EntryInfo*>(from_cache_entry->value); 1640 reinterpret_cast<EntryInfo*>(from_cache_entry->value);
1664 EntryInfo* to_entry_info = 1641 EntryInfo* to_entry_info =
1665 reinterpret_cast<EntryInfo*>(to_cache_entry->value); 1642 reinterpret_cast<EntryInfo*>(to_cache_entry->value);
1666 if (prev_children_count) 1643 if (prev_children_count)
1667 *prev_children_count = from_entry_info->children_count; 1644 *prev_children_count = from_entry_info->children_count;
1668 if (prev_retainers_count) 1645 if (prev_retainers_count)
1669 *prev_retainers_count = to_entry_info->retainers_count; 1646 *prev_retainers_count = to_entry_info->retainers_count;
1670 ++from_entry_info->children_count; 1647 ++from_entry_info->children_count;
1671 ++to_entry_info->retainers_count; 1648 ++to_entry_info->retainers_count;
1672 ++total_children_count_; 1649 ++total_children_count_;
1673 ++total_retainers_count_; 1650 ++total_retainers_count_;
1674 } 1651 }
1675 1652
1676 1653
1677 HeapObjectsSet::HeapObjectsSet() 1654 HeapObjectsSet::HeapObjectsSet()
1678 : entries_(HeapEntriesMap::HeapObjectsMatch) { 1655 : entries_(HeapEntriesMap::HeapThingsMatch) {
1679 } 1656 }
1680 1657
1681 1658
1682 void HeapObjectsSet::Clear() { 1659 void HeapObjectsSet::Clear() {
1683 entries_.Clear(); 1660 entries_.Clear();
1684 } 1661 }
1685 1662
1686 1663
1687 bool HeapObjectsSet::Contains(Object* obj) { 1664 bool HeapObjectsSet::Contains(Object* obj) {
1688 if (!obj->IsHeapObject()) return false; 1665 if (!obj->IsHeapObject()) return false;
1689 HeapObject* object = HeapObject::cast(obj); 1666 HeapObject* object = HeapObject::cast(obj);
1690 HashMap::Entry* cache_entry = 1667 HashMap::Entry* cache_entry =
1691 entries_.Lookup(object, HeapEntriesMap::Hash(object), false); 1668 entries_.Lookup(object, HeapEntriesMap::Hash(object), false);
1692 return cache_entry != NULL; 1669 return cache_entry != NULL;
1693 } 1670 }
1694 1671
1695 1672
1696 void HeapObjectsSet::Insert(Object* obj) { 1673 void HeapObjectsSet::Insert(Object* obj) {
1697 if (!obj->IsHeapObject()) return; 1674 if (!obj->IsHeapObject()) return;
1698 HeapObject* object = HeapObject::cast(obj); 1675 HeapObject* object = HeapObject::cast(obj);
1699 HashMap::Entry* cache_entry = 1676 HashMap::Entry* cache_entry =
1700 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); 1677 entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
1701 if (cache_entry->value == NULL) { 1678 if (cache_entry->value == NULL) {
1702 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; 1679 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder;
1703 } 1680 }
1704 } 1681 }
1705 1682
1706 1683
1707 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, 1684 HeapObject *const V8HeapExplorer::kInternalRootObject =
1708 v8::ActivityControl* control) 1685 reinterpret_cast<HeapObject*>(
1686 static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId));
1687 HeapObject *const V8HeapExplorer::kGcRootsObject =
1688 reinterpret_cast<HeapObject*>(
1689 static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId));
1690
1691
1692 V8HeapExplorer::V8HeapExplorer(
1693 HeapSnapshot* snapshot,
1694 SnapshottingProgressReportingInterface* progress)
1709 : snapshot_(snapshot), 1695 : snapshot_(snapshot),
1710 control_(control), 1696 collection_(snapshot_->collection()),
1711 collection_(snapshot->collection()), 1697 progress_(progress),
1712 filler_(NULL) { 1698 filler_(NULL) {
1713 } 1699 }
1714 1700
1715 class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface {
1716 public:
1717 explicit SnapshotCounter(HeapEntriesMap* entries)
1718 : entries_(entries) { }
1719 HeapEntry* AddEntry(HeapObject* obj) {
1720 entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder);
1721 return HeapEntriesMap::kHeapEntryPlaceholder;
1722 }
1723 void SetIndexedReference(HeapGraphEdge::Type,
1724 HeapObject* parent_obj,
1725 HeapEntry*,
1726 int,
1727 Object* child_obj,
1728 HeapEntry*) {
1729 entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
1730 }
1731 void SetNamedReference(HeapGraphEdge::Type,
1732 HeapObject* parent_obj,
1733 HeapEntry*,
1734 const char*,
1735 Object* child_obj,
1736 HeapEntry*) {
1737 entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
1738 }
1739 void SetRootShortcutReference(Object* child_obj, HeapEntry*) {
1740 entries_->CountReference(
1741 HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj));
1742 }
1743 void SetRootGcRootsReference() {
1744 entries_->CountReference(
1745 HeapSnapshot::kInternalRootObject, HeapSnapshot::kGcRootsObject);
1746 }
1747 void SetStrongRootReference(Object* child_obj, HeapEntry*) {
1748 entries_->CountReference(
1749 HeapSnapshot::kGcRootsObject, HeapObject::cast(child_obj));
1750 }
1751 private:
1752 HeapEntriesMap* entries_;
1753 };
1754 1701
1755 1702 V8HeapExplorer::~V8HeapExplorer() {
1756 class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface {
1757 public:
1758 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
1759 : snapshot_(snapshot),
1760 collection_(snapshot->collection()),
1761 entries_(entries) { }
1762 HeapEntry* AddEntry(HeapObject* obj) {
1763 UNREACHABLE();
1764 return NULL;
1765 }
1766 void SetIndexedReference(HeapGraphEdge::Type type,
1767 HeapObject* parent_obj,
1768 HeapEntry* parent_entry,
1769 int index,
1770 Object* child_obj,
1771 HeapEntry* child_entry) {
1772 int child_index, retainer_index;
1773 entries_->CountReference(parent_obj,
1774 HeapObject::cast(child_obj),
1775 &child_index,
1776 &retainer_index);
1777 parent_entry->SetIndexedReference(
1778 type, child_index, index, child_entry, retainer_index);
1779 }
1780 void SetNamedReference(HeapGraphEdge::Type type,
1781 HeapObject* parent_obj,
1782 HeapEntry* parent_entry,
1783 const char* reference_name,
1784 Object* child_obj,
1785 HeapEntry* child_entry) {
1786 int child_index, retainer_index;
1787 entries_->CountReference(parent_obj, HeapObject::cast(child_obj),
1788 &child_index, &retainer_index);
1789 parent_entry->SetNamedReference(type,
1790 child_index,
1791 reference_name,
1792 child_entry,
1793 retainer_index);
1794 }
1795 void SetRootGcRootsReference() {
1796 int child_index, retainer_index;
1797 entries_->CountReference(HeapSnapshot::kInternalRootObject,
1798 HeapSnapshot::kGcRootsObject,
1799 &child_index,
1800 &retainer_index);
1801 snapshot_->root()->SetIndexedReference(HeapGraphEdge::kElement,
1802 child_index,
1803 child_index + 1,
1804 snapshot_->gc_roots(),
1805 retainer_index);
1806 }
1807 void SetRootShortcutReference(Object* child_obj,
1808 HeapEntry* child_entry) {
1809 int child_index, retainer_index;
1810 entries_->CountReference(HeapSnapshot::kInternalRootObject,
1811 HeapObject::cast(child_obj),
1812 &child_index,
1813 &retainer_index);
1814 snapshot_->root()->SetNamedReference(HeapGraphEdge::kShortcut,
1815 child_index,
1816 collection_->GetName(child_index + 1),
1817 child_entry,
1818 retainer_index);
1819 }
1820 void SetStrongRootReference(Object* child_obj,
1821 HeapEntry* child_entry) {
1822 int child_index, retainer_index;
1823 entries_->CountReference(HeapSnapshot::kGcRootsObject,
1824 HeapObject::cast(child_obj),
1825 &child_index,
1826 &retainer_index);
1827 snapshot_->gc_roots()->SetIndexedReference(HeapGraphEdge::kElement,
1828 child_index,
1829 child_index + 1,
1830 child_entry,
1831 retainer_index);
1832 }
1833 private:
1834 HeapSnapshot* snapshot_;
1835 HeapSnapshotsCollection* collection_;
1836 HeapEntriesMap* entries_;
1837 };
1838
1839 class SnapshotAllocator {
1840 public:
1841 explicit SnapshotAllocator(HeapSnapshot* snapshot)
1842 : snapshot_(snapshot) { }
1843 HeapEntry* GetEntry(
1844 HeapObject* obj, int children_count, int retainers_count) {
1845 HeapEntry* entry =
1846 snapshot_->AddEntry(obj, children_count, retainers_count);
1847 ASSERT(entry != NULL);
1848 return entry;
1849 }
1850 private:
1851 HeapSnapshot* snapshot_;
1852 };
1853
1854 class RootsReferencesExtractor : public ObjectVisitor {
1855 public:
1856 explicit RootsReferencesExtractor(HeapSnapshotGenerator* generator)
1857 : generator_(generator) {
1858 }
1859 void VisitPointers(Object** start, Object** end) {
1860 for (Object** p = start; p < end; p++) generator_->SetGcRootsReference(*p);
1861 }
1862 private:
1863 HeapSnapshotGenerator* generator_;
1864 };
1865
1866
1867 bool HeapSnapshotGenerator::GenerateSnapshot() {
1868 AssertNoAllocation no_alloc;
1869
1870 SetProgressTotal(4); // 2 passes + dominators + sizes.
1871
1872 // Pass 1. Iterate heap contents to count entries and references.
1873 if (!CountEntriesAndReferences()) return false;
1874
1875 // Allocate and fill entries in the snapshot, allocate references.
1876 snapshot_->AllocateEntries(entries_.entries_count(),
1877 entries_.total_children_count(),
1878 entries_.total_retainers_count());
1879 SnapshotAllocator allocator(snapshot_);
1880 entries_.UpdateEntries(&allocator);
1881
1882 // Pass 2. Fill references.
1883 if (!FillReferences()) return false;
1884
1885 if (!SetEntriesDominators()) return false;
1886 if (!ApproximateRetainedSizes()) return false;
1887
1888 progress_counter_ = progress_total_;
1889 if (!ReportProgress(true)) return false;
1890 return true;
1891 } 1703 }
1892 1704
1893 1705
1894 HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) { 1706 HeapEntry* V8HeapExplorer::AllocateEntry(
1895 if (!obj->IsHeapObject()) return NULL; 1707 HeapThing ptr, int children_count, int retainers_count) {
1896 HeapObject* object = HeapObject::cast(obj); 1708 return AddEntry(
1897 HeapEntry* entry = entries_.Map(object); 1709 reinterpret_cast<HeapObject*>(ptr), children_count, retainers_count);
1898 // A new entry. 1710 }
1899 if (entry == NULL) entry = filler_->AddEntry(object); 1711
1900 return entry; 1712
1713 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1714 int children_count,
1715 int retainers_count) {
1716 if (object == kInternalRootObject) {
1717 ASSERT(retainers_count == 0);
1718 return snapshot_->AddRootEntry(children_count);
1719 } else if (object == kGcRootsObject) {
1720 return snapshot_->AddGcRootsEntry(children_count, retainers_count);
1721 } else if (object->IsJSFunction()) {
1722 JSFunction* func = JSFunction::cast(object);
1723 SharedFunctionInfo* shared = func->shared();
1724 return AddEntry(object,
1725 HeapEntry::kClosure,
1726 collection_->names()->GetName(String::cast(shared->name())),
1727 children_count,
1728 retainers_count);
1729 } else if (object->IsJSRegExp()) {
1730 JSRegExp* re = JSRegExp::cast(object);
1731 return AddEntry(object,
1732 HeapEntry::kRegExp,
1733 collection_->names()->GetName(re->Pattern()),
1734 children_count,
1735 retainers_count);
1736 } else if (object->IsJSObject()) {
1737 return AddEntry(object,
1738 HeapEntry::kObject,
1739 collection_->names()->GetName(
1740 GetConstructorNameForHeapProfile(
1741 JSObject::cast(object))),
1742 children_count,
1743 retainers_count);
1744 } else if (object->IsString()) {
1745 return AddEntry(object,
1746 HeapEntry::kString,
1747 collection_->names()->GetName(String::cast(object)),
1748 children_count,
1749 retainers_count);
1750 } else if (object->IsCode()) {
1751 return AddEntry(object,
1752 HeapEntry::kCode,
1753 "",
1754 children_count,
1755 retainers_count);
1756 } else if (object->IsSharedFunctionInfo()) {
1757 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
1758 return AddEntry(object,
1759 HeapEntry::kCode,
1760 collection_->names()->GetName(String::cast(shared->name())),
1761 children_count,
1762 retainers_count);
1763 } else if (object->IsScript()) {
1764 Script* script = Script::cast(object);
1765 return AddEntry(object,
1766 HeapEntry::kCode,
1767 script->name()->IsString() ?
1768 collection_->names()->GetName(
1769 String::cast(script->name()))
1770 : "",
1771 children_count,
1772 retainers_count);
1773 } else if (object->IsFixedArray()) {
1774 return AddEntry(object,
1775 HeapEntry::kArray,
1776 "",
1777 children_count,
1778 retainers_count);
1779 } else if (object->IsHeapNumber()) {
1780 return AddEntry(object,
1781 HeapEntry::kHeapNumber,
1782 "number",
1783 children_count,
1784 retainers_count);
1785 }
1786 return AddEntry(object,
1787 HeapEntry::kHidden,
1788 "system",
1789 children_count,
1790 retainers_count);
1791 }
1792
1793
1794 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1795 HeapEntry::Type type,
1796 const char* name,
1797 int children_count,
1798 int retainers_count) {
1799 return snapshot_->AddEntry(type,
1800 name,
1801 collection_->GetObjectId(object->address()),
1802 object->Size(),
1803 children_count,
1804 retainers_count);
1805 }
1806
1807
1808 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
1809 filler->AddEntry(kInternalRootObject, this);
1810 filler->AddEntry(kGcRootsObject, this);
1811 }
1812
1813
1814 int V8HeapExplorer::EstimateObjectsCount() {
1815 HeapIterator iterator(HeapIterator::kFilterUnreachable);
1816 int objects_count = 0;
1817 for (HeapObject* obj = iterator.next();
1818 obj != NULL;
1819 obj = iterator.next(), ++objects_count) {}
1820 return objects_count;
1901 } 1821 }
1902 1822
1903 1823
1904 class IndexedReferencesExtractor : public ObjectVisitor { 1824 class IndexedReferencesExtractor : public ObjectVisitor {
1905 public: 1825 public:
1906 IndexedReferencesExtractor(HeapSnapshotGenerator* generator, 1826 IndexedReferencesExtractor(V8HeapExplorer* generator,
1907 HeapObject* parent_obj, 1827 HeapObject* parent_obj,
1908 HeapEntry* parent_entry, 1828 HeapEntry* parent_entry,
1909 HeapObjectsSet* known_references = NULL) 1829 HeapObjectsSet* known_references = NULL)
1910 : generator_(generator), 1830 : generator_(generator),
1911 parent_obj_(parent_obj), 1831 parent_obj_(parent_obj),
1912 parent_(parent_entry), 1832 parent_(parent_entry),
1913 known_references_(known_references), 1833 known_references_(known_references),
1914 next_index_(1) { 1834 next_index_(1) {
1915 } 1835 }
1916 void VisitPointers(Object** start, Object** end) { 1836 void VisitPointers(Object** start, Object** end) {
1917 for (Object** p = start; p < end; p++) { 1837 for (Object** p = start; p < end; p++) {
1918 if (!known_references_ || !known_references_->Contains(*p)) { 1838 if (!known_references_ || !known_references_->Contains(*p)) {
1919 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); 1839 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p);
1920 } 1840 }
1921 } 1841 }
1922 } 1842 }
1923 private: 1843 private:
1924 HeapSnapshotGenerator* generator_; 1844 V8HeapExplorer* generator_;
1925 HeapObject* parent_obj_; 1845 HeapObject* parent_obj_;
1926 HeapEntry* parent_; 1846 HeapEntry* parent_;
1927 HeapObjectsSet* known_references_; 1847 HeapObjectsSet* known_references_;
1928 int next_index_; 1848 int next_index_;
1929 }; 1849 };
1930 1850
1931 1851
1932 void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) { 1852 void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
1933 HeapEntry* entry = GetEntry(obj); 1853 HeapEntry* entry = GetEntry(obj);
1934 if (entry == NULL) return; // No interest in this object. 1854 if (entry == NULL) return; // No interest in this object.
1935 1855
1936 known_references_.Clear(); 1856 known_references_.Clear();
1937 if (obj->IsJSGlobalProxy()) { 1857 if (obj->IsJSGlobalProxy()) {
1938 // We need to reference JS global objects from snapshot's root. 1858 // We need to reference JS global objects from snapshot's root.
1939 // We use JSGlobalProxy because this is what embedder (e.g. browser) 1859 // We use JSGlobalProxy because this is what embedder (e.g. browser)
1940 // uses for the global object. 1860 // uses for the global object.
1941 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); 1861 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj);
1942 SetRootShortcutReference(proxy->map()->prototype()); 1862 SetRootShortcutReference(proxy->map()->prototype());
(...skipping 23 matching lines...) Expand all
1966 SetInternalReference(obj, entry, 1, cs->first()); 1886 SetInternalReference(obj, entry, 1, cs->first());
1967 SetInternalReference(obj, entry, 2, cs->second()); 1887 SetInternalReference(obj, entry, 2, cs->second());
1968 } 1888 }
1969 } else { 1889 } else {
1970 IndexedReferencesExtractor refs_extractor(this, obj, entry); 1890 IndexedReferencesExtractor refs_extractor(this, obj, entry);
1971 obj->Iterate(&refs_extractor); 1891 obj->Iterate(&refs_extractor);
1972 } 1892 }
1973 } 1893 }
1974 1894
1975 1895
1976 void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj, 1896 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
1977 HeapEntry* entry) { 1897 HeapEntry* entry) {
1978 if (js_obj->IsJSFunction()) { 1898 if (js_obj->IsJSFunction()) {
1979 HandleScope hs; 1899 HandleScope hs;
1980 JSFunction* func = JSFunction::cast(js_obj); 1900 JSFunction* func = JSFunction::cast(js_obj);
1981 Context* context = func->context(); 1901 Context* context = func->context();
1982 ZoneScope zscope(DELETE_ON_EXIT); 1902 ZoneScope zscope(DELETE_ON_EXIT);
1983 SerializedScopeInfo* serialized_scope_info = 1903 SerializedScopeInfo* serialized_scope_info =
1984 context->closure()->shared()->scope_info(); 1904 context->closure()->shared()->scope_info();
1985 ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(serialized_scope_info); 1905 ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(serialized_scope_info);
1986 int locals_number = zone_scope_info.NumberOfLocals(); 1906 int locals_number = zone_scope_info.NumberOfLocals();
1987 for (int i = 0; i < locals_number; ++i) { 1907 for (int i = 0; i < locals_number; ++i) {
1988 String* local_name = *zone_scope_info.LocalName(i); 1908 String* local_name = *zone_scope_info.LocalName(i);
1989 int idx = serialized_scope_info->ContextSlotIndex(local_name, NULL); 1909 int idx = serialized_scope_info->ContextSlotIndex(local_name, NULL);
1990 if (idx >= 0 && idx < context->length()) { 1910 if (idx >= 0 && idx < context->length()) {
1991 SetClosureReference(js_obj, entry, local_name, context->get(idx)); 1911 SetClosureReference(js_obj, entry, local_name, context->get(idx));
1992 } 1912 }
1993 } 1913 }
1994 SetInternalReference(js_obj, entry, "code", func->shared()); 1914 SetInternalReference(js_obj, entry, "code", func->shared());
1995 } 1915 }
1996 } 1916 }
1997 1917
1998 1918
1999 void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj, 1919 void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj,
2000 HeapEntry* entry) { 1920 HeapEntry* entry) {
2001 if (js_obj->HasFastProperties()) { 1921 if (js_obj->HasFastProperties()) {
2002 DescriptorArray* descs = js_obj->map()->instance_descriptors(); 1922 DescriptorArray* descs = js_obj->map()->instance_descriptors();
2003 for (int i = 0; i < descs->number_of_descriptors(); i++) { 1923 for (int i = 0; i < descs->number_of_descriptors(); i++) {
2004 switch (descs->GetType(i)) { 1924 switch (descs->GetType(i)) {
2005 case FIELD: { 1925 case FIELD: {
2006 int index = descs->GetFieldIndex(i); 1926 int index = descs->GetFieldIndex(i);
2007 SetPropertyReference( 1927 SetPropertyReference(
2008 js_obj, entry, descs->GetKey(i), js_obj->FastPropertyAt(index)); 1928 js_obj, entry, descs->GetKey(i), js_obj->FastPropertyAt(index));
2009 break; 1929 break;
2010 } 1930 }
(...skipping 20 matching lines...) Expand all
2031 String::cast(k), 1951 String::cast(k),
2032 JSGlobalPropertyCell::cast( 1952 JSGlobalPropertyCell::cast(
2033 target)->value()); 1953 target)->value());
2034 } 1954 }
2035 } 1955 }
2036 } 1956 }
2037 } 1957 }
2038 } 1958 }
2039 1959
2040 1960
2041 void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj, 1961 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
2042 HeapEntry* entry) { 1962 HeapEntry* entry) {
2043 if (js_obj->HasFastElements()) { 1963 if (js_obj->HasFastElements()) {
2044 FixedArray* elements = FixedArray::cast(js_obj->elements()); 1964 FixedArray* elements = FixedArray::cast(js_obj->elements());
2045 int length = js_obj->IsJSArray() ? 1965 int length = js_obj->IsJSArray() ?
2046 Smi::cast(JSArray::cast(js_obj)->length())->value() : 1966 Smi::cast(JSArray::cast(js_obj)->length())->value() :
2047 elements->length(); 1967 elements->length();
2048 for (int i = 0; i < length; ++i) { 1968 for (int i = 0; i < length; ++i) {
2049 if (!elements->get(i)->IsTheHole()) { 1969 if (!elements->get(i)->IsTheHole()) {
2050 SetElementReference(js_obj, entry, i, elements->get(i)); 1970 SetElementReference(js_obj, entry, i, elements->get(i));
2051 } 1971 }
2052 } 1972 }
2053 } else if (js_obj->HasDictionaryElements()) { 1973 } else if (js_obj->HasDictionaryElements()) {
2054 NumberDictionary* dictionary = js_obj->element_dictionary(); 1974 NumberDictionary* dictionary = js_obj->element_dictionary();
2055 int length = dictionary->Capacity(); 1975 int length = dictionary->Capacity();
2056 for (int i = 0; i < length; ++i) { 1976 for (int i = 0; i < length; ++i) {
2057 Object* k = dictionary->KeyAt(i); 1977 Object* k = dictionary->KeyAt(i);
2058 if (dictionary->IsKey(k)) { 1978 if (dictionary->IsKey(k)) {
2059 ASSERT(k->IsNumber()); 1979 ASSERT(k->IsNumber());
2060 uint32_t index = static_cast<uint32_t>(k->Number()); 1980 uint32_t index = static_cast<uint32_t>(k->Number());
2061 SetElementReference(js_obj, entry, index, dictionary->ValueAt(i)); 1981 SetElementReference(js_obj, entry, index, dictionary->ValueAt(i));
2062 } 1982 }
2063 } 1983 }
2064 } 1984 }
2065 } 1985 }
2066 1986
2067 1987
2068 void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj, 1988 void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj,
2069 HeapEntry* entry) { 1989 HeapEntry* entry) {
2070 int length = js_obj->GetInternalFieldCount(); 1990 int length = js_obj->GetInternalFieldCount();
2071 for (int i = 0; i < length; ++i) { 1991 for (int i = 0; i < length; ++i) {
2072 Object* o = js_obj->GetInternalField(i); 1992 Object* o = js_obj->GetInternalField(i);
2073 SetInternalReference(js_obj, entry, i, o); 1993 SetInternalReference(js_obj, entry, i, o);
2074 } 1994 }
2075 } 1995 }
2076 1996
2077 1997
2078 void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj, 1998 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) {
2079 HeapEntry* parent_entry, 1999 if (!obj->IsHeapObject()) return NULL;
2080 String* reference_name, 2000 return filler_->FindOrAddEntry(obj, this);
2081 Object* child_obj) { 2001 }
2002
2003
2004 class RootsReferencesExtractor : public ObjectVisitor {
2005 public:
2006 explicit RootsReferencesExtractor(V8HeapExplorer* explorer)
2007 : explorer_(explorer) {
2008 }
2009 void VisitPointers(Object** start, Object** end) {
2010 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p);
2011 }
2012 private:
2013 V8HeapExplorer* explorer_;
2014 };
2015
2016
2017 bool V8HeapExplorer::IterateAndExtractReferences(
2018 SnapshotFillerInterface* filler) {
2019 filler_ = filler;
2020 HeapIterator iterator(HeapIterator::kFilterUnreachable);
2021 bool interrupted = false;
2022 // Heap iteration with filtering must be finished in any case.
2023 for (HeapObject* obj = iterator.next();
2024 obj != NULL;
2025 obj = iterator.next(), progress_->ProgressStep()) {
2026 if (!interrupted) {
2027 ExtractReferences(obj);
2028 if (!progress_->ProgressReport(false)) interrupted = true;
2029 }
2030 }
2031 if (interrupted) {
2032 filler_ = NULL;
2033 return false;
2034 }
2035 SetRootGcRootsReference();
2036 RootsReferencesExtractor extractor(this);
2037 Heap::IterateRoots(&extractor, VISIT_ALL);
2038 filler_ = NULL;
2039 return progress_->ProgressReport(false);
2040 }
2041
2042
2043 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj,
2044 HeapEntry* parent_entry,
2045 String* reference_name,
2046 Object* child_obj) {
2082 HeapEntry* child_entry = GetEntry(child_obj); 2047 HeapEntry* child_entry = GetEntry(child_obj);
2083 if (child_entry != NULL) { 2048 if (child_entry != NULL) {
2084 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, 2049 filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
2085 parent_obj, 2050 parent_obj,
2086 parent_entry, 2051 parent_entry,
2087 collection_->GetName(reference_name), 2052 collection_->names()->GetName(reference_name),
2088 child_obj, 2053 child_obj,
2089 child_entry); 2054 child_entry);
2090 known_references_.Insert(child_obj); 2055 known_references_.Insert(child_obj);
2091 } 2056 }
2092 } 2057 }
2093 2058
2094 2059
2095 void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj, 2060 void V8HeapExplorer::SetElementReference(HeapObject* parent_obj,
2096 HeapEntry* parent_entry, 2061 HeapEntry* parent_entry,
2097 int index, 2062 int index,
2098 Object* child_obj) { 2063 Object* child_obj) {
2099 HeapEntry* child_entry = GetEntry(child_obj); 2064 HeapEntry* child_entry = GetEntry(child_obj);
2100 if (child_entry != NULL) { 2065 if (child_entry != NULL) {
2101 filler_->SetIndexedReference(HeapGraphEdge::kElement, 2066 filler_->SetIndexedReference(HeapGraphEdge::kElement,
2102 parent_obj, 2067 parent_obj,
2103 parent_entry, 2068 parent_entry,
2104 index, 2069 index,
2105 child_obj, 2070 child_obj,
2106 child_entry); 2071 child_entry);
2107 known_references_.Insert(child_obj); 2072 known_references_.Insert(child_obj);
2108 } 2073 }
2109 } 2074 }
2110 2075
2111 2076
2112 void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, 2077 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2113 HeapEntry* parent_entry, 2078 HeapEntry* parent_entry,
2114 const char* reference_name, 2079 const char* reference_name,
2115 Object* child_obj) { 2080 Object* child_obj) {
2116 HeapEntry* child_entry = GetEntry(child_obj); 2081 HeapEntry* child_entry = GetEntry(child_obj);
2117 if (child_entry != NULL) { 2082 if (child_entry != NULL) {
2118 filler_->SetNamedReference(HeapGraphEdge::kInternal, 2083 filler_->SetNamedReference(HeapGraphEdge::kInternal,
2119 parent_obj, 2084 parent_obj,
2120 parent_entry, 2085 parent_entry,
2121 reference_name, 2086 reference_name,
2122 child_obj, 2087 child_obj,
2123 child_entry); 2088 child_entry);
2124 known_references_.Insert(child_obj); 2089 known_references_.Insert(child_obj);
2125 } 2090 }
2126 } 2091 }
2127 2092
2128 2093
2129 void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, 2094 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2130 HeapEntry* parent_entry, 2095 HeapEntry* parent_entry,
2131 int index, 2096 int index,
2132 Object* child_obj) { 2097 Object* child_obj) {
2133 HeapEntry* child_entry = GetEntry(child_obj); 2098 HeapEntry* child_entry = GetEntry(child_obj);
2134 if (child_entry != NULL) { 2099 if (child_entry != NULL) {
2135 filler_->SetNamedReference(HeapGraphEdge::kInternal, 2100 filler_->SetNamedReference(HeapGraphEdge::kInternal,
2136 parent_obj, 2101 parent_obj,
2137 parent_entry, 2102 parent_entry,
2138 collection_->GetName(index), 2103 collection_->names()->GetName(index),
2139 child_obj, 2104 child_obj,
2140 child_entry); 2105 child_entry);
2141 known_references_.Insert(child_obj); 2106 known_references_.Insert(child_obj);
2142 } 2107 }
2143 } 2108 }
2144 2109
2145 2110
2146 void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj, 2111 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj,
2147 HeapEntry* parent_entry, 2112 HeapEntry* parent_entry,
2148 int index, 2113 int index,
2149 Object* child_obj) { 2114 Object* child_obj) {
2150 HeapEntry* child_entry = GetEntry(child_obj); 2115 HeapEntry* child_entry = GetEntry(child_obj);
2151 if (child_entry != NULL) { 2116 if (child_entry != NULL) {
2152 filler_->SetIndexedReference(HeapGraphEdge::kHidden, 2117 filler_->SetIndexedReference(HeapGraphEdge::kHidden,
2153 parent_obj, 2118 parent_obj,
2154 parent_entry, 2119 parent_entry,
2155 index, 2120 index,
2156 child_obj, 2121 child_obj,
2157 child_entry); 2122 child_entry);
2158 } 2123 }
2159 } 2124 }
2160 2125
2161 2126
2162 void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj, 2127 void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
2163 HeapEntry* parent_entry, 2128 HeapEntry* parent_entry,
2164 String* reference_name, 2129 String* reference_name,
2165 Object* child_obj) { 2130 Object* child_obj) {
2166 HeapEntry* child_entry = GetEntry(child_obj); 2131 HeapEntry* child_entry = GetEntry(child_obj);
2167 if (child_entry != NULL) { 2132 if (child_entry != NULL) {
2168 HeapGraphEdge::Type type = reference_name->length() > 0 ? 2133 HeapGraphEdge::Type type = reference_name->length() > 0 ?
2169 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; 2134 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
2170 filler_->SetNamedReference(type, 2135 filler_->SetNamedReference(type,
2171 parent_obj, 2136 parent_obj,
2172 parent_entry, 2137 parent_entry,
2173 collection_->GetName(reference_name), 2138 collection_->names()->GetName(reference_name),
2174 child_obj, 2139 child_obj,
2175 child_entry); 2140 child_entry);
2176 known_references_.Insert(child_obj); 2141 known_references_.Insert(child_obj);
2177 } 2142 }
2178 } 2143 }
2179 2144
2180 2145
2181 void HeapSnapshotGenerator::SetPropertyShortcutReference( 2146 void V8HeapExplorer::SetPropertyShortcutReference(
2182 HeapObject* parent_obj, 2147 HeapObject* parent_obj,
2183 HeapEntry* parent_entry, 2148 HeapEntry* parent_entry,
2184 String* reference_name, 2149 String* reference_name,
2185 Object* child_obj) { 2150 Object* child_obj) {
2186 HeapEntry* child_entry = GetEntry(child_obj); 2151 HeapEntry* child_entry = GetEntry(child_obj);
2187 if (child_entry != NULL) { 2152 if (child_entry != NULL) {
2188 filler_->SetNamedReference(HeapGraphEdge::kShortcut, 2153 filler_->SetNamedReference(HeapGraphEdge::kShortcut,
2189 parent_obj, 2154 parent_obj,
2190 parent_entry, 2155 parent_entry,
2191 collection_->GetName(reference_name), 2156 collection_->names()->GetName(reference_name),
2192 child_obj, 2157 child_obj,
2193 child_entry); 2158 child_entry);
2194 } 2159 }
2195 } 2160 }
2196 2161
2197 2162
2198 void HeapSnapshotGenerator::SetRootGcRootsReference() { 2163 void V8HeapExplorer::SetRootGcRootsReference() {
2199 filler_->SetRootGcRootsReference(); 2164 filler_->SetIndexedAutoIndexReference(
2200 } 2165 HeapGraphEdge::kElement,
2201 2166 kInternalRootObject, snapshot_->root(),
2202 2167 kGcRootsObject, snapshot_->gc_roots());
2203 void HeapSnapshotGenerator::SetRootShortcutReference(Object* child_obj) { 2168 }
2169
2170
2171 void V8HeapExplorer::SetRootShortcutReference(Object* child_obj) {
2204 HeapEntry* child_entry = GetEntry(child_obj); 2172 HeapEntry* child_entry = GetEntry(child_obj);
2205 ASSERT(child_entry != NULL); 2173 ASSERT(child_entry != NULL);
2206 filler_->SetRootShortcutReference(child_obj, child_entry); 2174 filler_->SetNamedAutoIndexReference(
2207 } 2175 HeapGraphEdge::kShortcut,
2208 2176 kInternalRootObject, snapshot_->root(),
2209 2177 child_obj, child_entry);
2210 void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) { 2178 }
2179
2180
2181 void V8HeapExplorer::SetGcRootsReference(Object* child_obj) {
2211 HeapEntry* child_entry = GetEntry(child_obj); 2182 HeapEntry* child_entry = GetEntry(child_obj);
2212 if (child_entry != NULL) { 2183 if (child_entry != NULL) {
2213 filler_->SetStrongRootReference(child_obj, child_entry); 2184 filler_->SetIndexedAutoIndexReference(
2214 } 2185 HeapGraphEdge::kElement,
2186 kGcRootsObject, snapshot_->gc_roots(),
2187 child_obj, child_entry);
2188 }
2189 }
2190
2191
2192 class GlobalHandlesExtractor : public ObjectVisitor {
2193 public:
2194 explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer)
2195 : explorer_(explorer) {}
2196 virtual ~GlobalHandlesExtractor() {}
2197 virtual void VisitPointers(Object** start, Object** end) {
2198 UNREACHABLE();
2199 }
2200 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {
2201 explorer_->VisitSubtreeWrapper(p, class_id);
2202 }
2203 private:
2204 NativeObjectsExplorer* explorer_;
2205 };
2206
2207 HeapThing const NativeObjectsExplorer::kNativesRootObject =
2208 reinterpret_cast<HeapThing>(
2209 static_cast<intptr_t>(HeapObjectsMap::kNativesRootObjectId));
2210
2211
2212 NativeObjectsExplorer::NativeObjectsExplorer(
2213 HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress)
2214 : snapshot_(snapshot),
2215 collection_(snapshot_->collection()),
2216 progress_(progress),
2217 embedder_queried_(false),
2218 objects_by_info_(RetainedInfosMatch),
2219 filler_(NULL) {
2220 }
2221
2222
2223 NativeObjectsExplorer::~NativeObjectsExplorer() {
2224 for (HashMap::Entry* p = objects_by_info_.Start();
2225 p != NULL;
2226 p = objects_by_info_.Next(p)) {
2227 v8::RetainedObjectInfo* info =
2228 reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
2229 info->Dispose();
2230 List<HeapObject*>* objects =
2231 reinterpret_cast<List<HeapObject*>* >(p->value);
2232 delete objects;
2233 }
2234 }
2235
2236
2237 HeapEntry* NativeObjectsExplorer::AllocateEntry(
2238 HeapThing ptr, int children_count, int retainers_count) {
2239 if (ptr == kNativesRootObject) {
2240 return snapshot_->AddNativesRootEntry(children_count, retainers_count);
2241 } else {
2242 v8::RetainedObjectInfo* info =
2243 reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
2244 intptr_t elements = info->GetElementCount();
2245 intptr_t size = info->GetSizeInBytes();
2246 return snapshot_->AddEntry(
2247 HeapEntry::kNative,
2248 elements != -1 ?
2249 collection_->names()->GetFormatted(
2250 "%s / %" V8_PTR_PREFIX "d entries",
2251 info->GetLabel(),
2252 info->GetElementCount()) :
2253 collection_->names()->GetCopy(info->GetLabel()),
2254 HeapObjectsMap::GenerateId(info),
2255 size != -1 ? static_cast<int>(size) : 0,
2256 children_count,
2257 retainers_count);
2258 }
2259 }
2260
2261
2262 void NativeObjectsExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
2263 if (EstimateObjectsCount() <= 0) return;
2264 filler->AddEntry(kNativesRootObject, this);
2265 }
2266
2267
2268 int NativeObjectsExplorer::EstimateObjectsCount() {
2269 FillRetainedObjects();
2270 return objects_by_info_.occupancy();
2271 }
2272
2273
2274 void NativeObjectsExplorer::FillRetainedObjects() {
2275 if (embedder_queried_) return;
2276 // Record objects that are joined into ObjectGroups.
2277 Heap::CallGlobalGCPrologueCallback();
2278 List<ObjectGroup*>* groups = GlobalHandles::ObjectGroups();
2279 for (int i = 0; i < groups->length(); ++i) {
2280 ObjectGroup* group = groups->at(i);
2281 if (group->info_ == NULL) continue;
2282 List<HeapObject*>* list = GetListMaybeDisposeInfo(group->info_);
2283 for (int j = 0; j < group->objects_.length(); ++j) {
2284 HeapObject* obj = HeapObject::cast(*group->objects_[j]);
2285 list->Add(obj);
2286 in_groups_.Insert(obj);
2287 }
2288 group->info_ = NULL; // Acquire info object ownership.
2289 }
2290 GlobalHandles::RemoveObjectGroups();
2291 Heap::CallGlobalGCEpilogueCallback();
2292 // Record objects that are not in ObjectGroups, but have class ID.
2293 GlobalHandlesExtractor extractor(this);
2294 GlobalHandles::IterateAllRootsWithClassIds(&extractor);
2295 embedder_queried_ = true;
2296 }
2297
2298
2299 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo(
2300 v8::RetainedObjectInfo* info) {
2301 HashMap::Entry* entry =
2302 objects_by_info_.Lookup(info, InfoHash(info), true);
2303 if (entry->value != NULL) {
2304 info->Dispose();
2305 } else {
2306 entry->value = new List<HeapObject*>(4);
2307 }
2308 return reinterpret_cast<List<HeapObject*>* >(entry->value);
2309 }
2310
2311
2312 bool NativeObjectsExplorer::IterateAndExtractReferences(
2313 SnapshotFillerInterface* filler) {
2314 if (EstimateObjectsCount() <= 0) return true;
2315 filler_ = filler;
2316 FillRetainedObjects();
2317 for (HashMap::Entry* p = objects_by_info_.Start();
2318 p != NULL;
2319 p = objects_by_info_.Next(p)) {
2320 v8::RetainedObjectInfo* info =
2321 reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
2322 SetNativeRootReference(info);
2323 List<HeapObject*>* objects =
2324 reinterpret_cast<List<HeapObject*>* >(p->value);
2325 for (int i = 0; i < objects->length(); ++i) {
2326 SetWrapperNativeReferences(objects->at(i), info);
2327 }
2328 }
2329 SetRootNativesRootReference();
2330 filler_ = NULL;
2331 return true;
2332 }
2333
2334
2335 void NativeObjectsExplorer::SetNativeRootReference(
2336 v8::RetainedObjectInfo* info) {
2337 HeapEntry* child_entry = filler_->FindOrAddEntry(info, this);
2338 ASSERT(child_entry != NULL);
2339 filler_->SetIndexedAutoIndexReference(
2340 HeapGraphEdge::kElement,
2341 kNativesRootObject, snapshot_->natives_root(),
2342 info, child_entry);
2343 }
2344
2345
2346 void NativeObjectsExplorer::SetWrapperNativeReferences(
2347 HeapObject* wrapper, v8::RetainedObjectInfo* info) {
2348 HeapEntry* wrapper_entry = filler_->FindEntry(wrapper);
2349 ASSERT(wrapper_entry != NULL);
2350 HeapEntry* info_entry = filler_->FindOrAddEntry(info, this);
2351 ASSERT(info_entry != NULL);
2352 filler_->SetNamedReference(HeapGraphEdge::kInternal,
2353 wrapper, wrapper_entry,
2354 "Native",
2355 info, info_entry);
2356 filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
2357 info, info_entry,
2358 wrapper, wrapper_entry);
2359 }
2360
2361
2362 void NativeObjectsExplorer::SetRootNativesRootReference() {
2363 filler_->SetIndexedAutoIndexReference(
2364 HeapGraphEdge::kElement,
2365 V8HeapExplorer::kInternalRootObject, snapshot_->root(),
2366 kNativesRootObject, snapshot_->natives_root());
2367 }
2368
2369
2370 void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) {
2371 if (in_groups_.Contains(*p)) return;
2372 v8::RetainedObjectInfo* info =
2373 HeapProfiler::ExecuteWrapperClassCallback(class_id, p);
2374 if (info == NULL) return;
2375 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p));
2376 }
2377
2378
2379 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot,
2380 v8::ActivityControl* control)
2381 : snapshot_(snapshot),
2382 control_(control),
2383 v8_heap_explorer_(snapshot_, this),
2384 dom_explorer_(snapshot_, this) {
2385 }
2386
2387
2388 class SnapshotCounter : public SnapshotFillerInterface {
2389 public:
2390 explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { }
2391 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2392 entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder);
2393 return HeapEntriesMap::kHeapEntryPlaceholder;
2394 }
2395 HeapEntry* FindEntry(HeapThing ptr) {
2396 return entries_->Map(ptr);
2397 }
2398 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2399 HeapEntry* entry = FindEntry(ptr);
2400 return entry != NULL ? entry : AddEntry(ptr, allocator);
2401 }
2402 void SetIndexedReference(HeapGraphEdge::Type,
2403 HeapThing parent_ptr,
2404 HeapEntry*,
2405 int,
2406 HeapThing child_ptr,
2407 HeapEntry*) {
2408 entries_->CountReference(parent_ptr, child_ptr);
2409 }
2410 void SetIndexedAutoIndexReference(HeapGraphEdge::Type,
2411 HeapThing parent_ptr,
2412 HeapEntry*,
2413 HeapThing child_ptr,
2414 HeapEntry*) {
2415 entries_->CountReference(parent_ptr, child_ptr);
2416 }
2417 void SetNamedReference(HeapGraphEdge::Type,
2418 HeapThing parent_ptr,
2419 HeapEntry*,
2420 const char*,
2421 HeapThing child_ptr,
2422 HeapEntry*) {
2423 entries_->CountReference(parent_ptr, child_ptr);
2424 }
2425 void SetNamedAutoIndexReference(HeapGraphEdge::Type,
2426 HeapThing parent_ptr,
2427 HeapEntry*,
2428 HeapThing child_ptr,
2429 HeapEntry*) {
2430 entries_->CountReference(parent_ptr, child_ptr);
2431 }
2432 private:
2433 HeapEntriesMap* entries_;
2434 };
2435
2436
2437 class SnapshotFiller : public SnapshotFillerInterface {
2438 public:
2439 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
2440 : snapshot_(snapshot),
2441 collection_(snapshot->collection()),
2442 entries_(entries) { }
2443 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2444 UNREACHABLE();
2445 return NULL;
2446 }
2447 HeapEntry* FindEntry(HeapThing ptr) {
2448 return entries_->Map(ptr);
2449 }
2450 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2451 HeapEntry* entry = FindEntry(ptr);
2452 return entry != NULL ? entry : AddEntry(ptr, allocator);
2453 }
2454 void SetIndexedReference(HeapGraphEdge::Type type,
2455 HeapThing parent_ptr,
2456 HeapEntry* parent_entry,
2457 int index,
2458 HeapThing child_ptr,
2459 HeapEntry* child_entry) {
2460 int child_index, retainer_index;
2461 entries_->CountReference(
2462 parent_ptr, child_ptr, &child_index, &retainer_index);
2463 parent_entry->SetIndexedReference(
2464 type, child_index, index, child_entry, retainer_index);
2465 }
2466 void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
2467 HeapThing parent_ptr,
2468 HeapEntry* parent_entry,
2469 HeapThing child_ptr,
2470 HeapEntry* child_entry) {
2471 int child_index, retainer_index;
2472 entries_->CountReference(
2473 parent_ptr, child_ptr, &child_index, &retainer_index);
2474 parent_entry->SetIndexedReference(
2475 type, child_index, child_index + 1, child_entry, retainer_index);
2476 }
2477 void SetNamedReference(HeapGraphEdge::Type type,
2478 HeapThing parent_ptr,
2479 HeapEntry* parent_entry,
2480 const char* reference_name,
2481 HeapThing child_ptr,
2482 HeapEntry* child_entry) {
2483 int child_index, retainer_index;
2484 entries_->CountReference(
2485 parent_ptr, child_ptr, &child_index, &retainer_index);
2486 parent_entry->SetNamedReference(
2487 type, child_index, reference_name, child_entry, retainer_index);
2488 }
2489 void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
2490 HeapThing parent_ptr,
2491 HeapEntry* parent_entry,
2492 HeapThing child_ptr,
2493 HeapEntry* child_entry) {
2494 int child_index, retainer_index;
2495 entries_->CountReference(
2496 parent_ptr, child_ptr, &child_index, &retainer_index);
2497 parent_entry->SetNamedReference(type,
2498 child_index,
2499 collection_->names()->GetName(child_index + 1),
2500 child_entry,
2501 retainer_index);
2502 }
2503 private:
2504 HeapSnapshot* snapshot_;
2505 HeapSnapshotsCollection* collection_;
2506 HeapEntriesMap* entries_;
2507 };
2508
2509
2510 bool HeapSnapshotGenerator::GenerateSnapshot() {
2511 AssertNoAllocation no_alloc;
2512
2513 SetProgressTotal(4); // 2 passes + dominators + sizes.
2514
2515 // Pass 1. Iterate heap contents to count entries and references.
2516 if (!CountEntriesAndReferences()) return false;
2517
2518 // Allocate and fill entries in the snapshot, allocate references.
2519 snapshot_->AllocateEntries(entries_.entries_count(),
2520 entries_.total_children_count(),
2521 entries_.total_retainers_count());
2522 entries_.AllocateEntries();
2523
2524 // Pass 2. Fill references.
2525 if (!FillReferences()) return false;
2526
2527 if (!SetEntriesDominators()) return false;
2528 if (!ApproximateRetainedSizes()) return false;
2529
2530 progress_counter_ = progress_total_;
2531 if (!ProgressReport(true)) return false;
2532 return true;
2533 }
2534
2535
2536 void HeapSnapshotGenerator::ProgressStep() {
2537 ++progress_counter_;
2538 }
2539
2540
2541 bool HeapSnapshotGenerator::ProgressReport(bool force) {
2542 const int kProgressReportGranularity = 10000;
2543 if (control_ != NULL
2544 && (force || progress_counter_ % kProgressReportGranularity == 0)) {
2545 return
2546 control_->ReportProgressValue(progress_counter_, progress_total_) ==
2547 v8::ActivityControl::kContinue;
2548 }
2549 return true;
2215 } 2550 }
2216 2551
2217 2552
2218 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { 2553 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
2219 if (control_ == NULL) return; 2554 if (control_ == NULL) return;
2220 2555 progress_total_ = (
2221 HeapIterator iterator(HeapIterator::kFilterUnreachable); 2556 v8_heap_explorer_.EstimateObjectsCount() +
2222 int objects_count = 0; 2557 dom_explorer_.EstimateObjectsCount()) * iterations_count;
2223 for (HeapObject* obj = iterator.next();
2224 obj != NULL;
2225 obj = iterator.next(), ++objects_count) {}
2226 progress_total_ = objects_count * iterations_count;
2227 progress_counter_ = 0; 2558 progress_counter_ = 0;
2228 } 2559 }
2229 2560
2230 2561
2231 bool HeapSnapshotGenerator::CountEntriesAndReferences() { 2562 bool HeapSnapshotGenerator::CountEntriesAndReferences() {
2232 SnapshotCounter counter(&entries_); 2563 SnapshotCounter counter(&entries_);
2233 filler_ = &counter; 2564 v8_heap_explorer_.AddRootEntries(&counter);
2234 filler_->AddEntry(HeapSnapshot::kInternalRootObject); 2565 dom_explorer_.AddRootEntries(&counter);
2235 filler_->AddEntry(HeapSnapshot::kGcRootsObject); 2566 return
2236 return IterateAndExtractReferences(); 2567 v8_heap_explorer_.IterateAndExtractReferences(&counter) &&
2568 dom_explorer_.IterateAndExtractReferences(&counter);
2237 } 2569 }
2238 2570
2239 2571
2240 bool HeapSnapshotGenerator::FillReferences() { 2572 bool HeapSnapshotGenerator::FillReferences() {
2241 SnapshotFiller filler(snapshot_, &entries_); 2573 SnapshotFiller filler(snapshot_, &entries_);
2242 filler_ = &filler; 2574 return
2243 return IterateAndExtractReferences(); 2575 v8_heap_explorer_.IterateAndExtractReferences(&filler) &&
2244 } 2576 dom_explorer_.IterateAndExtractReferences(&filler);
2245 2577 }
2246 2578
2579
2247 void HeapSnapshotGenerator::FillReversePostorderIndexes( 2580 void HeapSnapshotGenerator::FillReversePostorderIndexes(
2248 Vector<HeapEntry*>* entries) { 2581 Vector<HeapEntry*>* entries) {
2249 snapshot_->ClearPaint(); 2582 snapshot_->ClearPaint();
2250 int current_entry = 0; 2583 int current_entry = 0;
2251 List<HeapEntry*> nodes_to_visit; 2584 List<HeapEntry*> nodes_to_visit;
2252 nodes_to_visit.Add(snapshot_->root()); 2585 nodes_to_visit.Add(snapshot_->root());
2253 snapshot_->root()->paint_reachable(); 2586 snapshot_->root()->paint_reachable();
2254 while (!nodes_to_visit.is_empty()) { 2587 while (!nodes_to_visit.is_empty()) {
2255 HeapEntry* entry = nodes_to_visit.last(); 2588 HeapEntry* entry = nodes_to_visit.last();
2256 Vector<HeapGraphEdge> children = entry->children(); 2589 Vector<HeapGraphEdge> children = entry->children();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2319 } 2652 }
2320 } 2653 }
2321 if (new_idom != NULL && dominators->at(i) != new_idom) { 2654 if (new_idom != NULL && dominators->at(i) != new_idom) {
2322 (*dominators)[i] = new_idom; 2655 (*dominators)[i] = new_idom;
2323 ++changed; 2656 ++changed;
2324 } 2657 }
2325 } 2658 }
2326 int remaining = entries_length - changed; 2659 int remaining = entries_length - changed;
2327 if (remaining < 0) remaining = 0; 2660 if (remaining < 0) remaining = 0;
2328 progress_counter_ = base_progress_counter + remaining; 2661 progress_counter_ = base_progress_counter + remaining;
2329 if (!ReportProgress(true)) return false; 2662 if (!ProgressReport(true)) return false;
2330 } 2663 }
2331 return true; 2664 return true;
2332 } 2665 }
2333 2666
2334 2667
2335 bool HeapSnapshotGenerator::SetEntriesDominators() { 2668 bool HeapSnapshotGenerator::SetEntriesDominators() {
2336 // This array is used for maintaining reverse postorder of nodes. 2669 // This array is used for maintaining reverse postorder of nodes.
2337 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); 2670 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length());
2338 FillReversePostorderIndexes(&ordered_entries); 2671 FillReversePostorderIndexes(&ordered_entries);
2339 ScopedVector<HeapEntry*> dominators(ordered_entries.length()); 2672 ScopedVector<HeapEntry*> dominators(ordered_entries.length());
2340 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; 2673 if (!BuildDominatorTree(ordered_entries, &dominators)) return false;
2341 for (int i = 0; i < ordered_entries.length(); ++i) { 2674 for (int i = 0; i < ordered_entries.length(); ++i) {
2342 ASSERT(dominators[i] != NULL); 2675 ASSERT(dominators[i] != NULL);
2343 ordered_entries[i]->set_dominator(dominators[i]); 2676 ordered_entries[i]->set_dominator(dominators[i]);
2344 } 2677 }
2345 return true; 2678 return true;
2346 } 2679 }
2347 2680
2348 2681
2349 bool HeapSnapshotGenerator::ApproximateRetainedSizes() { 2682 bool HeapSnapshotGenerator::ApproximateRetainedSizes() {
2350 // As for the dominators tree we only know parent nodes, not 2683 // As for the dominators tree we only know parent nodes, not
2351 // children, to sum up total sizes we "bubble" node's self size 2684 // children, to sum up total sizes we "bubble" node's self size
2352 // adding it to all of its parents. 2685 // adding it to all of its parents.
2353 for (int i = 0; i < snapshot_->entries()->length(); ++i) { 2686 for (int i = 0; i < snapshot_->entries()->length(); ++i) {
2354 HeapEntry* entry = snapshot_->entries()->at(i); 2687 HeapEntry* entry = snapshot_->entries()->at(i);
2355 entry->set_retained_size(entry->self_size()); 2688 entry->set_retained_size(entry->self_size());
2356 } 2689 }
2357 for (int i = 0; 2690 for (int i = 0;
2358 i < snapshot_->entries()->length(); 2691 i < snapshot_->entries()->length();
2359 ++i, IncProgressCounter()) { 2692 ++i, ProgressStep()) {
2360 HeapEntry* entry = snapshot_->entries()->at(i); 2693 HeapEntry* entry = snapshot_->entries()->at(i);
2361 int entry_size = entry->self_size(); 2694 int entry_size = entry->self_size();
2362 for (HeapEntry* dominator = entry->dominator(); 2695 for (HeapEntry* dominator = entry->dominator();
2363 dominator != entry; 2696 dominator != entry;
2364 entry = dominator, dominator = entry->dominator()) { 2697 entry = dominator, dominator = entry->dominator()) {
2365 dominator->add_retained_size(entry_size); 2698 dominator->add_retained_size(entry_size);
2366 } 2699 }
2367 if (!ReportProgress()) return false; 2700 if (!ProgressReport()) return false;
2368 } 2701 }
2369 return true; 2702 return true;
2370 } 2703 }
2371 2704
2372 2705
2373 bool HeapSnapshotGenerator::IterateAndExtractReferences() {
2374 HeapIterator iterator(HeapIterator::kFilterUnreachable);
2375 bool interrupted = false;
2376 // Heap iteration with filtering must be finished in any case.
2377 for (HeapObject* obj = iterator.next();
2378 obj != NULL;
2379 obj = iterator.next(), IncProgressCounter()) {
2380 if (!interrupted) {
2381 ExtractReferences(obj);
2382 if (!ReportProgress()) interrupted = true;
2383 }
2384 }
2385 if (interrupted) return false;
2386 SetRootGcRootsReference();
2387 RootsReferencesExtractor extractor(this);
2388 Heap::IterateRoots(&extractor, VISIT_ALL);
2389 return ReportProgress();
2390 }
2391
2392
2393 void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) { 2706 void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) {
2394 raw_additions_root_ = 2707 raw_additions_root_ =
2395 NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0)); 2708 NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0));
2396 additions_root()->Init( 2709 additions_root()->Init(
2397 snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0); 2710 snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0);
2398 raw_deletions_root_ = 2711 raw_deletions_root_ =
2399 NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0)); 2712 NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0));
2400 deletions_root()->Init( 2713 deletions_root()->Init(
2401 snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0); 2714 snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0);
2402 } 2715 }
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
2671 "," JSON_S("children")) 2984 "," JSON_S("children"))
2672 "," JSON_S("types") ":" JSON_A( 2985 "," JSON_S("types") ":" JSON_A(
2673 JSON_A( 2986 JSON_A(
2674 JSON_S("hidden") 2987 JSON_S("hidden")
2675 "," JSON_S("array") 2988 "," JSON_S("array")
2676 "," JSON_S("string") 2989 "," JSON_S("string")
2677 "," JSON_S("object") 2990 "," JSON_S("object")
2678 "," JSON_S("code") 2991 "," JSON_S("code")
2679 "," JSON_S("closure") 2992 "," JSON_S("closure")
2680 "," JSON_S("regexp") 2993 "," JSON_S("regexp")
2681 "," JSON_S("number")) 2994 "," JSON_S("number")
2995 "," JSON_S("native"))
2682 "," JSON_S("string") 2996 "," JSON_S("string")
2683 "," JSON_S("number") 2997 "," JSON_S("number")
2684 "," JSON_S("number") 2998 "," JSON_S("number")
2685 "," JSON_S("number") 2999 "," JSON_S("number")
2686 "," JSON_S("number") 3000 "," JSON_S("number")
2687 "," JSON_S("number") 3001 "," JSON_S("number")
2688 "," JSON_O( 3002 "," JSON_O(
2689 JSON_S("fields") ":" JSON_A( 3003 JSON_S("fields") ":" JSON_A(
2690 JSON_S("type") 3004 JSON_S("type")
2691 "," JSON_S("name_or_index") 3005 "," JSON_S("name_or_index")
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
2833 3147
2834 3148
2835 String* GetConstructorNameForHeapProfile(JSObject* object) { 3149 String* GetConstructorNameForHeapProfile(JSObject* object) {
2836 if (object->IsJSFunction()) return Heap::closure_symbol(); 3150 if (object->IsJSFunction()) return Heap::closure_symbol();
2837 return object->constructor_name(); 3151 return object->constructor_name();
2838 } 3152 }
2839 3153
2840 } } // namespace v8::internal 3154 } } // namespace v8::internal
2841 3155
2842 #endif // ENABLE_LOGGING_AND_PROFILING 3156 #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