| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 | 774 |
| 775 if (over_reserved > reserved / 3 && over_reserved >= 2 * space->AreaSize()) { | 775 if (over_reserved > reserved / 3 && over_reserved >= 2 * space->AreaSize()) { |
| 776 // If over-usage is very high (more than a third of the space), we | 776 // If over-usage is very high (more than a third of the space), we |
| 777 // try to free all mostly empty pages. We expect that almost empty | 777 // try to free all mostly empty pages. We expect that almost empty |
| 778 // pages are even easier to compact so bump the limit even more. | 778 // pages are even easier to compact so bump the limit even more. |
| 779 mode = REDUCE_MEMORY_FOOTPRINT; | 779 mode = REDUCE_MEMORY_FOOTPRINT; |
| 780 max_evacuation_candidates *= 2; | 780 max_evacuation_candidates *= 2; |
| 781 } | 781 } |
| 782 | 782 |
| 783 if (FLAG_trace_fragmentation && mode == REDUCE_MEMORY_FOOTPRINT) { | 783 if (FLAG_trace_fragmentation && mode == REDUCE_MEMORY_FOOTPRINT) { |
| 784 PrintF("Estimated over reserved memory: %.1f / %.1f MB (threshold %d)\n", | 784 PrintF("Estimated over reserved memory: %.1f / %.1f MB (threshold %d), " |
| 785 "evacuation candidate limit: %d\n", |
| 785 static_cast<double>(over_reserved) / MB, | 786 static_cast<double>(over_reserved) / MB, |
| 786 static_cast<double>(reserved) / MB, | 787 static_cast<double>(reserved) / MB, |
| 787 static_cast<int>(kFreenessThreshold)); | 788 static_cast<int>(kFreenessThreshold), |
| 789 max_evacuation_candidates); |
| 788 } | 790 } |
| 789 | 791 |
| 790 intptr_t estimated_release = 0; | 792 intptr_t estimated_release = 0; |
| 791 | 793 |
| 792 Candidate candidates[kMaxMaxEvacuationCandidates]; | 794 Candidate candidates[kMaxMaxEvacuationCandidates]; |
| 793 | 795 |
| 794 max_evacuation_candidates = | 796 max_evacuation_candidates = |
| 795 Min(kMaxMaxEvacuationCandidates, max_evacuation_candidates); | 797 Min(kMaxMaxEvacuationCandidates, max_evacuation_candidates); |
| 796 | 798 |
| 797 int count = 0; | 799 int count = 0; |
| 798 int fragmentation = 0; | 800 int fragmentation = 0; |
| 799 Candidate* least = NULL; | 801 Candidate* least = NULL; |
| 800 | 802 |
| 801 PageIterator it(space); | 803 PageIterator it(space); |
| 802 if (it.has_next()) it.next(); // Never compact the first page. | 804 if (it.has_next()) it.next(); // Never compact the first page. |
| 803 | 805 |
| 804 while (it.has_next()) { | 806 while (it.has_next()) { |
| 805 Page* p = it.next(); | 807 Page* p = it.next(); |
| 806 p->ClearEvacuationCandidate(); | 808 p->ClearEvacuationCandidate(); |
| 807 | 809 |
| 808 if (FLAG_stress_compaction) { | 810 if (FLAG_stress_compaction) { |
| 809 unsigned int counter = space->heap()->ms_count(); | 811 unsigned int counter = space->heap()->ms_count(); |
| 810 uintptr_t page_number = reinterpret_cast<uintptr_t>(p) >> kPageSizeBits; | 812 uintptr_t page_number = reinterpret_cast<uintptr_t>(p) >> kPageSizeBits; |
| 811 if ((counter & 1) == (page_number & 1)) fragmentation = 1; | 813 if ((counter & 1) == (page_number & 1)) fragmentation = 1; |
| 812 } else if (mode == REDUCE_MEMORY_FOOTPRINT) { | 814 } else if (mode == REDUCE_MEMORY_FOOTPRINT) { |
| 813 // Don't try to release too many pages. | 815 // Don't try to release too many pages. |
| 814 if (estimated_release >= ((over_reserved * 3) / 4)) { | 816 if (estimated_release >= over_reserved) { |
| 815 continue; | 817 continue; |
| 816 } | 818 } |
| 817 | 819 |
| 818 intptr_t free_bytes = 0; | 820 intptr_t free_bytes = 0; |
| 819 | 821 |
| 820 if (!p->WasSwept()) { | 822 if (!p->WasSwept()) { |
| 821 free_bytes = (p->area_size() - p->LiveBytes()); | 823 free_bytes = (p->area_size() - p->LiveBytes()); |
| 822 } else { | 824 } else { |
| 823 PagedSpace::SizeStats sizes; | 825 PagedSpace::SizeStats sizes; |
| 824 space->ObtainFreeListStatistics(p, &sizes); | 826 space->ObtainFreeListStatistics(p, &sizes); |
| 825 free_bytes = sizes.Total(); | 827 free_bytes = sizes.Total(); |
| 826 } | 828 } |
| 827 | 829 |
| 828 int free_pct = static_cast<int>(free_bytes * 100) / p->area_size(); | 830 int free_pct = static_cast<int>(free_bytes * 100) / p->area_size(); |
| 829 | 831 |
| 830 if (free_pct >= kFreenessThreshold) { | 832 if (free_pct >= kFreenessThreshold) { |
| 831 estimated_release += 2 * p->area_size() - free_bytes; | 833 estimated_release += free_bytes; |
| 832 fragmentation = free_pct; | 834 fragmentation = free_pct; |
| 833 } else { | 835 } else { |
| 834 fragmentation = 0; | 836 fragmentation = 0; |
| 835 } | 837 } |
| 836 | 838 |
| 837 if (FLAG_trace_fragmentation) { | 839 if (FLAG_trace_fragmentation) { |
| 838 PrintF("%p [%s]: %d (%.2f%%) free %s\n", | 840 PrintF("%p [%s]: %d (%.2f%%) free %s\n", |
| 839 reinterpret_cast<void*>(p), | 841 reinterpret_cast<void*>(p), |
| 840 AllocationSpaceName(space->identity()), | 842 AllocationSpaceName(space->identity()), |
| 841 static_cast<int>(free_bytes), | 843 static_cast<int>(free_bytes), |
| (...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1922 marking_deque->PushBlack(object); | 1924 marking_deque->PushBlack(object); |
| 1923 if (marking_deque->IsFull()) return; | 1925 if (marking_deque->IsFull()) return; |
| 1924 } | 1926 } |
| 1925 } | 1927 } |
| 1926 } | 1928 } |
| 1927 | 1929 |
| 1928 | 1930 |
| 1929 static inline int MarkWordToObjectStarts(uint32_t mark_bits, int* starts); | 1931 static inline int MarkWordToObjectStarts(uint32_t mark_bits, int* starts); |
| 1930 | 1932 |
| 1931 | 1933 |
| 1932 static void DiscoverGreyObjectsOnPage(MarkingDeque* marking_deque, Page* p) { | 1934 static void DiscoverGreyObjectsOnPage(MarkingDeque* marking_deque, |
| 1935 MemoryChunk* p) { |
| 1933 ASSERT(!marking_deque->IsFull()); | 1936 ASSERT(!marking_deque->IsFull()); |
| 1934 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 1937 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
| 1935 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 1938 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| 1936 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); | 1939 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); |
| 1937 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 1940 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
| 1938 | 1941 |
| 1939 MarkBit::CellType* cells = p->markbits()->cells(); | 1942 MarkBit::CellType* cells = p->markbits()->cells(); |
| 1940 | 1943 |
| 1941 int last_cell_index = | 1944 int last_cell_index = |
| 1942 Bitmap::IndexToCell( | 1945 Bitmap::IndexToCell( |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1996 PageIterator it(space); | 1999 PageIterator it(space); |
| 1997 while (it.has_next()) { | 2000 while (it.has_next()) { |
| 1998 Page* p = it.next(); | 2001 Page* p = it.next(); |
| 1999 DiscoverGreyObjectsOnPage(marking_deque, p); | 2002 DiscoverGreyObjectsOnPage(marking_deque, p); |
| 2000 if (marking_deque->IsFull()) return; | 2003 if (marking_deque->IsFull()) return; |
| 2001 } | 2004 } |
| 2002 } | 2005 } |
| 2003 } | 2006 } |
| 2004 | 2007 |
| 2005 | 2008 |
| 2009 static void DiscoverGreyObjectsInNewSpace(Heap* heap, |
| 2010 MarkingDeque* marking_deque) { |
| 2011 NewSpace* space = heap->new_space(); |
| 2012 NewSpacePageIterator it(space->bottom(), space->top()); |
| 2013 while (it.has_next()) { |
| 2014 NewSpacePage* page = it.next(); |
| 2015 DiscoverGreyObjectsOnPage(marking_deque, page); |
| 2016 if (marking_deque->IsFull()) return; |
| 2017 } |
| 2018 } |
| 2019 |
| 2020 |
| 2006 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { | 2021 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { |
| 2007 Object* o = *p; | 2022 Object* o = *p; |
| 2008 if (!o->IsHeapObject()) return false; | 2023 if (!o->IsHeapObject()) return false; |
| 2009 HeapObject* heap_object = HeapObject::cast(o); | 2024 HeapObject* heap_object = HeapObject::cast(o); |
| 2010 MarkBit mark = Marking::MarkBitFrom(heap_object); | 2025 MarkBit mark = Marking::MarkBitFrom(heap_object); |
| 2011 return !mark.Get(); | 2026 return !mark.Get(); |
| 2012 } | 2027 } |
| 2013 | 2028 |
| 2014 | 2029 |
| 2015 bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap, | 2030 bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap, |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2102 | 2117 |
| 2103 | 2118 |
| 2104 // Sweep the heap for overflowed objects, clear their overflow bits, and | 2119 // Sweep the heap for overflowed objects, clear their overflow bits, and |
| 2105 // push them on the marking stack. Stop early if the marking stack fills | 2120 // push them on the marking stack. Stop early if the marking stack fills |
| 2106 // before sweeping completes. If sweeping completes, there are no remaining | 2121 // before sweeping completes. If sweeping completes, there are no remaining |
| 2107 // overflowed objects in the heap so the overflow flag on the markings stack | 2122 // overflowed objects in the heap so the overflow flag on the markings stack |
| 2108 // is cleared. | 2123 // is cleared. |
| 2109 void MarkCompactCollector::RefillMarkingDeque() { | 2124 void MarkCompactCollector::RefillMarkingDeque() { |
| 2110 ASSERT(marking_deque_.overflowed()); | 2125 ASSERT(marking_deque_.overflowed()); |
| 2111 | 2126 |
| 2112 SemiSpaceIterator new_it(heap()->new_space()); | 2127 DiscoverGreyObjectsInNewSpace(heap(), &marking_deque_); |
| 2113 DiscoverGreyObjectsWithIterator(heap(), &marking_deque_, &new_it); | |
| 2114 if (marking_deque_.IsFull()) return; | 2128 if (marking_deque_.IsFull()) return; |
| 2115 | 2129 |
| 2116 DiscoverGreyObjectsInSpace(heap(), | 2130 DiscoverGreyObjectsInSpace(heap(), |
| 2117 &marking_deque_, | 2131 &marking_deque_, |
| 2118 heap()->old_pointer_space()); | 2132 heap()->old_pointer_space()); |
| 2119 if (marking_deque_.IsFull()) return; | 2133 if (marking_deque_.IsFull()) return; |
| 2120 | 2134 |
| 2121 DiscoverGreyObjectsInSpace(heap(), | 2135 DiscoverGreyObjectsInSpace(heap(), |
| 2122 &marking_deque_, | 2136 &marking_deque_, |
| 2123 heap()->old_data_space()); | 2137 heap()->old_data_space()); |
| (...skipping 2193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4317 while (buffer != NULL) { | 4331 while (buffer != NULL) { |
| 4318 SlotsBuffer* next_buffer = buffer->next(); | 4332 SlotsBuffer* next_buffer = buffer->next(); |
| 4319 DeallocateBuffer(buffer); | 4333 DeallocateBuffer(buffer); |
| 4320 buffer = next_buffer; | 4334 buffer = next_buffer; |
| 4321 } | 4335 } |
| 4322 *buffer_address = NULL; | 4336 *buffer_address = NULL; |
| 4323 } | 4337 } |
| 4324 | 4338 |
| 4325 | 4339 |
| 4326 } } // namespace v8::internal | 4340 } } // namespace v8::internal |
| OLD | NEW |