OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 } | 62 } |
63 | 63 |
64 | 64 |
65 // A helper class for recording back references. | 65 // A helper class for recording back references. |
66 class ReferencesExtractor : public ObjectVisitor { | 66 class ReferencesExtractor : public ObjectVisitor { |
67 public: | 67 public: |
68 ReferencesExtractor( | 68 ReferencesExtractor( |
69 const JSObjectsCluster& cluster, RetainerHeapProfile* profile) | 69 const JSObjectsCluster& cluster, RetainerHeapProfile* profile) |
70 : cluster_(cluster), | 70 : cluster_(cluster), |
71 profile_(profile), | 71 profile_(profile), |
72 insideArray_(false) { | 72 inside_array_(false) { |
73 } | 73 } |
74 | 74 |
75 void VisitPointer(Object** o) { | 75 void VisitPointer(Object** o) { |
76 if ((*o)->IsJSObject() || (*o)->IsString()) { | 76 if ((*o)->IsJSObject() || (*o)->IsString()) { |
77 profile_->StoreReference(cluster_, *o); | 77 profile_->StoreReference(cluster_, *o); |
78 } else if ((*o)->IsFixedArray() && !insideArray_) { | 78 } else if ((*o)->IsFixedArray() && !inside_array_) { |
79 // Traverse one level deep for data members that are fixed arrays. | 79 // Traverse one level deep for data members that are fixed arrays. |
80 // This covers the case of 'elements' and 'properties' of JSObject, | 80 // This covers the case of 'elements' and 'properties' of JSObject, |
81 // and function contexts. | 81 // and function contexts. |
82 insideArray_ = true; | 82 inside_array_ = true; |
83 FixedArray::cast(*o)->Iterate(this); | 83 FixedArray::cast(*o)->Iterate(this); |
84 insideArray_ = false; | 84 inside_array_ = false; |
85 } | 85 } |
86 } | 86 } |
87 | 87 |
88 void VisitPointers(Object** start, Object** end) { | 88 void VisitPointers(Object** start, Object** end) { |
89 for (Object** p = start; p < end; p++) VisitPointer(p); | 89 for (Object** p = start; p < end; p++) VisitPointer(p); |
90 } | 90 } |
91 | 91 |
92 private: | 92 private: |
93 const JSObjectsCluster& cluster_; | 93 const JSObjectsCluster& cluster_; |
94 RetainerHeapProfile* profile_; | 94 RetainerHeapProfile* profile_; |
95 bool insideArray_; | 95 bool inside_array_; |
96 }; | 96 }; |
97 | 97 |
98 | 98 |
99 // A printer interface implementation for the Retainers profile. | 99 // A printer interface implementation for the Retainers profile. |
100 class RetainersPrinter : public RetainerHeapProfile::Printer { | 100 class RetainersPrinter : public RetainerHeapProfile::Printer { |
101 public: | 101 public: |
102 void PrintRetainers(const StringStream& retainers) { | 102 void PrintRetainers(const StringStream& retainers) { |
103 LOG(HeapSampleJSRetainersEvent(*(retainers.ToCString()))); | 103 LOG(HeapSampleJSRetainersEvent(*(retainers.ToCString()))); |
104 } | 104 } |
105 }; | 105 }; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 for (int i = 0; i < a.refs.length(); ++i) { | 219 for (int i = 0; i < a.refs.length(); ++i) { |
220 int cmp = JSObjectsCluster::Compare(a.refs[i], b.refs[i]); | 220 int cmp = JSObjectsCluster::Compare(a.refs[i], b.refs[i]); |
221 if (cmp != 0) return cmp; | 221 if (cmp != 0) return cmp; |
222 } | 222 } |
223 return 0; | 223 return 0; |
224 } | 224 } |
225 | 225 |
226 | 226 |
227 ClustersCoarser::ClustersCoarser() | 227 ClustersCoarser::ClustersCoarser() |
228 : zscope_(DELETE_ON_EXIT), | 228 : zscope_(DELETE_ON_EXIT), |
229 simList_(ClustersCoarser::kInitialSimilarityListCapacity), | 229 sim_list_(ClustersCoarser::kInitialSimilarityListCapacity), |
230 currentPair_(NULL) { | 230 current_pair_(NULL) { |
231 } | 231 } |
232 | 232 |
233 | 233 |
234 void ClustersCoarser::Call( | 234 void ClustersCoarser::Call( |
235 const JSObjectsCluster& cluster, JSObjectsClusterTree* tree) { | 235 const JSObjectsCluster& cluster, JSObjectsClusterTree* tree) { |
236 if (tree != NULL) { | 236 if (tree != NULL) { |
237 // First level of retainer graph. | 237 // First level of retainer graph. |
238 if (!cluster.can_be_coarsed()) return; | 238 if (!cluster.can_be_coarsed()) return; |
239 ClusterBackRefs pair(cluster); | 239 ClusterBackRefs pair(cluster); |
240 ASSERT(currentPair_ == NULL); | 240 ASSERT(current_pair_ == NULL); |
241 currentPair_ = &pair; | 241 current_pair_ = &pair; |
242 currentSet_ = new JSObjectsClusterTree(); | 242 current_set_ = new JSObjectsClusterTree(); |
243 tree->ForEach(this); | 243 tree->ForEach(this); |
244 simList_.Add(pair); | 244 sim_list_.Add(pair); |
245 currentPair_ = NULL; | 245 current_pair_ = NULL; |
246 currentSet_ = NULL; | 246 current_set_ = NULL; |
247 } else { | 247 } else { |
248 // Second level of retainer graph. | 248 // Second level of retainer graph. |
249 ASSERT(currentPair_ != NULL); | 249 ASSERT(current_pair_ != NULL); |
250 ASSERT(currentSet_ != NULL); | 250 ASSERT(current_set_ != NULL); |
251 JSObjectsCluster eq = GetCoarseEquivalent(cluster); | 251 JSObjectsCluster eq = GetCoarseEquivalent(cluster); |
252 JSObjectsClusterTree::Locator loc; | 252 JSObjectsClusterTree::Locator loc; |
253 if (!eq.is_null()) { | 253 if (!eq.is_null()) { |
254 if (currentSet_->Find(eq, &loc)) return; | 254 if (current_set_->Find(eq, &loc)) return; |
255 currentPair_->refs.Add(eq); | 255 current_pair_->refs.Add(eq); |
256 currentSet_->Insert(eq, &loc); | 256 current_set_->Insert(eq, &loc); |
257 } else { | 257 } else { |
258 currentPair_->refs.Add(cluster); | 258 current_pair_->refs.Add(cluster); |
259 } | 259 } |
260 } | 260 } |
261 } | 261 } |
262 | 262 |
263 | 263 |
264 void ClustersCoarser::Process(JSObjectsClusterTree* tree) { | 264 void ClustersCoarser::Process(JSObjectsClusterTree* tree) { |
265 int last_eq_clusters = -1; | 265 int last_eq_clusters = -1; |
266 for (int i = 0; i < kMaxPassesCount; ++i) { | 266 for (int i = 0; i < kMaxPassesCount; ++i) { |
267 simList_.Clear(); | 267 sim_list_.Clear(); |
268 const int curr_eq_clusters = DoProcess(tree); | 268 const int curr_eq_clusters = DoProcess(tree); |
269 // If no new cluster equivalents discovered, abort processing. | 269 // If no new cluster equivalents discovered, abort processing. |
270 if (last_eq_clusters == curr_eq_clusters) break; | 270 if (last_eq_clusters == curr_eq_clusters) break; |
271 last_eq_clusters = curr_eq_clusters; | 271 last_eq_clusters = curr_eq_clusters; |
272 } | 272 } |
273 } | 273 } |
274 | 274 |
275 | 275 |
276 int ClustersCoarser::DoProcess(JSObjectsClusterTree* tree) { | 276 int ClustersCoarser::DoProcess(JSObjectsClusterTree* tree) { |
277 tree->ForEach(this); | 277 tree->ForEach(this); |
278 // To sort similarity list properly, references list of a cluster is | 278 // To sort similarity list properly, references list of a cluster is |
279 // required to be sorted, thus 'O1 <- A, B' and 'O2 <- B, A' would | 279 // required to be sorted, thus 'O1 <- A, B' and 'O2 <- B, A' would |
280 // be considered equivalent. But we don't sort them explicitly | 280 // be considered equivalent. But we don't sort them explicitly |
281 // because we know that they come from a splay tree traversal, so | 281 // because we know that they come from a splay tree traversal, so |
282 // they are already sorted. | 282 // they are already sorted. |
283 simList_.Sort(ClusterBackRefsCmp); | 283 sim_list_.Sort(ClusterBackRefsCmp); |
284 return FillEqualityTree(); | 284 return FillEqualityTree(); |
285 } | 285 } |
286 | 286 |
287 | 287 |
288 JSObjectsCluster ClustersCoarser::GetCoarseEquivalent( | 288 JSObjectsCluster ClustersCoarser::GetCoarseEquivalent( |
289 const JSObjectsCluster& cluster) { | 289 const JSObjectsCluster& cluster) { |
290 if (!cluster.can_be_coarsed()) return JSObjectsCluster(); | 290 if (!cluster.can_be_coarsed()) return JSObjectsCluster(); |
291 EqualityTree::Locator loc; | 291 EqualityTree::Locator loc; |
292 return eqTree_.Find(cluster, &loc) ? loc.value() : JSObjectsCluster(); | 292 return eq_tree_.Find(cluster, &loc) ? loc.value() : JSObjectsCluster(); |
293 } | 293 } |
294 | 294 |
295 | 295 |
296 bool ClustersCoarser::HasAnEquivalent(const JSObjectsCluster& cluster) { | 296 bool ClustersCoarser::HasAnEquivalent(const JSObjectsCluster& cluster) { |
297 // Return true for coarsible clusters that have a non-identical equivalent. | 297 // Return true for coarsible clusters that have a non-identical equivalent. |
298 return cluster.can_be_coarsed() && | 298 return cluster.can_be_coarsed() && |
299 JSObjectsCluster::Compare(cluster, GetCoarseEquivalent(cluster)) != 0; | 299 JSObjectsCluster::Compare(cluster, GetCoarseEquivalent(cluster)) != 0; |
300 } | 300 } |
301 | 301 |
302 | 302 |
303 int ClustersCoarser::FillEqualityTree() { | 303 int ClustersCoarser::FillEqualityTree() { |
304 int eqClustersCount = 0; | 304 int eq_clusters_count = 0; |
305 int eqTo = 0; | 305 int eq_to = 0; |
306 bool firstAdded = false; | 306 bool first_added = false; |
307 for (int i = 1; i < simList_.length(); ++i) { | 307 for (int i = 1; i < sim_list_.length(); ++i) { |
308 if (ClusterBackRefs::Compare(simList_[i], simList_[eqTo]) == 0) { | 308 if (ClusterBackRefs::Compare(sim_list_[i], sim_list_[eq_to]) == 0) { |
309 EqualityTree::Locator loc; | 309 EqualityTree::Locator loc; |
310 if (!firstAdded) { | 310 if (!first_added) { |
311 // Add self-equivalence, if we have more than one item in this | 311 // Add self-equivalence, if we have more than one item in this |
312 // equivalence class. | 312 // equivalence class. |
313 eqTree_.Insert(simList_[eqTo].cluster, &loc); | 313 eq_tree_.Insert(sim_list_[eq_to].cluster, &loc); |
314 loc.set_value(simList_[eqTo].cluster); | 314 loc.set_value(sim_list_[eq_to].cluster); |
315 firstAdded = true; | 315 first_added = true; |
316 } | 316 } |
317 eqTree_.Insert(simList_[i].cluster, &loc); | 317 eq_tree_.Insert(sim_list_[i].cluster, &loc); |
318 loc.set_value(simList_[eqTo].cluster); | 318 loc.set_value(sim_list_[eq_to].cluster); |
319 ++eqClustersCount; | 319 ++eq_clusters_count; |
320 } else { | 320 } else { |
321 eqTo = i; | 321 eq_to = i; |
322 firstAdded = false; | 322 first_added = false; |
323 } | 323 } |
324 } | 324 } |
325 return eqClustersCount; | 325 return eq_clusters_count; |
326 } | 326 } |
327 | 327 |
328 | 328 |
329 const JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoKey; | 329 const JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoKey; |
330 const JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoValue; | 330 const JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoValue; |
331 const JSObjectsClusterTreeConfig::Key JSObjectsClusterTreeConfig::kNoKey; | 331 const JSObjectsClusterTreeConfig::Key JSObjectsClusterTreeConfig::kNoKey; |
332 const JSObjectsClusterTreeConfig::Value JSObjectsClusterTreeConfig::kNoValue = | 332 const JSObjectsClusterTreeConfig::Value JSObjectsClusterTreeConfig::kNoValue = |
333 NULL; | 333 NULL; |
334 | 334 |
335 | 335 |
(...skipping 30 matching lines...) Expand all Loading... |
366 | 366 |
367 | 367 |
368 void RetainerHeapProfile::StoreReference( | 368 void RetainerHeapProfile::StoreReference( |
369 const JSObjectsCluster& cluster, | 369 const JSObjectsCluster& cluster, |
370 Object* ref) { | 370 Object* ref) { |
371 JSObjectsCluster ref_cluster = Clusterize(ref); | 371 JSObjectsCluster ref_cluster = Clusterize(ref); |
372 JSObjectsClusterTree::Locator ref_loc; | 372 JSObjectsClusterTree::Locator ref_loc; |
373 if (retainers_tree_.Insert(ref_cluster, &ref_loc)) { | 373 if (retainers_tree_.Insert(ref_cluster, &ref_loc)) { |
374 ref_loc.set_value(new JSObjectsClusterTree()); | 374 ref_loc.set_value(new JSObjectsClusterTree()); |
375 } | 375 } |
376 JSObjectsClusterTree* referencedBy = ref_loc.value(); | 376 JSObjectsClusterTree* referenced_by = ref_loc.value(); |
377 JSObjectsClusterTree::Locator obj_loc; | 377 JSObjectsClusterTree::Locator obj_loc; |
378 referencedBy->Insert(cluster, &obj_loc); | 378 referenced_by->Insert(cluster, &obj_loc); |
379 } | 379 } |
380 | 380 |
381 | 381 |
382 void RetainerHeapProfile::CollectStats(HeapObject* obj) { | 382 void RetainerHeapProfile::CollectStats(HeapObject* obj) { |
383 if (obj->IsJSObject()) { | 383 if (obj->IsJSObject()) { |
384 const JSObjectsCluster cluster = Clusterize(JSObject::cast(obj)); | 384 const JSObjectsCluster cluster = Clusterize(JSObject::cast(obj)); |
385 ReferencesExtractor extractor(cluster, this); | 385 ReferencesExtractor extractor(cluster, this); |
386 obj->Iterate(&extractor); | 386 obj->Iterate(&extractor); |
387 } else if (obj->IsJSGlobalPropertyCell()) { | 387 } else if (obj->IsJSGlobalPropertyCell()) { |
388 JSObjectsCluster global_prop(JSObjectsCluster::GLOBAL_PROPERTY); | 388 JSObjectsCluster global_prop(JSObjectsCluster::GLOBAL_PROPERTY); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 js_retainer_profile.PrintStats(); | 510 js_retainer_profile.PrintStats(); |
511 | 511 |
512 LOG(HeapSampleEndEvent("Heap", "allocated")); | 512 LOG(HeapSampleEndEvent("Heap", "allocated")); |
513 } | 513 } |
514 | 514 |
515 | 515 |
516 #endif // ENABLE_LOGGING_AND_PROFILING | 516 #endif // ENABLE_LOGGING_AND_PROFILING |
517 | 517 |
518 | 518 |
519 } } // namespace v8::internal | 519 } } // namespace v8::internal |
OLD | NEW |