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

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

Issue 10007009: External references should not affect dominance relation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressing comments. 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
« 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 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 children_count_ = children_count; 974 children_count_ = children_count;
979 retainers_count_ = retainers_count; 975 retainers_count_ = retainers_count;
980 dominator_ = NULL; 976 dominator_ = NULL;
981 id_ = id; 977 id_ = id;
982 } 978 }
983 979
984 980
(...skipping 1166 matching lines...) Expand 10 before | Expand all | Expand 10 after
2151 break; 2147 break;
2152 } 2148 }
2153 } 2149 }
2154 } else { 2150 } else {
2155 StringDictionary* dictionary = js_obj->property_dictionary(); 2151 StringDictionary* dictionary = js_obj->property_dictionary();
2156 int length = dictionary->Capacity(); 2152 int length = dictionary->Capacity();
2157 for (int i = 0; i < length; ++i) { 2153 for (int i = 0; i < length; ++i) {
2158 Object* k = dictionary->KeyAt(i); 2154 Object* k = dictionary->KeyAt(i);
2159 if (dictionary->IsKey(k)) { 2155 if (dictionary->IsKey(k)) {
2160 Object* target = dictionary->ValueAt(i); 2156 Object* target = dictionary->ValueAt(i);
2161 SetPropertyReference(
2162 js_obj, entry, String::cast(k), target);
2163 // We assume that global objects can only have slow properties. 2157 // We assume that global objects can only have slow properties.
2164 if (target->IsJSGlobalPropertyCell()) { 2158 Object* value = target->IsJSGlobalPropertyCell()
2165 SetPropertyShortcutReference(js_obj, 2159 ? JSGlobalPropertyCell::cast(target)->value()
2166 entry, 2160 : target;
2167 String::cast(k), 2161 if (String::cast(k)->length() > 0) {
2168 JSGlobalPropertyCell::cast( 2162 SetPropertyReference(js_obj, entry, String::cast(k), value);
2169 target)->value()); 2163 } else {
2164 TagObject(value, "(hidden properties)");
2165 SetInternalReference(js_obj, entry, "hidden_properties", value);
2170 } 2166 }
2171 } 2167 }
2172 } 2168 }
2173 } 2169 }
2174 } 2170 }
2175 2171
2176 2172
2177 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, 2173 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
2178 HeapEntry* entry) { 2174 HeapEntry* entry) {
2179 if (js_obj->HasFastElements()) { 2175 if (js_obj->HasFastElements()) {
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
2610 isolate->factory()->NewStringFromAscii(CStrVector("document")); 2606 isolate->factory()->NewStringFromAscii(CStrVector("document"));
2611 Handle<String> url_string = 2607 Handle<String> url_string =
2612 isolate->factory()->NewStringFromAscii(CStrVector("URL")); 2608 isolate->factory()->NewStringFromAscii(CStrVector("URL"));
2613 const char** urls = NewArray<const char*>(enumerator.count()); 2609 const char** urls = NewArray<const char*>(enumerator.count());
2614 for (int i = 0, l = enumerator.count(); i < l; ++i) { 2610 for (int i = 0, l = enumerator.count(); i < l; ++i) {
2615 urls[i] = NULL; 2611 urls[i] = NULL;
2616 HandleScope scope; 2612 HandleScope scope;
2617 Handle<JSGlobalObject> global_obj = enumerator.at(i); 2613 Handle<JSGlobalObject> global_obj = enumerator.at(i);
2618 Object* obj_document; 2614 Object* obj_document;
2619 if (global_obj->GetProperty(*document_string)->ToObject(&obj_document) && 2615 if (global_obj->GetProperty(*document_string)->ToObject(&obj_document) &&
2620 obj_document->IsJSObject()) { 2616 obj_document->IsJSObject()) {
2621 JSObject* document = JSObject::cast(obj_document); 2617 JSObject* document = JSObject::cast(obj_document);
2622 Object* obj_url; 2618 Object* obj_url;
2623 if (document->GetProperty(*url_string)->ToObject(&obj_url) && 2619 if (document->GetProperty(*url_string)->ToObject(&obj_url) &&
2624 obj_url->IsString()) { 2620 obj_url->IsString()) {
2625 urls[i] = collection_->names()->GetName(String::cast(obj_url)); 2621 urls[i] = collection_->names()->GetName(String::cast(obj_url));
2626 } 2622 }
2627 } 2623 }
2628 } 2624 }
2629 2625
2630 AssertNoAllocation no_allocation; 2626 AssertNoAllocation no_allocation;
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
3164 // in turn may relocate objects in property maps thus changing the heap 3160 // in turn may relocate objects in property maps thus changing the heap
3165 // layout and affecting retainer counts. This is not acceptable because 3161 // layout and affecting retainer counts. This is not acceptable because
3166 // number of retainers must not change between count and fill passes. 3162 // number of retainers must not change between count and fill passes.
3167 // To avoid this there's a separate postpass that set object names. 3163 // To avoid this there's a separate postpass that set object names.
3168 return v8_heap_explorer_.IterateAndExtractReferences(&filler) 3164 return v8_heap_explorer_.IterateAndExtractReferences(&filler)
3169 && dom_explorer_.IterateAndExtractReferences(&filler) 3165 && dom_explorer_.IterateAndExtractReferences(&filler)
3170 && v8_heap_explorer_.IterateAndSetObjectNames(&filler); 3166 && v8_heap_explorer_.IterateAndSetObjectNames(&filler);
3171 } 3167 }
3172 3168
3173 3169
3174 void HeapSnapshotGenerator::FillReversePostorderIndexes( 3170 void HeapSnapshotGenerator::MarkWindowReachableObjects() {
3171 List<HeapEntry*> worklist;
3172
3173 Vector<HeapGraphEdge> children = snapshot_->root()->children();
3174 for (int i = 0; i < children.length(); ++i) {
3175 if (children[i].type() == HeapGraphEdge::kShortcut) {
3176 worklist.Add(children[i].to());
3177 }
3178 }
3179
3180 while (!worklist.is_empty()) {
3181 HeapEntry* entry = worklist.RemoveLast();
3182 if (entry->reachable_from_window()) continue;
3183 entry->set_reachable_from_window();
3184 Vector<HeapGraphEdge> children = entry->children();
3185 for (int i = 0; i < children.length(); ++i) {
3186 HeapEntry* child = children[i].to();
3187 if (!child->reachable_from_window()) {
3188 worklist.Add(child);
3189 }
3190 }
3191 }
3192 }
3193
3194
3195 static bool IsRetainingEdge(HeapGraphEdge* edge) {
3196 if (edge->type() == HeapGraphEdge::kShortcut) return false;
3197 // The edge is not retaining if it goes from system domain
3198 // (i.e. an object not reachable from window) to the user domain
3199 // (i.e. a reachable object).
3200 return edge->from()->reachable_from_window()
3201 || !edge->to()->reachable_from_window();
3202 }
3203
3204
3205 void HeapSnapshotGenerator::FillPostorderIndexes(
3175 Vector<HeapEntry*>* entries) { 3206 Vector<HeapEntry*>* entries) {
3176 snapshot_->ClearPaint(); 3207 snapshot_->ClearPaint();
3177 int current_entry = 0; 3208 int current_entry = 0;
3178 List<HeapEntry*> nodes_to_visit; 3209 List<HeapEntry*> nodes_to_visit;
3179 nodes_to_visit.Add(snapshot_->root()); 3210 HeapEntry* root = snapshot_->root();
3211 nodes_to_visit.Add(root);
3180 snapshot_->root()->paint(); 3212 snapshot_->root()->paint();
3181 while (!nodes_to_visit.is_empty()) { 3213 while (!nodes_to_visit.is_empty()) {
3182 HeapEntry* entry = nodes_to_visit.last(); 3214 HeapEntry* entry = nodes_to_visit.last();
3183 Vector<HeapGraphEdge> children = entry->children(); 3215 Vector<HeapGraphEdge> children = entry->children();
3184 bool has_new_edges = false; 3216 bool has_new_edges = false;
3185 for (int i = 0; i < children.length(); ++i) { 3217 for (int i = 0; i < children.length(); ++i) {
3186 if (children[i].type() == HeapGraphEdge::kShortcut) continue; 3218 if (entry != root && !IsRetainingEdge(&children[i])) continue;
3187 HeapEntry* child = children[i].to(); 3219 HeapEntry* child = children[i].to();
3188 if (!child->painted()) { 3220 if (!child->painted()) {
3189 nodes_to_visit.Add(child); 3221 nodes_to_visit.Add(child);
3190 child->paint(); 3222 child->paint();
3191 has_new_edges = true; 3223 has_new_edges = true;
3192 } 3224 }
3193 } 3225 }
3194 if (!has_new_edges) { 3226 if (!has_new_edges) {
3195 entry->set_ordered_index(current_entry); 3227 entry->set_ordered_index(current_entry);
3196 (*entries)[current_entry++] = entry; 3228 (*entries)[current_entry++] = entry;
(...skipping 14 matching lines...) Expand all
3211 } 3243 }
3212 3244
3213 3245
3214 // The algorithm is based on the article: 3246 // The algorithm is based on the article:
3215 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" 3247 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm"
3216 // Softw. Pract. Exper. 4 (2001), pp. 1-10. 3248 // Softw. Pract. Exper. 4 (2001), pp. 1-10.
3217 bool HeapSnapshotGenerator::BuildDominatorTree( 3249 bool HeapSnapshotGenerator::BuildDominatorTree(
3218 const Vector<HeapEntry*>& entries, 3250 const Vector<HeapEntry*>& entries,
3219 Vector<int>* dominators) { 3251 Vector<int>* dominators) {
3220 if (entries.length() == 0) return true; 3252 if (entries.length() == 0) return true;
3253 HeapEntry* root = snapshot_->root();
3221 const int entries_length = entries.length(), root_index = entries_length - 1; 3254 const int entries_length = entries.length(), root_index = entries_length - 1;
3222 static const int kNoDominator = -1; 3255 static const int kNoDominator = -1;
3223 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; 3256 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator;
3224 (*dominators)[root_index] = root_index; 3257 (*dominators)[root_index] = root_index;
3225 3258
3226 // The affected array is used to mark entries which dominators 3259 // The affected array is used to mark entries which dominators
3227 // have to be racalculated because of changes in their retainers. 3260 // have to be racalculated because of changes in their retainers.
3228 ScopedVector<bool> affected(entries_length); 3261 ScopedVector<bool> affected(entries_length);
3229 for (int i = 0; i < affected.length(); ++i) affected[i] = false; 3262 for (int i = 0; i < affected.length(); ++i) affected[i] = false;
3230 // Mark the root direct children as affected. 3263 // Mark the root direct children as affected.
3231 Vector<HeapGraphEdge> children = entries[root_index]->children(); 3264 Vector<HeapGraphEdge> children = entries[root_index]->children();
3232 for (int i = 0; i < children.length(); ++i) { 3265 for (int i = 0; i < children.length(); ++i) {
3233 affected[children[i].to()->ordered_index()] = true; 3266 affected[children[i].to()->ordered_index()] = true;
3234 } 3267 }
3235 3268
3236 bool changed = true; 3269 bool changed = true;
3237 while (changed) { 3270 while (changed) {
3238 changed = false; 3271 changed = false;
3239 if (!ProgressReport(true)) return false; 3272 if (!ProgressReport(true)) return false;
3240 for (int i = root_index - 1; i >= 0; --i) { 3273 for (int i = root_index - 1; i >= 0; --i) {
3241 if (!affected[i]) continue; 3274 if (!affected[i]) continue;
3242 affected[i] = false; 3275 affected[i] = false;
3243 // If dominator of the entry has already been set to root, 3276 // If dominator of the entry has already been set to root,
3244 // then it can't propagate any further. 3277 // then it can't propagate any further.
3245 if ((*dominators)[i] == root_index) continue; 3278 if ((*dominators)[i] == root_index) continue;
3246 int new_idom_index = kNoDominator; 3279 int new_idom_index = kNoDominator;
3247 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); 3280 Vector<HeapGraphEdge*> rets = entries[i]->retainers();
3248 for (int j = 0; j < rets.length(); ++j) { 3281 for (int j = 0; j < rets.length(); ++j) {
3249 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; 3282 if (rets[j]->from() != root && !IsRetainingEdge(rets[j])) continue;
3250 int ret_index = rets[j]->From()->ordered_index(); 3283 int ret_index = rets[j]->from()->ordered_index();
3251 if (dominators->at(ret_index) != kNoDominator) { 3284 if (dominators->at(ret_index) != kNoDominator) {
3252 new_idom_index = new_idom_index == kNoDominator 3285 new_idom_index = new_idom_index == kNoDominator
3253 ? ret_index 3286 ? ret_index
3254 : Intersect(ret_index, new_idom_index, *dominators); 3287 : Intersect(ret_index, new_idom_index, *dominators);
3255 // If idom has already reached the root, it doesn't make sense 3288 // If idom has already reached the root, it doesn't make sense
3256 // to check other retainers. 3289 // to check other retainers.
3257 if (new_idom_index == root_index) break; 3290 if (new_idom_index == root_index) break;
3258 } 3291 }
3259 } 3292 }
3260 if (new_idom_index != kNoDominator 3293 if (new_idom_index != kNoDominator
3261 && dominators->at(i) != new_idom_index) { 3294 && dominators->at(i) != new_idom_index) {
3262 (*dominators)[i] = new_idom_index; 3295 (*dominators)[i] = new_idom_index;
3263 changed = true; 3296 changed = true;
3264 Vector<HeapGraphEdge> children = entries[i]->children(); 3297 Vector<HeapGraphEdge> children = entries[i]->children();
3265 for (int j = 0; j < children.length(); ++j) { 3298 for (int j = 0; j < children.length(); ++j) {
3266 affected[children[j].to()->ordered_index()] = true; 3299 affected[children[j].to()->ordered_index()] = true;
3267 } 3300 }
3268 } 3301 }
3269 } 3302 }
3270 } 3303 }
3271 return true; 3304 return true;
3272 } 3305 }
3273 3306
3274 3307
3275 bool HeapSnapshotGenerator::SetEntriesDominators() { 3308 bool HeapSnapshotGenerator::SetEntriesDominators() {
3276 // This array is used for maintaining reverse postorder of nodes. 3309 MarkWindowReachableObjects();
3310 // This array is used for maintaining postorder of nodes.
3277 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); 3311 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length());
3278 FillReversePostorderIndexes(&ordered_entries); 3312 FillPostorderIndexes(&ordered_entries);
3279 ScopedVector<int> dominators(ordered_entries.length()); 3313 ScopedVector<int> dominators(ordered_entries.length());
3280 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; 3314 if (!BuildDominatorTree(ordered_entries, &dominators)) return false;
3281 for (int i = 0; i < ordered_entries.length(); ++i) { 3315 for (int i = 0; i < ordered_entries.length(); ++i) {
3282 ASSERT(dominators[i] >= 0); 3316 ASSERT(dominators[i] >= 0);
3283 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]); 3317 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]);
3284 } 3318 }
3285 return true; 3319 return true;
3286 } 3320 }
3287 3321
3288 3322
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after
3763 3797
3764 3798
3765 void HeapSnapshotJSONSerializer::SortHashMap( 3799 void HeapSnapshotJSONSerializer::SortHashMap(
3766 HashMap* map, List<HashMap::Entry*>* sorted_entries) { 3800 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
3767 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) 3801 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
3768 sorted_entries->Add(p); 3802 sorted_entries->Add(p);
3769 sorted_entries->Sort(SortUsingEntryValue); 3803 sorted_entries->Sort(SortUsingEntryValue);
3770 } 3804 }
3771 3805
3772 } } // namespace v8::internal 3806 } } // namespace v8::internal
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