| 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 | 
|---|