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

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

Issue 10086006: External references should not affect dominance relation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 8 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
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698