| 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 10 matching lines...) Expand all Loading... |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "heap-profiler.h" | 30 #include "heap-profiler.h" |
| 31 #include "frames-inl.h" |
| 32 #include "global-handles.h" |
| 31 #include "string-stream.h" | 33 #include "string-stream.h" |
| 32 | 34 |
| 33 namespace v8 { | 35 namespace v8 { |
| 34 namespace internal { | 36 namespace internal { |
| 35 | 37 |
| 36 | 38 |
| 37 #ifdef ENABLE_LOGGING_AND_PROFILING | 39 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 38 namespace { | 40 namespace { |
| 39 | 41 |
| 40 // Clusterizer is a set of helper functions for converting | 42 // Clusterizer is a set of helper functions for converting |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 void ConstructorHeapProfile::CollectStats(HeapObject* obj) { | 322 void ConstructorHeapProfile::CollectStats(HeapObject* obj) { |
| 321 Clusterizer::InsertIntoTree(&js_objects_info_tree_, obj, false); | 323 Clusterizer::InsertIntoTree(&js_objects_info_tree_, obj, false); |
| 322 } | 324 } |
| 323 | 325 |
| 324 | 326 |
| 325 void ConstructorHeapProfile::PrintStats() { | 327 void ConstructorHeapProfile::PrintStats() { |
| 326 js_objects_info_tree_.ForEach(this); | 328 js_objects_info_tree_.ForEach(this); |
| 327 } | 329 } |
| 328 | 330 |
| 329 | 331 |
| 332 static const char* GetConstructorName(const char* name) { |
| 333 return name[0] != '\0' ? name : "(anonymous)"; |
| 334 } |
| 335 |
| 336 |
| 330 void JSObjectsCluster::Print(StringStream* accumulator) const { | 337 void JSObjectsCluster::Print(StringStream* accumulator) const { |
| 331 ASSERT(!is_null()); | 338 ASSERT(!is_null()); |
| 332 if (constructor_ == FromSpecialCase(ROOTS)) { | 339 if (constructor_ == FromSpecialCase(ROOTS)) { |
| 333 accumulator->Add("(roots)"); | 340 accumulator->Add("(roots)"); |
| 334 } else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) { | 341 } else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) { |
| 335 accumulator->Add("(global property)"); | 342 accumulator->Add("(global property)"); |
| 336 } else if (constructor_ == FromSpecialCase(SELF)) { | 343 } else if (constructor_ == FromSpecialCase(SELF)) { |
| 337 accumulator->Add("(self)"); | 344 accumulator->Add("(self)"); |
| 338 } else { | 345 } else { |
| 339 SmartPointer<char> s_name( | 346 SmartPointer<char> s_name( |
| 340 constructor_->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)); | 347 constructor_->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)); |
| 341 accumulator->Add("%s", (*s_name)[0] != '\0' ? *s_name : "(anonymous)"); | 348 accumulator->Add("%s", GetConstructorName(*s_name)); |
| 342 if (instance_ != NULL) { | 349 if (instance_ != NULL) { |
| 343 accumulator->Add(":%p", static_cast<void*>(instance_)); | 350 accumulator->Add(":%p", static_cast<void*>(instance_)); |
| 344 } | 351 } |
| 345 } | 352 } |
| 346 } | 353 } |
| 347 | 354 |
| 348 | 355 |
| 349 void JSObjectsCluster::DebugPrint(StringStream* accumulator) const { | 356 void JSObjectsCluster::DebugPrint(StringStream* accumulator) const { |
| 350 if (!is_null()) { | 357 if (!is_null()) { |
| 351 Print(accumulator); | 358 Print(accumulator); |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 // HeapProfiler class implementation. | 574 // HeapProfiler class implementation. |
| 568 // | 575 // |
| 569 void HeapProfiler::CollectStats(HeapObject* obj, HistogramInfo* info) { | 576 void HeapProfiler::CollectStats(HeapObject* obj, HistogramInfo* info) { |
| 570 InstanceType type = obj->map()->instance_type(); | 577 InstanceType type = obj->map()->instance_type(); |
| 571 ASSERT(0 <= type && type <= LAST_TYPE); | 578 ASSERT(0 <= type && type <= LAST_TYPE); |
| 572 info[type].increment_number(1); | 579 info[type].increment_number(1); |
| 573 info[type].increment_bytes(obj->Size()); | 580 info[type].increment_bytes(obj->Size()); |
| 574 } | 581 } |
| 575 | 582 |
| 576 | 583 |
| 584 static void StackWeakReferenceCallback(Persistent<Value> object, |
| 585 void* trace) { |
| 586 DeleteArray(static_cast<Address*>(trace)); |
| 587 object.Dispose(); |
| 588 } |
| 589 |
| 590 |
| 591 static void PrintProducerStackTrace(Object* obj, void* trace) { |
| 592 if (!obj->IsJSObject()) return; |
| 593 String* constructor = JSObject::cast(obj)->constructor_name(); |
| 594 SmartPointer<char> s_name( |
| 595 constructor->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)); |
| 596 LOG(HeapSampleJSProducerEvent(GetConstructorName(*s_name), |
| 597 reinterpret_cast<Address*>(trace))); |
| 598 } |
| 599 |
| 600 |
| 577 void HeapProfiler::WriteSample() { | 601 void HeapProfiler::WriteSample() { |
| 578 LOG(HeapSampleBeginEvent("Heap", "allocated")); | 602 LOG(HeapSampleBeginEvent("Heap", "allocated")); |
| 579 LOG(HeapSampleStats( | 603 LOG(HeapSampleStats( |
| 580 "Heap", "allocated", Heap::Capacity(), Heap::SizeOfObjects())); | 604 "Heap", "allocated", Heap::Capacity(), Heap::SizeOfObjects())); |
| 581 | 605 |
| 582 HistogramInfo info[LAST_TYPE+1]; | 606 HistogramInfo info[LAST_TYPE+1]; |
| 583 #define DEF_TYPE_NAME(name) info[name].set_name(#name); | 607 #define DEF_TYPE_NAME(name) info[name].set_name(#name); |
| 584 INSTANCE_TYPE_LIST(DEF_TYPE_NAME) | 608 INSTANCE_TYPE_LIST(DEF_TYPE_NAME) |
| 585 #undef DEF_TYPE_NAME | 609 #undef DEF_TYPE_NAME |
| 586 | 610 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 609 for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) { | 633 for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) { |
| 610 if (info[i].bytes() > 0) { | 634 if (info[i].bytes() > 0) { |
| 611 LOG(HeapSampleItemEvent(info[i].name(), info[i].number(), | 635 LOG(HeapSampleItemEvent(info[i].name(), info[i].number(), |
| 612 info[i].bytes())); | 636 info[i].bytes())); |
| 613 } | 637 } |
| 614 } | 638 } |
| 615 | 639 |
| 616 js_cons_profile.PrintStats(); | 640 js_cons_profile.PrintStats(); |
| 617 js_retainer_profile.PrintStats(); | 641 js_retainer_profile.PrintStats(); |
| 618 | 642 |
| 643 GlobalHandles::IterateWeakRoots(PrintProducerStackTrace, |
| 644 StackWeakReferenceCallback); |
| 645 |
| 619 LOG(HeapSampleEndEvent("Heap", "allocated")); | 646 LOG(HeapSampleEndEvent("Heap", "allocated")); |
| 620 } | 647 } |
| 621 | 648 |
| 622 | 649 |
| 650 bool ProducerHeapProfile::can_log_ = false; |
| 651 |
| 652 void ProducerHeapProfile::Setup() { |
| 653 can_log_ = true; |
| 654 } |
| 655 |
| 656 void ProducerHeapProfile::RecordJSObjectAllocation(Object* obj) { |
| 657 if (!can_log_ || !FLAG_log_producers) return; |
| 658 int framesCount = 0; |
| 659 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) { |
| 660 ++framesCount; |
| 661 } |
| 662 if (framesCount == 0) return; |
| 663 ++framesCount; // Reserve place for the terminator item. |
| 664 Vector<Address> stack(NewArray<Address>(framesCount), framesCount); |
| 665 int i = 0; |
| 666 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) { |
| 667 stack[i++] = it.frame()->pc(); |
| 668 } |
| 669 stack[i] = NULL; |
| 670 Handle<Object> handle = GlobalHandles::Create(obj); |
| 671 GlobalHandles::MakeWeak(handle.location(), |
| 672 static_cast<void*>(stack.start()), |
| 673 StackWeakReferenceCallback); |
| 674 } |
| 675 |
| 676 |
| 623 #endif // ENABLE_LOGGING_AND_PROFILING | 677 #endif // ENABLE_LOGGING_AND_PROFILING |
| 624 | 678 |
| 625 | 679 |
| 626 } } // namespace v8::internal | 680 } } // namespace v8::internal |
| OLD | NEW |