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 1609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1620 // Update pointers from external string table. | 1620 // Update pointers from external string table. |
1621 Heap::UpdateNewSpaceReferencesInExternalStringTable( | 1621 Heap::UpdateNewSpaceReferencesInExternalStringTable( |
1622 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1622 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
1623 | 1623 |
1624 // All pointers were updated. Update auxiliary allocation info. | 1624 // All pointers were updated. Update auxiliary allocation info. |
1625 Heap::IncrementYoungSurvivorsCounter(survivors_size); | 1625 Heap::IncrementYoungSurvivorsCounter(survivors_size); |
1626 space->set_age_mark(space->top()); | 1626 space->set_age_mark(space->top()); |
1627 } | 1627 } |
1628 | 1628 |
1629 | 1629 |
1630 static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) { | 1630 static void SweepSpace(PagedSpace* space) { |
1631 PageIterator it(space, PageIterator::PAGES_IN_USE); | 1631 PageIterator it(space, PageIterator::PAGES_IN_USE); |
1632 | 1632 |
1633 // During sweeping of paged space we are trying to find longest sequences | 1633 // During sweeping of paged space we are trying to find longest sequences |
1634 // of pages without live objects and free them (instead of putting them on | 1634 // of pages without live objects and free them (instead of putting them on |
1635 // the free list). | 1635 // the free list). |
1636 | 1636 |
1637 // Page preceding current. | 1637 // Page preceding current. |
1638 Page* prev = Page::FromAddress(NULL); | 1638 Page* prev = Page::FromAddress(NULL); |
1639 | 1639 |
1640 // First empty page in a sequence. | 1640 // First empty page in a sequence. |
(...skipping 20 matching lines...) Expand all Loading... |
1661 | 1661 |
1662 for (Address current = p->ObjectAreaStart(); | 1662 for (Address current = p->ObjectAreaStart(); |
1663 current < p->AllocationTop(); | 1663 current < p->AllocationTop(); |
1664 current += object->Size()) { | 1664 current += object->Size()) { |
1665 object = HeapObject::FromAddress(current); | 1665 object = HeapObject::FromAddress(current); |
1666 if (object->IsMarked()) { | 1666 if (object->IsMarked()) { |
1667 object->ClearMark(); | 1667 object->ClearMark(); |
1668 MarkCompactCollector::tracer()->decrement_marked_count(); | 1668 MarkCompactCollector::tracer()->decrement_marked_count(); |
1669 | 1669 |
1670 if (!is_previous_alive) { // Transition from free to live. | 1670 if (!is_previous_alive) { // Transition from free to live. |
1671 dealloc(free_start, | 1671 space->DeallocateBlock(free_start, |
1672 static_cast<int>(current - free_start), | 1672 static_cast<int>(current - free_start), |
1673 true, | 1673 true); |
1674 false); | |
1675 is_previous_alive = true; | 1674 is_previous_alive = true; |
1676 } | 1675 } |
1677 } else { | 1676 } else { |
1678 MarkCompactCollector::ReportDeleteIfNeeded(object); | 1677 MarkCompactCollector::ReportDeleteIfNeeded(object); |
1679 if (is_previous_alive) { // Transition from live to free. | 1678 if (is_previous_alive) { // Transition from live to free. |
1680 free_start = current; | 1679 free_start = current; |
1681 is_previous_alive = false; | 1680 is_previous_alive = false; |
1682 } | 1681 } |
1683 } | 1682 } |
1684 // The object is now unmarked for the call to Size() at the top of the | 1683 // The object is now unmarked for the call to Size() at the top of the |
1685 // loop. | 1684 // loop. |
1686 } | 1685 } |
1687 | 1686 |
1688 bool page_is_empty = (p->ObjectAreaStart() == p->AllocationTop()) | 1687 bool page_is_empty = (p->ObjectAreaStart() == p->AllocationTop()) |
1689 || (!is_previous_alive && free_start == p->ObjectAreaStart()); | 1688 || (!is_previous_alive && free_start == p->ObjectAreaStart()); |
1690 | 1689 |
1691 if (page_is_empty) { | 1690 if (page_is_empty) { |
1692 // This page is empty. Check whether we are in the middle of | 1691 // This page is empty. Check whether we are in the middle of |
1693 // sequence of empty pages and start one if not. | 1692 // sequence of empty pages and start one if not. |
1694 if (!first_empty_page->is_valid()) { | 1693 if (!first_empty_page->is_valid()) { |
1695 first_empty_page = p; | 1694 first_empty_page = p; |
1696 prec_first_empty_page = prev; | 1695 prec_first_empty_page = prev; |
1697 } | 1696 } |
1698 | 1697 |
1699 if (!is_previous_alive) { | 1698 if (!is_previous_alive) { |
1700 // There are dead objects on this page. Update space accounting stats | 1699 // There are dead objects on this page. Update space accounting stats |
1701 // without putting anything into free list. | 1700 // without putting anything into free list. |
1702 int size_in_bytes = static_cast<int>(p->AllocationTop() - free_start); | 1701 int size_in_bytes = static_cast<int>(p->AllocationTop() - free_start); |
1703 if (size_in_bytes > 0) { | 1702 if (size_in_bytes > 0) { |
1704 dealloc(free_start, size_in_bytes, false, true); | 1703 space->DeallocateBlock(free_start, size_in_bytes, false); |
1705 } | 1704 } |
1706 } | 1705 } |
1707 } else { | 1706 } else { |
1708 // This page is not empty. Sequence of empty pages ended on the previous | 1707 // This page is not empty. Sequence of empty pages ended on the previous |
1709 // one. | 1708 // one. |
1710 if (first_empty_page->is_valid()) { | 1709 if (first_empty_page->is_valid()) { |
1711 space->FreePages(prec_first_empty_page, prev); | 1710 space->FreePages(prec_first_empty_page, prev); |
1712 prec_first_empty_page = first_empty_page = Page::FromAddress(NULL); | 1711 prec_first_empty_page = first_empty_page = Page::FromAddress(NULL); |
1713 } | 1712 } |
1714 | 1713 |
1715 // If there is a free ending area on one of the previous pages we have | 1714 // If there is a free ending area on one of the previous pages we have |
1716 // deallocate that area and put it on the free list. | 1715 // deallocate that area and put it on the free list. |
1717 if (last_free_size > 0) { | 1716 if (last_free_size > 0) { |
1718 Page::FromAddress(last_free_start)-> | 1717 Page::FromAddress(last_free_start)-> |
1719 SetAllocationWatermark(last_free_start); | 1718 SetAllocationWatermark(last_free_start); |
1720 dealloc(last_free_start, last_free_size, true, true); | 1719 space->DeallocateBlock(last_free_start, last_free_size, true); |
1721 last_free_start = NULL; | 1720 last_free_start = NULL; |
1722 last_free_size = 0; | 1721 last_free_size = 0; |
1723 } | 1722 } |
1724 | 1723 |
1725 // If the last region of this page was not live we remember it. | 1724 // If the last region of this page was not live we remember it. |
1726 if (!is_previous_alive) { | 1725 if (!is_previous_alive) { |
1727 ASSERT(last_free_size == 0); | 1726 ASSERT(last_free_size == 0); |
1728 last_free_size = static_cast<int>(p->AllocationTop() - free_start); | 1727 last_free_size = static_cast<int>(p->AllocationTop() - free_start); |
1729 last_free_start = free_start; | 1728 last_free_start = free_start; |
1730 } | 1729 } |
(...skipping 10 matching lines...) Expand all Loading... |
1741 // to the beginning of first empty page. | 1740 // to the beginning of first empty page. |
1742 ASSERT(prev == space->AllocationTopPage()); | 1741 ASSERT(prev == space->AllocationTopPage()); |
1743 | 1742 |
1744 new_allocation_top = first_empty_page->ObjectAreaStart(); | 1743 new_allocation_top = first_empty_page->ObjectAreaStart(); |
1745 } | 1744 } |
1746 | 1745 |
1747 if (last_free_size > 0) { | 1746 if (last_free_size > 0) { |
1748 // There was a free ending area on the previous page. | 1747 // There was a free ending area on the previous page. |
1749 // Deallocate it without putting it into freelist and move allocation | 1748 // Deallocate it without putting it into freelist and move allocation |
1750 // top to the beginning of this free area. | 1749 // top to the beginning of this free area. |
1751 dealloc(last_free_start, last_free_size, false, true); | 1750 space->DeallocateBlock(last_free_start, last_free_size, false); |
1752 new_allocation_top = last_free_start; | 1751 new_allocation_top = last_free_start; |
1753 } | 1752 } |
1754 | 1753 |
1755 if (new_allocation_top != NULL) { | 1754 if (new_allocation_top != NULL) { |
1756 #ifdef DEBUG | 1755 #ifdef DEBUG |
1757 Page* new_allocation_top_page = Page::FromAllocationTop(new_allocation_top); | 1756 Page* new_allocation_top_page = Page::FromAllocationTop(new_allocation_top); |
1758 if (!first_empty_page->is_valid()) { | 1757 if (!first_empty_page->is_valid()) { |
1759 ASSERT(new_allocation_top_page == space->AllocationTopPage()); | 1758 ASSERT(new_allocation_top_page == space->AllocationTopPage()); |
1760 } else if (last_free_size > 0) { | 1759 } else if (last_free_size > 0) { |
1761 ASSERT(new_allocation_top_page == prec_first_empty_page); | 1760 ASSERT(new_allocation_top_page == prec_first_empty_page); |
1762 } else { | 1761 } else { |
1763 ASSERT(new_allocation_top_page == first_empty_page); | 1762 ASSERT(new_allocation_top_page == first_empty_page); |
1764 } | 1763 } |
1765 #endif | 1764 #endif |
1766 | 1765 |
1767 space->SetTop(new_allocation_top); | 1766 space->SetTop(new_allocation_top); |
1768 } | 1767 } |
1769 } | 1768 } |
1770 | 1769 |
1771 | 1770 |
1772 void MarkCompactCollector::DeallocateOldPointerBlock(Address start, | |
1773 int size_in_bytes, | |
1774 bool add_to_freelist, | |
1775 bool last_on_page) { | |
1776 Heap::old_pointer_space()->Free(start, size_in_bytes, add_to_freelist); | |
1777 } | |
1778 | |
1779 | |
1780 void MarkCompactCollector::DeallocateOldDataBlock(Address start, | |
1781 int size_in_bytes, | |
1782 bool add_to_freelist, | |
1783 bool last_on_page) { | |
1784 Heap::old_data_space()->Free(start, size_in_bytes, add_to_freelist); | |
1785 } | |
1786 | |
1787 | |
1788 void MarkCompactCollector::DeallocateCodeBlock(Address start, | |
1789 int size_in_bytes, | |
1790 bool add_to_freelist, | |
1791 bool last_on_page) { | |
1792 Heap::code_space()->Free(start, size_in_bytes, add_to_freelist); | |
1793 } | |
1794 | |
1795 | |
1796 void MarkCompactCollector::DeallocateMapBlock(Address start, | |
1797 int size_in_bytes, | |
1798 bool add_to_freelist, | |
1799 bool last_on_page) { | |
1800 // Objects in map space are assumed to have size Map::kSize and a | |
1801 // valid map in their first word. Thus, we break the free block up into | |
1802 // chunks and free them separately. | |
1803 ASSERT(size_in_bytes % Map::kSize == 0); | |
1804 Address end = start + size_in_bytes; | |
1805 for (Address a = start; a < end; a += Map::kSize) { | |
1806 Heap::map_space()->Free(a, add_to_freelist); | |
1807 } | |
1808 } | |
1809 | |
1810 | |
1811 void MarkCompactCollector::DeallocateCellBlock(Address start, | |
1812 int size_in_bytes, | |
1813 bool add_to_freelist, | |
1814 bool last_on_page) { | |
1815 // Free-list elements in cell space are assumed to have a fixed size. | |
1816 // We break the free block into chunks and add them to the free list | |
1817 // individually. | |
1818 int size = Heap::cell_space()->object_size_in_bytes(); | |
1819 ASSERT(size_in_bytes % size == 0); | |
1820 Address end = start + size_in_bytes; | |
1821 for (Address a = start; a < end; a += size) { | |
1822 Heap::cell_space()->Free(a, add_to_freelist); | |
1823 } | |
1824 } | |
1825 | |
1826 | |
1827 void MarkCompactCollector::EncodeForwardingAddresses() { | 1771 void MarkCompactCollector::EncodeForwardingAddresses() { |
1828 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); | 1772 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); |
1829 // Objects in the active semispace of the young generation may be | 1773 // Objects in the active semispace of the young generation may be |
1830 // relocated to the inactive semispace (if not promoted). Set the | 1774 // relocated to the inactive semispace (if not promoted). Set the |
1831 // relocation info to the beginning of the inactive semispace. | 1775 // relocation info to the beginning of the inactive semispace. |
1832 Heap::new_space()->MCResetRelocationInfo(); | 1776 Heap::new_space()->MCResetRelocationInfo(); |
1833 | 1777 |
1834 // Compute the forwarding pointers in each space. | 1778 // Compute the forwarding pointers in each space. |
1835 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace, | 1779 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace, |
1836 ReportDeleteIfNeeded>( | 1780 ReportDeleteIfNeeded>( |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2081 void MarkCompactCollector::SweepSpaces() { | 2025 void MarkCompactCollector::SweepSpaces() { |
2082 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); | 2026 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); |
2083 | 2027 |
2084 ASSERT(state_ == SWEEP_SPACES); | 2028 ASSERT(state_ == SWEEP_SPACES); |
2085 ASSERT(!IsCompacting()); | 2029 ASSERT(!IsCompacting()); |
2086 // Noncompacting collections simply sweep the spaces to clear the mark | 2030 // Noncompacting collections simply sweep the spaces to clear the mark |
2087 // bits and free the nonlive blocks (for old and map spaces). We sweep | 2031 // bits and free the nonlive blocks (for old and map spaces). We sweep |
2088 // the map space last because freeing non-live maps overwrites them and | 2032 // the map space last because freeing non-live maps overwrites them and |
2089 // the other spaces rely on possibly non-live maps to get the sizes for | 2033 // the other spaces rely on possibly non-live maps to get the sizes for |
2090 // non-live objects. | 2034 // non-live objects. |
2091 SweepSpace(Heap::old_pointer_space(), &DeallocateOldPointerBlock); | 2035 SweepSpace(Heap::old_pointer_space()); |
2092 SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock); | 2036 SweepSpace(Heap::old_data_space()); |
2093 SweepSpace(Heap::code_space(), &DeallocateCodeBlock); | 2037 SweepSpace(Heap::code_space()); |
2094 SweepSpace(Heap::cell_space(), &DeallocateCellBlock); | 2038 SweepSpace(Heap::cell_space()); |
2095 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); | 2039 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); |
2096 SweepNewSpace(Heap::new_space()); | 2040 SweepNewSpace(Heap::new_space()); |
2097 } | 2041 } |
2098 SweepSpace(Heap::map_space(), &DeallocateMapBlock); | 2042 SweepSpace(Heap::map_space()); |
2099 | 2043 |
2100 Heap::IterateDirtyRegions(Heap::map_space(), | 2044 Heap::IterateDirtyRegions(Heap::map_space(), |
2101 &Heap::IteratePointersInDirtyMapsRegion, | 2045 &Heap::IteratePointersInDirtyMapsRegion, |
2102 &UpdatePointerToNewGen, | 2046 &UpdatePointerToNewGen, |
2103 Heap::WATERMARK_SHOULD_BE_VALID); | 2047 Heap::WATERMARK_SHOULD_BE_VALID); |
2104 | 2048 |
2105 int live_maps_size = Heap::map_space()->Size(); | 2049 int live_maps_size = Heap::map_space()->Size(); |
2106 int live_maps = live_maps_size / Map::kSize; | 2050 int live_maps = live_maps_size / Map::kSize; |
2107 ASSERT(live_map_objects_size_ == live_maps_size); | 2051 ASSERT(live_map_objects_size_ == live_maps_size); |
2108 | 2052 |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2664 } | 2608 } |
2665 | 2609 |
2666 | 2610 |
2667 void MarkCompactCollector::Initialize() { | 2611 void MarkCompactCollector::Initialize() { |
2668 StaticPointersToNewGenUpdatingVisitor::Initialize(); | 2612 StaticPointersToNewGenUpdatingVisitor::Initialize(); |
2669 StaticMarkingVisitor::Initialize(); | 2613 StaticMarkingVisitor::Initialize(); |
2670 } | 2614 } |
2671 | 2615 |
2672 | 2616 |
2673 } } // namespace v8::internal | 2617 } } // namespace v8::internal |
OLD | NEW |