| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1666 ASSERT(map() == NULL || Size() >= kNextOffset + kPointerSize); | 1666 ASSERT(map() == NULL || Size() >= kNextOffset + kPointerSize); |
| 1667 Memory::Address_at(address() + kNextOffset) = | 1667 Memory::Address_at(address() + kNextOffset) = |
| 1668 reinterpret_cast<Address>(next); | 1668 reinterpret_cast<Address>(next); |
| 1669 } else { | 1669 } else { |
| 1670 Memory::Address_at(address() + kPointerSize) = | 1670 Memory::Address_at(address() + kPointerSize) = |
| 1671 reinterpret_cast<Address>(next); | 1671 reinterpret_cast<Address>(next); |
| 1672 } | 1672 } |
| 1673 } | 1673 } |
| 1674 | 1674 |
| 1675 | 1675 |
| 1676 OldSpaceFreeList::OldSpaceFreeList(PagedSpace* owner) | 1676 FreeList::FreeList(PagedSpace* owner) |
| 1677 : owner_(owner), heap_(owner->heap()) { | 1677 : owner_(owner), heap_(owner->heap()) { |
| 1678 Reset(); | 1678 Reset(); |
| 1679 } | 1679 } |
| 1680 | 1680 |
| 1681 | 1681 |
| 1682 void OldSpaceFreeList::Reset() { | 1682 void FreeList::Reset() { |
| 1683 available_ = 0; | 1683 available_ = 0; |
| 1684 small_list_ = NULL; | 1684 small_list_ = NULL; |
| 1685 medium_list_ = NULL; | 1685 medium_list_ = NULL; |
| 1686 large_list_ = NULL; | 1686 large_list_ = NULL; |
| 1687 huge_list_ = NULL; | 1687 huge_list_ = NULL; |
| 1688 } | 1688 } |
| 1689 | 1689 |
| 1690 | 1690 |
| 1691 int OldSpaceFreeList::Free(Address start, int size_in_bytes) { | 1691 int FreeList::Free(Address start, int size_in_bytes) { |
| 1692 if (size_in_bytes == 0) return 0; | 1692 if (size_in_bytes == 0) return 0; |
| 1693 FreeListNode* node = FreeListNode::FromAddress(start); | 1693 FreeListNode* node = FreeListNode::FromAddress(start); |
| 1694 node->set_size(heap_, size_in_bytes); | 1694 node->set_size(heap_, size_in_bytes); |
| 1695 | 1695 |
| 1696 // Early return to drop too-small blocks on the floor. | 1696 // Early return to drop too-small blocks on the floor. |
| 1697 if (size_in_bytes < kSmallListMin) return size_in_bytes; | 1697 if (size_in_bytes < kSmallListMin) return size_in_bytes; |
| 1698 | 1698 |
| 1699 // Insert other blocks at the head of a free list of the appropriate | 1699 // Insert other blocks at the head of a free list of the appropriate |
| 1700 // magnitude. | 1700 // magnitude. |
| 1701 if (size_in_bytes <= kSmallListMax) { | 1701 if (size_in_bytes <= kSmallListMax) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1714 available_ += size_in_bytes; | 1714 available_ += size_in_bytes; |
| 1715 ASSERT(IsVeryLong() || available_ == SumFreeLists()); | 1715 ASSERT(IsVeryLong() || available_ == SumFreeLists()); |
| 1716 return 0; | 1716 return 0; |
| 1717 } | 1717 } |
| 1718 | 1718 |
| 1719 | 1719 |
| 1720 // Allocation on the old space free list. If it succeeds then a new linear | 1720 // Allocation on the old space free list. If it succeeds then a new linear |
| 1721 // allocation space has been set up with the top and limit of the space. If | 1721 // allocation space has been set up with the top and limit of the space. If |
| 1722 // the allocation fails then NULL is returned, and the caller can perform a GC | 1722 // the allocation fails then NULL is returned, and the caller can perform a GC |
| 1723 // or allocate a new page before retrying. | 1723 // or allocate a new page before retrying. |
| 1724 HeapObject* OldSpaceFreeList::Allocate(int size_in_bytes) { | 1724 HeapObject* FreeList::Allocate(int size_in_bytes) { |
| 1725 ASSERT(0 < size_in_bytes); | 1725 ASSERT(0 < size_in_bytes); |
| 1726 ASSERT(size_in_bytes <= kMaxBlockSize); | 1726 ASSERT(size_in_bytes <= kMaxBlockSize); |
| 1727 ASSERT(IsAligned(size_in_bytes, kPointerSize)); | 1727 ASSERT(IsAligned(size_in_bytes, kPointerSize)); |
| 1728 // Don't free list allocate if there is linear space available. | 1728 // Don't free list allocate if there is linear space available. |
| 1729 ASSERT(owner_->limit() - owner_->top() < size_in_bytes); | 1729 ASSERT(owner_->limit() - owner_->top() < size_in_bytes); |
| 1730 | 1730 |
| 1731 FreeListNode* new_node = NULL; | 1731 FreeListNode* new_node = NULL; |
| 1732 int new_node_size = 0; | 1732 int new_node_size = 0; |
| 1733 | 1733 |
| 1734 if (size_in_bytes <= kSmallAllocationMax && small_list_ != NULL) { | 1734 if (size_in_bytes <= kSmallAllocationMax && small_list_ != NULL) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1795 // Normally we give the rest of the node to the allocator as its new | 1795 // Normally we give the rest of the node to the allocator as its new |
| 1796 // linear allocation area. | 1796 // linear allocation area. |
| 1797 owner_->SetTop(new_node->address() + size_in_bytes, | 1797 owner_->SetTop(new_node->address() + size_in_bytes, |
| 1798 new_node->address() + new_node_size); | 1798 new_node->address() + new_node_size); |
| 1799 } | 1799 } |
| 1800 | 1800 |
| 1801 return new_node; | 1801 return new_node; |
| 1802 } | 1802 } |
| 1803 | 1803 |
| 1804 | 1804 |
| 1805 static intptr_t CountFreeListItemsInList(FreeListNode* n, Page* p) { |
| 1806 intptr_t sum = 0; |
| 1807 while (n != NULL) { |
| 1808 if (Page::FromAddress(n->address()) == p) { |
| 1809 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(n); |
| 1810 sum += free_space->Size(); |
| 1811 } |
| 1812 n = n->next(); |
| 1813 } |
| 1814 return sum; |
| 1815 } |
| 1816 |
| 1817 |
| 1818 void FreeList::CountFreeListItems(Page* p, intptr_t* sizes) { |
| 1819 sizes[0] = CountFreeListItemsInList(small_list_, p); |
| 1820 sizes[1] = CountFreeListItemsInList(medium_list_, p); |
| 1821 sizes[2] = CountFreeListItemsInList(large_list_, p); |
| 1822 sizes[3] = CountFreeListItemsInList(huge_list_, p); |
| 1823 } |
| 1824 |
| 1805 #ifdef DEBUG | 1825 #ifdef DEBUG |
| 1806 intptr_t OldSpaceFreeList::SumFreeList(FreeListNode* cur) { | 1826 intptr_t FreeList::SumFreeList(FreeListNode* cur) { |
| 1807 intptr_t sum = 0; | 1827 intptr_t sum = 0; |
| 1808 while (cur != NULL) { | 1828 while (cur != NULL) { |
| 1809 ASSERT(cur->map() == HEAP->raw_unchecked_free_space_map()); | 1829 ASSERT(cur->map() == HEAP->raw_unchecked_free_space_map()); |
| 1810 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(cur); | 1830 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(cur); |
| 1811 sum += cur_as_free_space->Size(); | 1831 sum += cur_as_free_space->Size(); |
| 1812 cur = cur->next(); | 1832 cur = cur->next(); |
| 1813 } | 1833 } |
| 1814 return sum; | 1834 return sum; |
| 1815 } | 1835 } |
| 1816 | 1836 |
| 1817 | 1837 |
| 1818 static const int kVeryLongFreeList = 500; | 1838 static const int kVeryLongFreeList = 500; |
| 1819 | 1839 |
| 1820 | 1840 |
| 1821 int OldSpaceFreeList::FreeListLength(FreeListNode* cur) { | 1841 int FreeList::FreeListLength(FreeListNode* cur) { |
| 1822 int length = 0; | 1842 int length = 0; |
| 1823 while (cur != NULL) { | 1843 while (cur != NULL) { |
| 1824 length++; | 1844 length++; |
| 1825 cur = cur->next(); | 1845 cur = cur->next(); |
| 1826 if (length == kVeryLongFreeList) return length; | 1846 if (length == kVeryLongFreeList) return length; |
| 1827 } | 1847 } |
| 1828 return length; | 1848 return length; |
| 1829 } | 1849 } |
| 1830 | 1850 |
| 1831 | 1851 |
| 1832 bool OldSpaceFreeList::IsVeryLong() { | 1852 bool FreeList::IsVeryLong() { |
| 1833 if (FreeListLength(small_list_) == kVeryLongFreeList) return true; | 1853 if (FreeListLength(small_list_) == kVeryLongFreeList) return true; |
| 1834 if (FreeListLength(medium_list_) == kVeryLongFreeList) return true; | 1854 if (FreeListLength(medium_list_) == kVeryLongFreeList) return true; |
| 1835 if (FreeListLength(large_list_) == kVeryLongFreeList) return true; | 1855 if (FreeListLength(large_list_) == kVeryLongFreeList) return true; |
| 1836 if (FreeListLength(huge_list_) == kVeryLongFreeList) return true; | 1856 if (FreeListLength(huge_list_) == kVeryLongFreeList) return true; |
| 1837 return false; | 1857 return false; |
| 1838 } | 1858 } |
| 1839 | 1859 |
| 1840 | 1860 |
| 1841 // This can take a very long time because it is linear in the number of entries | 1861 // This can take a very long time because it is linear in the number of entries |
| 1842 // on the free list, so it should not be called if FreeListLength returns | 1862 // on the free list, so it should not be called if FreeListLength returns |
| 1843 // kVeryLongFreeList. | 1863 // kVeryLongFreeList. |
| 1844 intptr_t OldSpaceFreeList::SumFreeLists() { | 1864 intptr_t FreeList::SumFreeLists() { |
| 1845 intptr_t sum = SumFreeList(small_list_); | 1865 intptr_t sum = SumFreeList(small_list_); |
| 1846 sum += SumFreeList(medium_list_); | 1866 sum += SumFreeList(medium_list_); |
| 1847 sum += SumFreeList(large_list_); | 1867 sum += SumFreeList(large_list_); |
| 1848 sum += SumFreeList(huge_list_); | 1868 sum += SumFreeList(huge_list_); |
| 1849 return sum; | 1869 return sum; |
| 1850 } | 1870 } |
| 1851 #endif | 1871 #endif |
| 1852 | 1872 |
| 1853 | 1873 |
| 1854 // ----------------------------------------------------------------------------- | 1874 // ----------------------------------------------------------------------------- |
| 1855 // OldSpace implementation | 1875 // OldSpace implementation |
| 1856 | 1876 |
| 1857 void OldSpace::PrepareForMarkCompact(bool will_compact) { | 1877 void OldSpace::PrepareForMarkCompact() { |
| 1858 ASSERT(!will_compact); | |
| 1859 // Call prepare of the super class. | 1878 // Call prepare of the super class. |
| 1860 PagedSpace::PrepareForMarkCompact(will_compact); | 1879 PagedSpace::PrepareForMarkCompact(); |
| 1861 | 1880 |
| 1881 // Stop lazy sweeping for this space. |
| 1862 first_unswept_page_ = last_unswept_page_ = Page::FromAddress(NULL); | 1882 first_unswept_page_ = last_unswept_page_ = Page::FromAddress(NULL); |
| 1863 | 1883 |
| 1864 // Clear the free list before a full GC---it will be rebuilt afterward. | 1884 // Clear the free list before a full GC---it will be rebuilt afterward. |
| 1865 // TODO(gc): can we avoid resetting free list? | |
| 1866 free_list_.Reset(); | 1885 free_list_.Reset(); |
| 1867 } | 1886 } |
| 1868 | 1887 |
| 1869 | 1888 |
| 1870 bool NewSpace::ReserveSpace(int bytes) { | 1889 bool NewSpace::ReserveSpace(int bytes) { |
| 1871 // We can't reliably unpack a partial snapshot that needs more new space | 1890 // We can't reliably unpack a partial snapshot that needs more new space |
| 1872 // space than the minimum NewSpace size. | 1891 // space than the minimum NewSpace size. |
| 1873 ASSERT(bytes <= InitialCapacity()); | 1892 ASSERT(bytes <= InitialCapacity()); |
| 1874 Address limit = allocation_info_.limit; | 1893 Address limit = allocation_info_.limit; |
| 1875 Address top = allocation_info_.top; | 1894 Address top = allocation_info_.top; |
| 1876 return limit - top >= bytes; | 1895 return limit - top >= bytes; |
| 1877 } | 1896 } |
| 1878 | 1897 |
| 1879 | 1898 |
| 1880 void PagedSpace::PrepareForMarkCompact(bool will_compact) { | 1899 void PagedSpace::PrepareForMarkCompact() { |
| 1881 ASSERT(!will_compact); | |
| 1882 // We don't have a linear allocation area while sweeping. It will be restored | 1900 // We don't have a linear allocation area while sweeping. It will be restored |
| 1883 // on the first allocation after the sweep. | 1901 // on the first allocation after the sweep. |
| 1884 // Mark the old linear allocation area with a free space map so it can be | 1902 // Mark the old linear allocation area with a free space map so it can be |
| 1885 // skipped when scanning the heap. | 1903 // skipped when scanning the heap. |
| 1886 int old_linear_size = limit() - top(); | 1904 int old_linear_size = limit() - top(); |
| 1887 Free(top(), old_linear_size); | 1905 Free(top(), old_linear_size); |
| 1888 SetTop(NULL, NULL); | 1906 SetTop(NULL, NULL); |
| 1889 } | 1907 } |
| 1890 | 1908 |
| 1891 | 1909 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2119 HeapObjectIterator obj_it(this); | 2137 HeapObjectIterator obj_it(this); |
| 2120 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) | 2138 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) |
| 2121 CollectHistogramInfo(obj); | 2139 CollectHistogramInfo(obj); |
| 2122 ReportHistogram(true); | 2140 ReportHistogram(true); |
| 2123 } | 2141 } |
| 2124 #endif | 2142 #endif |
| 2125 | 2143 |
| 2126 // ----------------------------------------------------------------------------- | 2144 // ----------------------------------------------------------------------------- |
| 2127 // FixedSpace implementation | 2145 // FixedSpace implementation |
| 2128 | 2146 |
| 2129 void FixedSpace::PrepareForMarkCompact(bool will_compact) { | 2147 void FixedSpace::PrepareForMarkCompact() { |
| 2130 // Call prepare of the super class. | 2148 // Call prepare of the super class. |
| 2131 PagedSpace::PrepareForMarkCompact(will_compact); | 2149 PagedSpace::PrepareForMarkCompact(); |
| 2132 | |
| 2133 ASSERT(!will_compact); | |
| 2134 | 2150 |
| 2135 // During a non-compacting collection, everything below the linear | 2151 // During a non-compacting collection, everything below the linear |
| 2136 // allocation pointer except wasted top-of-page blocks is considered | 2152 // allocation pointer except wasted top-of-page blocks is considered |
| 2137 // allocated and we will rediscover available bytes during the | 2153 // allocated and we will rediscover available bytes during the |
| 2138 // collection. | 2154 // collection. |
| 2139 accounting_stats_.AllocateBytes(free_list_.available()); | 2155 accounting_stats_.AllocateBytes(free_list_.available()); |
| 2140 | 2156 |
| 2141 // Clear the free list before a full GC---it will be rebuilt afterward. | 2157 // Clear the free list before a full GC---it will be rebuilt afterward. |
| 2142 free_list_.Reset(); | 2158 free_list_.Reset(); |
| 2143 } | 2159 } |
| 2144 | 2160 |
| 2145 | 2161 |
| 2146 // ----------------------------------------------------------------------------- | 2162 // ----------------------------------------------------------------------------- |
| 2147 // MapSpace implementation | 2163 // MapSpace implementation |
| 2148 | 2164 |
| 2149 void MapSpace::PrepareForMarkCompact(bool will_compact) { | |
| 2150 // Call prepare of the super class. | |
| 2151 FixedSpace::PrepareForMarkCompact(will_compact); | |
| 2152 } | |
| 2153 | |
| 2154 | |
| 2155 #ifdef DEBUG | 2165 #ifdef DEBUG |
| 2156 void MapSpace::VerifyObject(HeapObject* object) { | 2166 void MapSpace::VerifyObject(HeapObject* object) { |
| 2157 // The object should be a map or a free-list node. | 2167 // The object should be a map or a free-list node. |
| 2158 ASSERT(object->IsMap() || object->IsFreeSpace()); | 2168 ASSERT(object->IsMap() || object->IsFreeSpace()); |
| 2159 } | 2169 } |
| 2160 #endif | 2170 #endif |
| 2161 | 2171 |
| 2162 | 2172 |
| 2163 // ----------------------------------------------------------------------------- | 2173 // ----------------------------------------------------------------------------- |
| 2164 // GlobalPropertyCellSpace implementation | 2174 // GlobalPropertyCellSpace implementation |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2330 | 2340 |
| 2331 | 2341 |
| 2332 void LargeObjectSpace::FreeUnmarkedObjects() { | 2342 void LargeObjectSpace::FreeUnmarkedObjects() { |
| 2333 LargePage* previous = NULL; | 2343 LargePage* previous = NULL; |
| 2334 LargePage* current = first_page_; | 2344 LargePage* current = first_page_; |
| 2335 while (current != NULL) { | 2345 while (current != NULL) { |
| 2336 HeapObject* object = current->GetObject(); | 2346 HeapObject* object = current->GetObject(); |
| 2337 MarkBit mark_bit = Marking::MarkBitFrom(object); | 2347 MarkBit mark_bit = Marking::MarkBitFrom(object); |
| 2338 if (mark_bit.Get()) { | 2348 if (mark_bit.Get()) { |
| 2339 mark_bit.Clear(); | 2349 mark_bit.Clear(); |
| 2340 heap()->mark_compact_collector()->tracer()->decrement_marked_count(); | |
| 2341 previous = current; | 2350 previous = current; |
| 2342 current = current->next_page(); | 2351 current = current->next_page(); |
| 2343 } else { | 2352 } else { |
| 2344 LargePage* page = current; | 2353 LargePage* page = current; |
| 2345 // Cut the chunk out from the chunk list. | 2354 // Cut the chunk out from the chunk list. |
| 2346 current = current->next_page(); | 2355 current = current->next_page(); |
| 2347 if (previous == NULL) { | 2356 if (previous == NULL) { |
| 2348 first_page_ = current; | 2357 first_page_ = current; |
| 2349 } else { | 2358 } else { |
| 2350 previous->set_next_page(current); | 2359 previous->set_next_page(current); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2456 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) { | 2465 for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) { |
| 2457 if (obj->IsCode()) { | 2466 if (obj->IsCode()) { |
| 2458 Code* code = Code::cast(obj); | 2467 Code* code = Code::cast(obj); |
| 2459 isolate->code_kind_statistics()[code->kind()] += code->Size(); | 2468 isolate->code_kind_statistics()[code->kind()] += code->Size(); |
| 2460 } | 2469 } |
| 2461 } | 2470 } |
| 2462 } | 2471 } |
| 2463 #endif // DEBUG | 2472 #endif // DEBUG |
| 2464 | 2473 |
| 2465 } } // namespace v8::internal | 2474 } } // namespace v8::internal |
| OLD | NEW |