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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 String* constructor = JSObject::cast(js_obj)->constructor_name(); | 71 String* constructor = JSObject::cast(js_obj)->constructor_name(); |
72 // Differentiate Object and Array instances. | 72 // Differentiate Object and Array instances. |
73 if (fine_grain && (constructor == Heap::Object_symbol() || | 73 if (fine_grain && (constructor == Heap::Object_symbol() || |
74 constructor == Heap::Array_symbol())) { | 74 constructor == Heap::Array_symbol())) { |
75 return JSObjectsCluster(constructor, obj); | 75 return JSObjectsCluster(constructor, obj); |
76 } else { | 76 } else { |
77 return JSObjectsCluster(constructor); | 77 return JSObjectsCluster(constructor); |
78 } | 78 } |
79 } else if (obj->IsString()) { | 79 } else if (obj->IsString()) { |
80 return JSObjectsCluster(Heap::String_symbol()); | 80 return JSObjectsCluster(Heap::String_symbol()); |
| 81 } else if (obj->IsJSGlobalPropertyCell()) { |
| 82 return JSObjectsCluster(JSObjectsCluster::GLOBAL_PROPERTY); |
| 83 } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) { |
| 84 return JSObjectsCluster(JSObjectsCluster::CODE); |
81 } | 85 } |
82 return JSObjectsCluster(); | 86 return JSObjectsCluster(); |
83 } | 87 } |
84 | 88 |
85 | 89 |
86 void Clusterizer::InsertIntoTree(JSObjectsClusterTree* tree, | 90 void Clusterizer::InsertIntoTree(JSObjectsClusterTree* tree, |
87 HeapObject* obj, bool fine_grain) { | 91 HeapObject* obj, bool fine_grain) { |
88 JSObjectsCluster cluster = Clusterize(obj, fine_grain); | 92 JSObjectsCluster cluster = Clusterize(obj, fine_grain); |
89 if (cluster.is_null()) return; | 93 if (cluster.is_null()) return; |
90 InsertIntoTree(tree, cluster, GetObjectSize(obj)); | 94 InsertIntoTree(tree, cluster, GetObjectSize(obj)); |
(...skipping 14 matching lines...) Expand all Loading... |
105 int Clusterizer::CalculateNetworkSize(JSObject* obj) { | 109 int Clusterizer::CalculateNetworkSize(JSObject* obj) { |
106 int size = obj->Size(); | 110 int size = obj->Size(); |
107 // If 'properties' and 'elements' are non-empty (thus, non-shared), | 111 // If 'properties' and 'elements' are non-empty (thus, non-shared), |
108 // take their size into account. | 112 // take their size into account. |
109 if (FixedArray::cast(obj->properties())->length() != 0) { | 113 if (FixedArray::cast(obj->properties())->length() != 0) { |
110 size += obj->properties()->Size(); | 114 size += obj->properties()->Size(); |
111 } | 115 } |
112 if (FixedArray::cast(obj->elements())->length() != 0) { | 116 if (FixedArray::cast(obj->elements())->length() != 0) { |
113 size += obj->elements()->Size(); | 117 size += obj->elements()->Size(); |
114 } | 118 } |
| 119 // For functions, also account non-empty context and literals sizes. |
| 120 if (obj->IsJSFunction()) { |
| 121 JSFunction* f = JSFunction::cast(obj); |
| 122 if (f->unchecked_context()->IsContext()) { |
| 123 size += f->context()->Size(); |
| 124 } |
| 125 if (f->literals()->length() != 0) { |
| 126 size += f->literals()->Size(); |
| 127 } |
| 128 } |
115 return size; | 129 return size; |
116 } | 130 } |
117 | 131 |
118 | 132 |
119 // A helper class for recording back references. | 133 // A helper class for recording back references. |
120 class ReferencesExtractor : public ObjectVisitor { | 134 class ReferencesExtractor : public ObjectVisitor { |
121 public: | 135 public: |
122 ReferencesExtractor(const JSObjectsCluster& cluster, | 136 ReferencesExtractor(const JSObjectsCluster& cluster, |
123 RetainerHeapProfile* profile) | 137 RetainerHeapProfile* profile) |
124 : cluster_(cluster), | 138 : cluster_(cluster), |
125 profile_(profile), | 139 profile_(profile), |
126 inside_array_(false) { | 140 inside_array_(false) { |
127 } | 141 } |
128 | 142 |
129 void VisitPointer(Object** o) { | 143 void VisitPointer(Object** o) { |
130 if ((*o)->IsJSObject() || (*o)->IsString()) { | 144 if ((*o)->IsFixedArray() && !inside_array_) { |
131 profile_->StoreReference(cluster_, HeapObject::cast(*o)); | |
132 } else if ((*o)->IsFixedArray() && !inside_array_) { | |
133 // Traverse one level deep for data members that are fixed arrays. | 145 // Traverse one level deep for data members that are fixed arrays. |
134 // This covers the case of 'elements' and 'properties' of JSObject, | 146 // This covers the case of 'elements' and 'properties' of JSObject, |
135 // and function contexts. | 147 // and function contexts. |
136 inside_array_ = true; | 148 inside_array_ = true; |
137 FixedArray::cast(*o)->Iterate(this); | 149 FixedArray::cast(*o)->Iterate(this); |
138 inside_array_ = false; | 150 inside_array_ = false; |
| 151 } else { |
| 152 profile_->StoreReference(cluster_, HeapObject::cast(*o)); |
139 } | 153 } |
140 } | 154 } |
141 | 155 |
142 void VisitPointers(Object** start, Object** end) { | 156 void VisitPointers(Object** start, Object** end) { |
143 for (Object** p = start; p < end; p++) VisitPointer(p); | 157 for (Object** p = start; p < end; p++) VisitPointer(p); |
144 } | 158 } |
145 | 159 |
146 private: | 160 private: |
147 const JSObjectsCluster& cluster_; | 161 const JSObjectsCluster& cluster_; |
148 RetainerHeapProfile* profile_; | 162 RetainerHeapProfile* profile_; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 return name[0] != '\0' ? name : "(anonymous)"; | 347 return name[0] != '\0' ? name : "(anonymous)"; |
334 } | 348 } |
335 | 349 |
336 | 350 |
337 void JSObjectsCluster::Print(StringStream* accumulator) const { | 351 void JSObjectsCluster::Print(StringStream* accumulator) const { |
338 ASSERT(!is_null()); | 352 ASSERT(!is_null()); |
339 if (constructor_ == FromSpecialCase(ROOTS)) { | 353 if (constructor_ == FromSpecialCase(ROOTS)) { |
340 accumulator->Add("(roots)"); | 354 accumulator->Add("(roots)"); |
341 } else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) { | 355 } else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) { |
342 accumulator->Add("(global property)"); | 356 accumulator->Add("(global property)"); |
| 357 } else if (constructor_ == FromSpecialCase(CODE)) { |
| 358 accumulator->Add("(code)"); |
343 } else if (constructor_ == FromSpecialCase(SELF)) { | 359 } else if (constructor_ == FromSpecialCase(SELF)) { |
344 accumulator->Add("(self)"); | 360 accumulator->Add("(self)"); |
345 } else { | 361 } else { |
346 SmartPointer<char> s_name( | 362 SmartPointer<char> s_name( |
347 constructor_->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)); | 363 constructor_->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)); |
348 accumulator->Add("%s", GetConstructorName(*s_name)); | 364 accumulator->Add("%s", GetConstructorName(*s_name)); |
349 if (instance_ != NULL) { | 365 if (instance_ != NULL) { |
350 accumulator->Add(":%p", static_cast<void*>(instance_)); | 366 accumulator->Add(":%p", static_cast<void*>(instance_)); |
351 } | 367 } |
352 } | 368 } |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 : zscope_(DELETE_ON_EXIT) { | 536 : zscope_(DELETE_ON_EXIT) { |
521 JSObjectsCluster roots(JSObjectsCluster::ROOTS); | 537 JSObjectsCluster roots(JSObjectsCluster::ROOTS); |
522 ReferencesExtractor extractor(roots, this); | 538 ReferencesExtractor extractor(roots, this); |
523 Heap::IterateRoots(&extractor); | 539 Heap::IterateRoots(&extractor); |
524 } | 540 } |
525 | 541 |
526 | 542 |
527 void RetainerHeapProfile::StoreReference(const JSObjectsCluster& cluster, | 543 void RetainerHeapProfile::StoreReference(const JSObjectsCluster& cluster, |
528 HeapObject* ref) { | 544 HeapObject* ref) { |
529 JSObjectsCluster ref_cluster = Clusterizer::Clusterize(ref); | 545 JSObjectsCluster ref_cluster = Clusterizer::Clusterize(ref); |
| 546 if (ref_cluster.is_null()) return; |
530 JSObjectsRetainerTree::Locator ref_loc; | 547 JSObjectsRetainerTree::Locator ref_loc; |
531 if (retainers_tree_.Insert(ref_cluster, &ref_loc)) { | 548 if (retainers_tree_.Insert(ref_cluster, &ref_loc)) { |
532 ref_loc.set_value(new JSObjectsClusterTree()); | 549 ref_loc.set_value(new JSObjectsClusterTree()); |
533 } | 550 } |
534 JSObjectsClusterTree* referenced_by = ref_loc.value(); | 551 JSObjectsClusterTree* referenced_by = ref_loc.value(); |
535 Clusterizer::InsertReferenceIntoTree(referenced_by, cluster); | 552 Clusterizer::InsertReferenceIntoTree(referenced_by, cluster); |
536 } | 553 } |
537 | 554 |
538 | 555 |
539 void RetainerHeapProfile::CollectStats(HeapObject* obj) { | 556 void RetainerHeapProfile::CollectStats(HeapObject* obj) { |
540 if (obj->IsJSObject()) { | 557 const JSObjectsCluster cluster = Clusterizer::Clusterize(obj); |
541 const JSObjectsCluster cluster = Clusterizer::Clusterize(obj); | 558 if (cluster.is_null()) return; |
542 ReferencesExtractor extractor(cluster, this); | 559 ReferencesExtractor extractor(cluster, this); |
543 obj->Iterate(&extractor); | 560 obj->Iterate(&extractor); |
544 } else if (obj->IsJSGlobalPropertyCell()) { | |
545 JSObjectsCluster global_prop(JSObjectsCluster::GLOBAL_PROPERTY); | |
546 ReferencesExtractor extractor(global_prop, this); | |
547 obj->Iterate(&extractor); | |
548 } | |
549 } | 561 } |
550 | 562 |
551 | 563 |
552 void RetainerHeapProfile::DebugPrintStats( | 564 void RetainerHeapProfile::DebugPrintStats( |
553 RetainerHeapProfile::Printer* printer) { | 565 RetainerHeapProfile::Printer* printer) { |
554 coarser_.Process(&retainers_tree_); | 566 coarser_.Process(&retainers_tree_); |
555 // Print clusters that have no equivalents, aggregating their retainers. | 567 // Print clusters that have no equivalents, aggregating their retainers. |
556 AggregatingRetainerTreePrinter agg_printer(&coarser_, printer); | 568 AggregatingRetainerTreePrinter agg_printer(&coarser_, printer); |
557 retainers_tree_.ForEach(&agg_printer); | 569 retainers_tree_.ForEach(&agg_printer); |
558 // Now aggregate clusters that have equivalents... | 570 // Now aggregate clusters that have equivalents... |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 GlobalHandles::MakeWeak(handle.location(), | 685 GlobalHandles::MakeWeak(handle.location(), |
674 static_cast<void*>(stack.start()), | 686 static_cast<void*>(stack.start()), |
675 StackWeakReferenceCallback); | 687 StackWeakReferenceCallback); |
676 } | 688 } |
677 | 689 |
678 | 690 |
679 #endif // ENABLE_LOGGING_AND_PROFILING | 691 #endif // ENABLE_LOGGING_AND_PROFILING |
680 | 692 |
681 | 693 |
682 } } // namespace v8::internal | 694 } } // namespace v8::internal |
OLD | NEW |