OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 939 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
950 index_ = index; | 950 index_ = index; |
951 to_ = to; | 951 to_ = to; |
952 } | 952 } |
953 | 953 |
954 | 954 |
955 void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) { | 955 void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) { |
956 Init(child_index, kElement, index, to); | 956 Init(child_index, kElement, index, to); |
957 } | 957 } |
958 | 958 |
959 | 959 |
960 HeapEntry* HeapGraphEdge::From() { | |
961 return reinterpret_cast<HeapEntry*>(this - child_index_) - 1; | |
962 } | |
963 | |
964 | |
965 void HeapEntry::Init(HeapSnapshot* snapshot, | 960 void HeapEntry::Init(HeapSnapshot* snapshot, |
966 Type type, | 961 Type type, |
967 const char* name, | 962 const char* name, |
968 SnapshotObjectId id, | 963 SnapshotObjectId id, |
969 int self_size, | 964 int self_size, |
970 int children_count, | 965 int children_count, |
971 int retainers_count) { | 966 int retainers_count) { |
972 snapshot_ = snapshot; | 967 snapshot_ = snapshot; |
973 type_ = type; | 968 type_ = type; |
974 painted_ = false; | 969 painted_ = false; |
970 reachable_from_window_ = false; | |
975 name_ = name; | 971 name_ = name; |
976 self_size_ = self_size; | 972 self_size_ = self_size; |
977 retained_size_ = 0; | 973 retained_size_ = 0; |
978 entry_index_ = -1; | 974 entry_index_ = -1; |
979 children_count_ = children_count; | 975 children_count_ = children_count; |
980 retainers_count_ = retainers_count; | 976 retainers_count_ = retainers_count; |
981 dominator_ = NULL; | 977 dominator_ = NULL; |
982 id_ = id; | 978 id_ = id; |
983 } | 979 } |
984 | 980 |
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2279 break; | 2275 break; |
2280 } | 2276 } |
2281 } | 2277 } |
2282 } else { | 2278 } else { |
2283 StringDictionary* dictionary = js_obj->property_dictionary(); | 2279 StringDictionary* dictionary = js_obj->property_dictionary(); |
2284 int length = dictionary->Capacity(); | 2280 int length = dictionary->Capacity(); |
2285 for (int i = 0; i < length; ++i) { | 2281 for (int i = 0; i < length; ++i) { |
2286 Object* k = dictionary->KeyAt(i); | 2282 Object* k = dictionary->KeyAt(i); |
2287 if (dictionary->IsKey(k)) { | 2283 if (dictionary->IsKey(k)) { |
2288 Object* target = dictionary->ValueAt(i); | 2284 Object* target = dictionary->ValueAt(i); |
2289 SetPropertyReference( | |
2290 js_obj, entry, String::cast(k), target); | |
2291 // We assume that global objects can only have slow properties. | 2285 // We assume that global objects can only have slow properties. |
2292 if (target->IsJSGlobalPropertyCell()) { | 2286 Object* value = target->IsJSGlobalPropertyCell() |
2293 SetPropertyShortcutReference(js_obj, | 2287 ? JSGlobalPropertyCell::cast(target)->value() |
2294 entry, | 2288 : target; |
2295 String::cast(k), | 2289 if (String::cast(k)->length() > 0) { |
2296 JSGlobalPropertyCell::cast( | 2290 SetPropertyReference(js_obj, entry, String::cast(k), value); |
2297 target)->value()); | 2291 } else { |
2292 TagObject(value, "(hidden properties)"); | |
2293 SetInternalReference(js_obj, entry, "hidden_properties", value); | |
2298 } | 2294 } |
2299 } | 2295 } |
2300 } | 2296 } |
2301 } | 2297 } |
2302 } | 2298 } |
2303 | 2299 |
2304 | 2300 |
2305 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, | 2301 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, |
2306 HeapEntry* entry) { | 2302 HeapEntry* entry) { |
2307 if (js_obj->HasFastElements()) { | 2303 if (js_obj->HasFastElements()) { |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2738 isolate->factory()->NewStringFromAscii(CStrVector("document")); | 2734 isolate->factory()->NewStringFromAscii(CStrVector("document")); |
2739 Handle<String> url_string = | 2735 Handle<String> url_string = |
2740 isolate->factory()->NewStringFromAscii(CStrVector("URL")); | 2736 isolate->factory()->NewStringFromAscii(CStrVector("URL")); |
2741 const char** urls = NewArray<const char*>(enumerator.count()); | 2737 const char** urls = NewArray<const char*>(enumerator.count()); |
2742 for (int i = 0, l = enumerator.count(); i < l; ++i) { | 2738 for (int i = 0, l = enumerator.count(); i < l; ++i) { |
2743 urls[i] = NULL; | 2739 urls[i] = NULL; |
2744 HandleScope scope; | 2740 HandleScope scope; |
2745 Handle<JSGlobalObject> global_obj = enumerator.at(i); | 2741 Handle<JSGlobalObject> global_obj = enumerator.at(i); |
2746 Object* obj_document; | 2742 Object* obj_document; |
2747 if (global_obj->GetProperty(*document_string)->ToObject(&obj_document) && | 2743 if (global_obj->GetProperty(*document_string)->ToObject(&obj_document) && |
2748 obj_document->IsJSObject()) { | 2744 obj_document->IsJSObject()) { |
2749 JSObject* document = JSObject::cast(obj_document); | 2745 JSObject* document = JSObject::cast(obj_document); |
2750 Object* obj_url; | 2746 Object* obj_url; |
2751 if (document->GetProperty(*url_string)->ToObject(&obj_url) && | 2747 if (document->GetProperty(*url_string)->ToObject(&obj_url) && |
2752 obj_url->IsString()) { | 2748 obj_url->IsString()) { |
2753 urls[i] = collection_->names()->GetName(String::cast(obj_url)); | 2749 urls[i] = collection_->names()->GetName(String::cast(obj_url)); |
2754 } | 2750 } |
2755 } | 2751 } |
2756 } | 2752 } |
2757 | 2753 |
2758 AssertNoAllocation no_allocation; | 2754 AssertNoAllocation no_allocation; |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3292 // in turn may relocate objects in property maps thus changing the heap | 3288 // in turn may relocate objects in property maps thus changing the heap |
3293 // layout and affecting retainer counts. This is not acceptable because | 3289 // layout and affecting retainer counts. This is not acceptable because |
3294 // number of retainers must not change between count and fill passes. | 3290 // number of retainers must not change between count and fill passes. |
3295 // To avoid this there's a separate postpass that set object names. | 3291 // To avoid this there's a separate postpass that set object names. |
3296 return v8_heap_explorer_.IterateAndExtractReferences(&filler) | 3292 return v8_heap_explorer_.IterateAndExtractReferences(&filler) |
3297 && dom_explorer_.IterateAndExtractReferences(&filler) | 3293 && dom_explorer_.IterateAndExtractReferences(&filler) |
3298 && v8_heap_explorer_.IterateAndSetObjectNames(&filler); | 3294 && v8_heap_explorer_.IterateAndSetObjectNames(&filler); |
3299 } | 3295 } |
3300 | 3296 |
3301 | 3297 |
3302 void HeapSnapshotGenerator::FillReversePostorderIndexes( | 3298 void HeapSnapshotGenerator::MarkWindowReachableObjects() { |
3299 List<HeapEntry*> worklist; | |
3300 | |
3301 Vector<HeapGraphEdge> children = snapshot_->root()->children(); | |
3302 for (int i = 0; i < children.length(); ++i) { | |
3303 if (children[i].type() == HeapGraphEdge::kShortcut) { | |
mnaganov (inactive)
2012/04/16 08:40:26
For the sake of clarity, I'd rename 'SetRootShortc
alexeif
2012/04/16 10:49:11
Done.
| |
3304 worklist.Add(children[i].to()); | |
3305 } | |
3306 } | |
3307 | |
3308 while (!worklist.is_empty()) { | |
3309 HeapEntry* entry = worklist.RemoveLast(); | |
3310 if (entry->reachable_from_window()) continue; | |
3311 entry->set_reachable_from_window(); | |
3312 Vector<HeapGraphEdge> children = entry->children(); | |
3313 for (int i = 0; i < children.length(); ++i) { | |
3314 HeapEntry* child = children[i].to(); | |
3315 if (!child->reachable_from_window()) { | |
3316 worklist.Add(child); | |
3317 } | |
3318 } | |
3319 } | |
3320 } | |
3321 | |
3322 | |
3323 static bool IsRetainingEdge(HeapGraphEdge* edge) { | |
3324 if (edge->type() == HeapGraphEdge::kShortcut) return false; | |
3325 // The edge is not retaining if it goes from system domain | |
3326 // (i.e. an object not reachable from window) to the user domain | |
3327 // (i.e. a reachable object). | |
3328 return edge->from()->reachable_from_window() | |
3329 || !edge->to()->reachable_from_window(); | |
3330 } | |
3331 | |
3332 | |
3333 void HeapSnapshotGenerator::FillPostorderIndexes( | |
3303 Vector<HeapEntry*>* entries) { | 3334 Vector<HeapEntry*>* entries) { |
3304 snapshot_->ClearPaint(); | 3335 snapshot_->ClearPaint(); |
3305 int current_entry = 0; | 3336 int current_entry = 0; |
3306 List<HeapEntry*> nodes_to_visit; | 3337 List<HeapEntry*> nodes_to_visit; |
3307 nodes_to_visit.Add(snapshot_->root()); | 3338 HeapEntry* root = snapshot_->root(); |
3339 nodes_to_visit.Add(root); | |
3308 snapshot_->root()->paint(); | 3340 snapshot_->root()->paint(); |
3309 while (!nodes_to_visit.is_empty()) { | 3341 while (!nodes_to_visit.is_empty()) { |
3310 HeapEntry* entry = nodes_to_visit.last(); | 3342 HeapEntry* entry = nodes_to_visit.last(); |
3311 Vector<HeapGraphEdge> children = entry->children(); | 3343 Vector<HeapGraphEdge> children = entry->children(); |
3312 bool has_new_edges = false; | 3344 bool has_new_edges = false; |
3313 for (int i = 0; i < children.length(); ++i) { | 3345 for (int i = 0; i < children.length(); ++i) { |
3314 if (children[i].type() == HeapGraphEdge::kShortcut) continue; | 3346 if (entry != root && !IsRetainingEdge(&children[i])) continue; |
3315 HeapEntry* child = children[i].to(); | 3347 HeapEntry* child = children[i].to(); |
3316 if (!child->painted()) { | 3348 if (!child->painted()) { |
3317 nodes_to_visit.Add(child); | 3349 nodes_to_visit.Add(child); |
3318 child->paint(); | 3350 child->paint(); |
3319 has_new_edges = true; | 3351 has_new_edges = true; |
3320 } | 3352 } |
3321 } | 3353 } |
3322 if (!has_new_edges) { | 3354 if (!has_new_edges) { |
3323 entry->set_ordered_index(current_entry); | 3355 entry->set_ordered_index(current_entry); |
3324 (*entries)[current_entry++] = entry; | 3356 (*entries)[current_entry++] = entry; |
(...skipping 14 matching lines...) Expand all Loading... | |
3339 } | 3371 } |
3340 | 3372 |
3341 | 3373 |
3342 // The algorithm is based on the article: | 3374 // The algorithm is based on the article: |
3343 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" | 3375 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" |
3344 // Softw. Pract. Exper. 4 (2001), pp. 1-10. | 3376 // Softw. Pract. Exper. 4 (2001), pp. 1-10. |
3345 bool HeapSnapshotGenerator::BuildDominatorTree( | 3377 bool HeapSnapshotGenerator::BuildDominatorTree( |
3346 const Vector<HeapEntry*>& entries, | 3378 const Vector<HeapEntry*>& entries, |
3347 Vector<int>* dominators) { | 3379 Vector<int>* dominators) { |
3348 if (entries.length() == 0) return true; | 3380 if (entries.length() == 0) return true; |
3381 HeapEntry* root = snapshot_->root(); | |
3349 const int entries_length = entries.length(), root_index = entries_length - 1; | 3382 const int entries_length = entries.length(), root_index = entries_length - 1; |
3350 static const int kNoDominator = -1; | 3383 static const int kNoDominator = -1; |
3351 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; | 3384 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; |
3352 (*dominators)[root_index] = root_index; | 3385 (*dominators)[root_index] = root_index; |
3353 | 3386 |
3354 // The affected array is used to mark entries which dominators | 3387 // The affected array is used to mark entries which dominators |
3355 // have to be racalculated because of changes in their retainers. | 3388 // have to be racalculated because of changes in their retainers. |
3356 ScopedVector<bool> affected(entries_length); | 3389 ScopedVector<bool> affected(entries_length); |
3357 for (int i = 0; i < affected.length(); ++i) affected[i] = false; | 3390 for (int i = 0; i < affected.length(); ++i) affected[i] = false; |
3358 // Mark the root direct children as affected. | 3391 // Mark the root direct children as affected. |
3359 Vector<HeapGraphEdge> children = entries[root_index]->children(); | 3392 Vector<HeapGraphEdge> children = entries[root_index]->children(); |
3360 for (int i = 0; i < children.length(); ++i) { | 3393 for (int i = 0; i < children.length(); ++i) { |
3361 affected[children[i].to()->ordered_index()] = true; | 3394 affected[children[i].to()->ordered_index()] = true; |
3362 } | 3395 } |
3363 | 3396 |
3364 bool changed = true; | 3397 bool changed = true; |
3365 while (changed) { | 3398 while (changed) { |
3366 changed = false; | 3399 changed = false; |
3367 if (!ProgressReport(true)) return false; | 3400 if (!ProgressReport(true)) return false; |
3368 for (int i = root_index - 1; i >= 0; --i) { | 3401 for (int i = root_index - 1; i >= 0; --i) { |
3369 if (!affected[i]) continue; | 3402 if (!affected[i]) continue; |
3370 affected[i] = false; | 3403 affected[i] = false; |
3371 // If dominator of the entry has already been set to root, | 3404 // If dominator of the entry has already been set to root, |
3372 // then it can't propagate any further. | 3405 // then it can't propagate any further. |
3373 if ((*dominators)[i] == root_index) continue; | 3406 if ((*dominators)[i] == root_index) continue; |
3374 int new_idom_index = kNoDominator; | 3407 int new_idom_index = kNoDominator; |
3375 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); | 3408 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); |
3376 for (int j = 0; j < rets.length(); ++j) { | 3409 for (int j = 0; j < rets.length(); ++j) { |
3377 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; | 3410 if (rets[j]->from() != root && !IsRetainingEdge(rets[j])) continue; |
3378 int ret_index = rets[j]->From()->ordered_index(); | 3411 int ret_index = rets[j]->from()->ordered_index(); |
3379 if (dominators->at(ret_index) != kNoDominator) { | 3412 if (dominators->at(ret_index) != kNoDominator) { |
3380 new_idom_index = new_idom_index == kNoDominator | 3413 new_idom_index = new_idom_index == kNoDominator |
3381 ? ret_index | 3414 ? ret_index |
3382 : Intersect(ret_index, new_idom_index, *dominators); | 3415 : Intersect(ret_index, new_idom_index, *dominators); |
3383 // If idom has already reached the root, it doesn't make sense | 3416 // If idom has already reached the root, it doesn't make sense |
3384 // to check other retainers. | 3417 // to check other retainers. |
3385 if (new_idom_index == root_index) break; | 3418 if (new_idom_index == root_index) break; |
3386 } | 3419 } |
3387 } | 3420 } |
3388 if (new_idom_index != kNoDominator | 3421 if (new_idom_index != kNoDominator |
3389 && dominators->at(i) != new_idom_index) { | 3422 && dominators->at(i) != new_idom_index) { |
3390 (*dominators)[i] = new_idom_index; | 3423 (*dominators)[i] = new_idom_index; |
3391 changed = true; | 3424 changed = true; |
3392 Vector<HeapGraphEdge> children = entries[i]->children(); | 3425 Vector<HeapGraphEdge> children = entries[i]->children(); |
3393 for (int j = 0; j < children.length(); ++j) { | 3426 for (int j = 0; j < children.length(); ++j) { |
3394 affected[children[j].to()->ordered_index()] = true; | 3427 affected[children[j].to()->ordered_index()] = true; |
3395 } | 3428 } |
3396 } | 3429 } |
3397 } | 3430 } |
3398 } | 3431 } |
3399 return true; | 3432 return true; |
3400 } | 3433 } |
3401 | 3434 |
3402 | 3435 |
3403 bool HeapSnapshotGenerator::SetEntriesDominators() { | 3436 bool HeapSnapshotGenerator::SetEntriesDominators() { |
3404 // This array is used for maintaining reverse postorder of nodes. | 3437 MarkWindowReachableObjects(); |
3438 // This array is used for maintaining postorder of nodes. | |
3405 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); | 3439 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); |
3406 FillReversePostorderIndexes(&ordered_entries); | 3440 FillPostorderIndexes(&ordered_entries); |
3407 ScopedVector<int> dominators(ordered_entries.length()); | 3441 ScopedVector<int> dominators(ordered_entries.length()); |
3408 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; | 3442 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; |
3409 for (int i = 0; i < ordered_entries.length(); ++i) { | 3443 for (int i = 0; i < ordered_entries.length(); ++i) { |
3410 ASSERT(dominators[i] >= 0); | 3444 ASSERT(dominators[i] >= 0); |
3411 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]); | 3445 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]); |
3412 } | 3446 } |
3413 return true; | 3447 return true; |
3414 } | 3448 } |
3415 | 3449 |
3416 | 3450 |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3887 | 3921 |
3888 | 3922 |
3889 void HeapSnapshotJSONSerializer::SortHashMap( | 3923 void HeapSnapshotJSONSerializer::SortHashMap( |
3890 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 3924 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
3891 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 3925 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
3892 sorted_entries->Add(p); | 3926 sorted_entries->Add(p); |
3893 sorted_entries->Sort(SortUsingEntryValue); | 3927 sorted_entries->Sort(SortUsingEntryValue); |
3894 } | 3928 } |
3895 | 3929 |
3896 } } // namespace v8::internal | 3930 } } // namespace v8::internal |
OLD | NEW |