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