OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 size_func_ = size_f; | 75 size_func_ = size_f; |
76 Page* p = Page::FromAllocationTop(cur_addr_); | 76 Page* p = Page::FromAllocationTop(cur_addr_); |
77 cur_limit_ = (p == end_page_) ? end_addr_ : p->AllocationTop(); | 77 cur_limit_ = (p == end_page_) ? end_addr_ : p->AllocationTop(); |
78 | 78 |
79 #ifdef DEBUG | 79 #ifdef DEBUG |
80 Verify(); | 80 Verify(); |
81 #endif | 81 #endif |
82 } | 82 } |
83 | 83 |
84 | 84 |
85 bool HeapObjectIterator::HasNextInNextPage() { | 85 HeapObject* HeapObjectIterator::FromNextPage() { |
86 if (cur_addr_ == end_addr_) return false; | 86 if (cur_addr_ == end_addr_) return NULL; |
87 | 87 |
88 Page* cur_page = Page::FromAllocationTop(cur_addr_); | 88 Page* cur_page = Page::FromAllocationTop(cur_addr_); |
89 cur_page = cur_page->next_page(); | 89 cur_page = cur_page->next_page(); |
90 ASSERT(cur_page->is_valid()); | 90 ASSERT(cur_page->is_valid()); |
91 | 91 |
92 cur_addr_ = cur_page->ObjectAreaStart(); | 92 cur_addr_ = cur_page->ObjectAreaStart(); |
93 cur_limit_ = (cur_page == end_page_) ? end_addr_ : cur_page->AllocationTop(); | 93 cur_limit_ = (cur_page == end_page_) ? end_addr_ : cur_page->AllocationTop(); |
94 | 94 |
95 if (cur_addr_ == end_addr_) return false; | 95 if (cur_addr_ == end_addr_) return NULL; |
96 ASSERT(cur_addr_ < cur_limit_); | 96 ASSERT(cur_addr_ < cur_limit_); |
97 #ifdef DEBUG | 97 #ifdef DEBUG |
98 Verify(); | 98 Verify(); |
99 #endif | 99 #endif |
100 return true; | 100 return FromCurrentPage(); |
101 } | 101 } |
102 | 102 |
103 | 103 |
104 #ifdef DEBUG | 104 #ifdef DEBUG |
105 void HeapObjectIterator::Verify() { | 105 void HeapObjectIterator::Verify() { |
106 Page* p = Page::FromAllocationTop(cur_addr_); | 106 Page* p = Page::FromAllocationTop(cur_addr_); |
107 ASSERT(p == Page::FromAllocationTop(cur_limit_)); | 107 ASSERT(p == Page::FromAllocationTop(cur_limit_)); |
108 ASSERT(p->Offset(cur_addr_) <= p->Offset(cur_limit_)); | 108 ASSERT(p->Offset(cur_addr_) <= p->Offset(cur_limit_)); |
109 } | 109 } |
110 #endif | 110 #endif |
(...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1430 } | 1430 } |
1431 | 1431 |
1432 // Because the copying collector does not touch garbage objects, we iterate | 1432 // Because the copying collector does not touch garbage objects, we iterate |
1433 // the new space before a collection to get a histogram of allocated objects. | 1433 // the new space before a collection to get a histogram of allocated objects. |
1434 // This only happens (1) when compiled with DEBUG and the --heap-stats flag is | 1434 // This only happens (1) when compiled with DEBUG and the --heap-stats flag is |
1435 // set, or when compiled with ENABLE_LOGGING_AND_PROFILING and the --log-gc | 1435 // set, or when compiled with ENABLE_LOGGING_AND_PROFILING and the --log-gc |
1436 // flag is set. | 1436 // flag is set. |
1437 void NewSpace::CollectStatistics() { | 1437 void NewSpace::CollectStatistics() { |
1438 ClearHistograms(); | 1438 ClearHistograms(); |
1439 SemiSpaceIterator it(this); | 1439 SemiSpaceIterator it(this); |
1440 while (it.has_next()) RecordAllocation(it.next()); | 1440 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) |
| 1441 RecordAllocation(obj); |
1441 } | 1442 } |
1442 | 1443 |
1443 | 1444 |
1444 #ifdef ENABLE_LOGGING_AND_PROFILING | 1445 #ifdef ENABLE_LOGGING_AND_PROFILING |
1445 static void DoReportStatistics(HistogramInfo* info, const char* description) { | 1446 static void DoReportStatistics(HistogramInfo* info, const char* description) { |
1446 LOG(HeapSampleBeginEvent("NewSpace", description)); | 1447 LOG(HeapSampleBeginEvent("NewSpace", description)); |
1447 // Lump all the string types together. | 1448 // Lump all the string types together. |
1448 int string_number = 0; | 1449 int string_number = 0; |
1449 int string_bytes = 0; | 1450 int string_bytes = 0; |
1450 #define INCREMENT(type, size, name, camel_name) \ | 1451 #define INCREMENT(type, size, name, camel_name) \ |
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2047 } | 2048 } |
2048 EnterComment(comment_txt, flat_delta); | 2049 EnterComment(comment_txt, flat_delta); |
2049 } | 2050 } |
2050 | 2051 |
2051 | 2052 |
2052 // Collects code size statistics: | 2053 // Collects code size statistics: |
2053 // - by code kind | 2054 // - by code kind |
2054 // - by code comment | 2055 // - by code comment |
2055 void PagedSpace::CollectCodeStatistics() { | 2056 void PagedSpace::CollectCodeStatistics() { |
2056 HeapObjectIterator obj_it(this); | 2057 HeapObjectIterator obj_it(this); |
2057 while (obj_it.has_next()) { | 2058 for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) { |
2058 HeapObject* obj = obj_it.next(); | |
2059 if (obj->IsCode()) { | 2059 if (obj->IsCode()) { |
2060 Code* code = Code::cast(obj); | 2060 Code* code = Code::cast(obj); |
2061 code_kind_statistics[code->kind()] += code->Size(); | 2061 code_kind_statistics[code->kind()] += code->Size(); |
2062 RelocIterator it(code); | 2062 RelocIterator it(code); |
2063 int delta = 0; | 2063 int delta = 0; |
2064 const byte* prev_pc = code->instruction_start(); | 2064 const byte* prev_pc = code->instruction_start(); |
2065 while (!it.done()) { | 2065 while (!it.done()) { |
2066 if (it.rinfo()->rmode() == RelocInfo::COMMENT) { | 2066 if (it.rinfo()->rmode() == RelocInfo::COMMENT) { |
2067 delta += static_cast<int>(it.rinfo()->pc() - prev_pc); | 2067 delta += static_cast<int>(it.rinfo()->pc() - prev_pc); |
2068 CollectCommentStatistics(&it); | 2068 CollectCommentStatistics(&it); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2150 pct = (rset_marked_pointers + rset_marked_array_elements) == 0 ? 0 | 2150 pct = (rset_marked_pointers + rset_marked_array_elements) == 0 ? 0 |
2151 : (cross_gen_pointers + cross_gen_array_elements) * 100 / | 2151 : (cross_gen_pointers + cross_gen_array_elements) * 100 / |
2152 (rset_marked_pointers + rset_marked_array_elements); | 2152 (rset_marked_pointers + rset_marked_array_elements); |
2153 PrintF(" total rset pointers %d, true cross generation ones %d (%%%d)\n", | 2153 PrintF(" total rset pointers %d, true cross generation ones %d (%%%d)\n", |
2154 (rset_marked_pointers + rset_marked_array_elements), | 2154 (rset_marked_pointers + rset_marked_array_elements), |
2155 (cross_gen_pointers + cross_gen_array_elements), | 2155 (cross_gen_pointers + cross_gen_array_elements), |
2156 pct); | 2156 pct); |
2157 | 2157 |
2158 ClearHistograms(); | 2158 ClearHistograms(); |
2159 HeapObjectIterator obj_it(this); | 2159 HeapObjectIterator obj_it(this); |
2160 while (obj_it.has_next()) { CollectHistogramInfo(obj_it.next()); } | 2160 for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) |
| 2161 CollectHistogramInfo(obj); |
2161 ReportHistogram(true); | 2162 ReportHistogram(true); |
2162 } | 2163 } |
2163 | 2164 |
2164 | 2165 |
2165 // Dump the range of remembered set words between [start, end) corresponding | 2166 // Dump the range of remembered set words between [start, end) corresponding |
2166 // to the pointers starting at object_p. The allocation_top is an object | 2167 // to the pointers starting at object_p. The allocation_top is an object |
2167 // pointer which should not be read past. This is important for large object | 2168 // pointer which should not be read past. This is important for large object |
2168 // pages, where some bits in the remembered set range do not correspond to | 2169 // pages, where some bits in the remembered set range do not correspond to |
2169 // allocated addresses. | 2170 // allocated addresses. |
2170 static void PrintRSetRange(Address start, Address end, Object** object_p, | 2171 static void PrintRSetRange(Address start, Address end, Object** object_p, |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2386 } | 2387 } |
2387 } | 2388 } |
2388 | 2389 |
2389 pct = rset_marked_pointers == 0 ? | 2390 pct = rset_marked_pointers == 0 ? |
2390 0 : cross_gen_pointers * 100 / rset_marked_pointers; | 2391 0 : cross_gen_pointers * 100 / rset_marked_pointers; |
2391 PrintF(" rset-marked pointers %d, to-new-space %d (%%%d)\n", | 2392 PrintF(" rset-marked pointers %d, to-new-space %d (%%%d)\n", |
2392 rset_marked_pointers, cross_gen_pointers, pct); | 2393 rset_marked_pointers, cross_gen_pointers, pct); |
2393 | 2394 |
2394 ClearHistograms(); | 2395 ClearHistograms(); |
2395 HeapObjectIterator obj_it(this); | 2396 HeapObjectIterator obj_it(this); |
2396 while (obj_it.has_next()) { CollectHistogramInfo(obj_it.next()); } | 2397 for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) |
| 2398 CollectHistogramInfo(obj); |
2397 ReportHistogram(false); | 2399 ReportHistogram(false); |
2398 } | 2400 } |
2399 | 2401 |
2400 | 2402 |
2401 void FixedSpace::PrintRSet() { DoPrintRSet(name_); } | 2403 void FixedSpace::PrintRSet() { DoPrintRSet(name_); } |
2402 #endif | 2404 #endif |
2403 | 2405 |
2404 | 2406 |
2405 // ----------------------------------------------------------------------------- | 2407 // ----------------------------------------------------------------------------- |
2406 // MapSpace implementation | 2408 // MapSpace implementation |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2455 | 2457 |
2456 | 2458 |
2457 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space, | 2459 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space, |
2458 HeapObjectCallback size_func) { | 2460 HeapObjectCallback size_func) { |
2459 current_ = space->first_chunk_; | 2461 current_ = space->first_chunk_; |
2460 size_func_ = size_func; | 2462 size_func_ = size_func; |
2461 } | 2463 } |
2462 | 2464 |
2463 | 2465 |
2464 HeapObject* LargeObjectIterator::next() { | 2466 HeapObject* LargeObjectIterator::next() { |
2465 ASSERT(has_next()); | 2467 if (current_ == NULL) return NULL; |
| 2468 |
2466 HeapObject* object = current_->GetObject(); | 2469 HeapObject* object = current_->GetObject(); |
2467 current_ = current_->next(); | 2470 current_ = current_->next(); |
2468 return object; | 2471 return object; |
2469 } | 2472 } |
2470 | 2473 |
2471 | 2474 |
2472 // ----------------------------------------------------------------------------- | 2475 // ----------------------------------------------------------------------------- |
2473 // LargeObjectChunk | 2476 // LargeObjectChunk |
2474 | 2477 |
2475 LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes, | 2478 LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes, |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2632 } | 2635 } |
2633 } | 2636 } |
2634 return Failure::Exception(); | 2637 return Failure::Exception(); |
2635 } | 2638 } |
2636 | 2639 |
2637 | 2640 |
2638 void LargeObjectSpace::ClearRSet() { | 2641 void LargeObjectSpace::ClearRSet() { |
2639 ASSERT(Page::is_rset_in_use()); | 2642 ASSERT(Page::is_rset_in_use()); |
2640 | 2643 |
2641 LargeObjectIterator it(this); | 2644 LargeObjectIterator it(this); |
2642 while (it.has_next()) { | 2645 for (HeapObject* object = it.next(); object != NULL; object = it.next()) { |
2643 HeapObject* object = it.next(); | |
2644 // We only have code, sequential strings, or fixed arrays in large | 2646 // We only have code, sequential strings, or fixed arrays in large |
2645 // object space, and only fixed arrays need remembered set support. | 2647 // object space, and only fixed arrays need remembered set support. |
2646 if (object->IsFixedArray()) { | 2648 if (object->IsFixedArray()) { |
2647 // Clear the normal remembered set region of the page; | 2649 // Clear the normal remembered set region of the page; |
2648 Page* page = Page::FromAddress(object->address()); | 2650 Page* page = Page::FromAddress(object->address()); |
2649 page->ClearRSet(); | 2651 page->ClearRSet(); |
2650 | 2652 |
2651 // Clear the extra remembered set. | 2653 // Clear the extra remembered set. |
2652 int size = object->Size(); | 2654 int size = object->Size(); |
2653 int extra_rset_bytes = ExtraRSetBytesFor(size); | 2655 int extra_rset_bytes = ExtraRSetBytesFor(size); |
2654 memset(object->address() + size, 0, extra_rset_bytes); | 2656 memset(object->address() + size, 0, extra_rset_bytes); |
2655 } | 2657 } |
2656 } | 2658 } |
2657 } | 2659 } |
2658 | 2660 |
2659 | 2661 |
2660 void LargeObjectSpace::IterateRSet(ObjectSlotCallback copy_object_func) { | 2662 void LargeObjectSpace::IterateRSet(ObjectSlotCallback copy_object_func) { |
2661 ASSERT(Page::is_rset_in_use()); | 2663 ASSERT(Page::is_rset_in_use()); |
2662 | 2664 |
2663 static void* lo_rset_histogram = StatsTable::CreateHistogram( | 2665 static void* lo_rset_histogram = StatsTable::CreateHistogram( |
2664 "V8.RSetLO", | 2666 "V8.RSetLO", |
2665 0, | 2667 0, |
2666 // Keeping this histogram's buckets the same as the paged space histogram. | 2668 // Keeping this histogram's buckets the same as the paged space histogram. |
2667 Page::kObjectAreaSize / kPointerSize, | 2669 Page::kObjectAreaSize / kPointerSize, |
2668 30); | 2670 30); |
2669 | 2671 |
2670 LargeObjectIterator it(this); | 2672 LargeObjectIterator it(this); |
2671 while (it.has_next()) { | 2673 for (HeapObject* object = it.next(); object != NULL; object = it.next()) { |
2672 // We only have code, sequential strings, or fixed arrays in large | 2674 // We only have code, sequential strings, or fixed arrays in large |
2673 // object space, and only fixed arrays can possibly contain pointers to | 2675 // object space, and only fixed arrays can possibly contain pointers to |
2674 // the young generation. | 2676 // the young generation. |
2675 HeapObject* object = it.next(); | |
2676 if (object->IsFixedArray()) { | 2677 if (object->IsFixedArray()) { |
2677 // Iterate the normal page remembered set range. | 2678 // Iterate the normal page remembered set range. |
2678 Page* page = Page::FromAddress(object->address()); | 2679 Page* page = Page::FromAddress(object->address()); |
2679 Address object_end = object->address() + object->Size(); | 2680 Address object_end = object->address() + object->Size(); |
2680 int count = Heap::IterateRSetRange(page->ObjectAreaStart(), | 2681 int count = Heap::IterateRSetRange(page->ObjectAreaStart(), |
2681 Min(page->ObjectAreaEnd(), object_end), | 2682 Min(page->ObjectAreaEnd(), object_end), |
2682 page->RSetStart(), | 2683 page->RSetStart(), |
2683 copy_object_func); | 2684 copy_object_func); |
2684 | 2685 |
2685 // Iterate the extra array elements. | 2686 // Iterate the extra array elements. |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2791 } | 2792 } |
2792 } | 2793 } |
2793 } | 2794 } |
2794 } | 2795 } |
2795 } | 2796 } |
2796 } | 2797 } |
2797 | 2798 |
2798 | 2799 |
2799 void LargeObjectSpace::Print() { | 2800 void LargeObjectSpace::Print() { |
2800 LargeObjectIterator it(this); | 2801 LargeObjectIterator it(this); |
2801 while (it.has_next()) { | 2802 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) { |
2802 it.next()->Print(); | 2803 obj->Print(); |
2803 } | 2804 } |
2804 } | 2805 } |
2805 | 2806 |
2806 | 2807 |
2807 void LargeObjectSpace::ReportStatistics() { | 2808 void LargeObjectSpace::ReportStatistics() { |
2808 PrintF(" size: %d\n", size_); | 2809 PrintF(" size: %d\n", size_); |
2809 int num_objects = 0; | 2810 int num_objects = 0; |
2810 ClearHistograms(); | 2811 ClearHistograms(); |
2811 LargeObjectIterator it(this); | 2812 LargeObjectIterator it(this); |
2812 while (it.has_next()) { | 2813 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) { |
2813 num_objects++; | 2814 num_objects++; |
2814 CollectHistogramInfo(it.next()); | 2815 CollectHistogramInfo(obj); |
2815 } | 2816 } |
2816 | 2817 |
2817 PrintF(" number of objects %d\n", num_objects); | 2818 PrintF(" number of objects %d\n", num_objects); |
2818 if (num_objects > 0) ReportHistogram(false); | 2819 if (num_objects > 0) ReportHistogram(false); |
2819 } | 2820 } |
2820 | 2821 |
2821 | 2822 |
2822 void LargeObjectSpace::CollectCodeStatistics() { | 2823 void LargeObjectSpace::CollectCodeStatistics() { |
2823 LargeObjectIterator obj_it(this); | 2824 LargeObjectIterator obj_it(this); |
2824 while (obj_it.has_next()) { | 2825 for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) { |
2825 HeapObject* obj = obj_it.next(); | |
2826 if (obj->IsCode()) { | 2826 if (obj->IsCode()) { |
2827 Code* code = Code::cast(obj); | 2827 Code* code = Code::cast(obj); |
2828 code_kind_statistics[code->kind()] += code->Size(); | 2828 code_kind_statistics[code->kind()] += code->Size(); |
2829 } | 2829 } |
2830 } | 2830 } |
2831 } | 2831 } |
2832 | 2832 |
2833 | 2833 |
2834 void LargeObjectSpace::PrintRSet() { | 2834 void LargeObjectSpace::PrintRSet() { |
2835 LargeObjectIterator it(this); | 2835 LargeObjectIterator it(this); |
2836 while (it.has_next()) { | 2836 for (HeapObject* object = it.next(); object != NULL; object = it.next()) { |
2837 HeapObject* object = it.next(); | |
2838 if (object->IsFixedArray()) { | 2837 if (object->IsFixedArray()) { |
2839 Page* page = Page::FromAddress(object->address()); | 2838 Page* page = Page::FromAddress(object->address()); |
2840 | 2839 |
2841 Address allocation_top = object->address() + object->Size(); | 2840 Address allocation_top = object->address() + object->Size(); |
2842 PrintF("large page 0x%x:\n", page); | 2841 PrintF("large page 0x%x:\n", page); |
2843 PrintRSetRange(page->RSetStart(), page->RSetEnd(), | 2842 PrintRSetRange(page->RSetStart(), page->RSetEnd(), |
2844 reinterpret_cast<Object**>(object->address()), | 2843 reinterpret_cast<Object**>(object->address()), |
2845 allocation_top); | 2844 allocation_top); |
2846 int extra_array_bytes = object->Size() - Page::kObjectAreaSize; | 2845 int extra_array_bytes = object->Size() - Page::kObjectAreaSize; |
2847 int extra_rset_bits = RoundUp(extra_array_bytes / kPointerSize, | 2846 int extra_rset_bits = RoundUp(extra_array_bytes / kPointerSize, |
2848 kBitsPerInt); | 2847 kBitsPerInt); |
2849 PrintF("------------------------------------------------------------" | 2848 PrintF("------------------------------------------------------------" |
2850 "-----------\n"); | 2849 "-----------\n"); |
2851 PrintRSetRange(allocation_top, | 2850 PrintRSetRange(allocation_top, |
2852 allocation_top + extra_rset_bits / kBitsPerByte, | 2851 allocation_top + extra_rset_bits / kBitsPerByte, |
2853 reinterpret_cast<Object**>(object->address() | 2852 reinterpret_cast<Object**>(object->address() |
2854 + Page::kObjectAreaSize), | 2853 + Page::kObjectAreaSize), |
2855 allocation_top); | 2854 allocation_top); |
2856 PrintF("\n"); | 2855 PrintF("\n"); |
2857 } | 2856 } |
2858 } | 2857 } |
2859 } | 2858 } |
2860 #endif // DEBUG | 2859 #endif // DEBUG |
2861 | 2860 |
2862 } } // namespace v8::internal | 2861 } } // namespace v8::internal |
OLD | NEW |