| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 #endif | 172 #endif |
| 173 | 173 |
| 174 void BaseArena::makeConsistentForGC() { | 174 void BaseArena::makeConsistentForGC() { |
| 175 clearFreeLists(); | 175 clearFreeLists(); |
| 176 ASSERT(isConsistentForGC()); | 176 ASSERT(isConsistentForGC()); |
| 177 for (BasePage* page = m_firstPage; page; page = page->next()) { | 177 for (BasePage* page = m_firstPage; page; page = page->next()) { |
| 178 page->markAsUnswept(); | 178 page->markAsUnswept(); |
| 179 page->invalidateObjectStartBitmap(); | 179 page->invalidateObjectStartBitmap(); |
| 180 } | 180 } |
| 181 | 181 |
| 182 // If a new GC is requested before this thread got around to sweep, | 182 // We should not start a new GC until we finish sweeping in the current GC. |
| 183 // ie. due to the thread doing a long running operation, we clear | 183 CHECK(!m_firstUnsweptPage); |
| 184 // the mark bits and mark any of the dead objects as dead. The latter | |
| 185 // is used to ensure the next GC marking does not trace already dead | |
| 186 // objects. If we trace a dead object we could end up tracing into | |
| 187 // garbage or the middle of another object via the newly conservatively | |
| 188 // found object. | |
| 189 BasePage* previousPage = nullptr; | |
| 190 for (BasePage *page = m_firstUnsweptPage; page; | |
| 191 previousPage = page, page = page->next()) { | |
| 192 page->makeConsistentForGC(); | |
| 193 ASSERT(!page->hasBeenSwept()); | |
| 194 page->invalidateObjectStartBitmap(); | |
| 195 } | |
| 196 if (previousPage) { | |
| 197 ASSERT(m_firstUnsweptPage); | |
| 198 previousPage->m_next = m_firstPage; | |
| 199 m_firstPage = m_firstUnsweptPage; | |
| 200 m_firstUnsweptPage = nullptr; | |
| 201 } | |
| 202 ASSERT(!m_firstUnsweptPage); | |
| 203 | 184 |
| 204 HeapCompact* heapCompactor = getThreadState()->heap().compaction(); | 185 HeapCompact* heapCompactor = getThreadState()->heap().compaction(); |
| 205 if (!heapCompactor->isCompactingArena(arenaIndex())) | 186 if (!heapCompactor->isCompactingArena(arenaIndex())) |
| 206 return; | 187 return; |
| 207 | 188 |
| 208 BasePage* nextPage = m_firstPage; | 189 BasePage* nextPage = m_firstPage; |
| 209 while (nextPage) { | 190 while (nextPage) { |
| 210 if (!nextPage->isLargeObjectPage()) | 191 if (!nextPage->isLargeObjectPage()) |
| 211 heapCompactor->addCompactingPage(nextPage); | 192 heapCompactor->addCompactingPage(nextPage); |
| 212 nextPage = nextPage->next(); | 193 nextPage = nextPage->next(); |
| (...skipping 1305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1518 // Zap the unused portion, until it is either compacted into or freed. | 1499 // Zap the unused portion, until it is either compacted into or freed. |
| 1519 if (currentPage != this) { | 1500 if (currentPage != this) { |
| 1520 FreeList::zapFreedMemory(payload(), payloadSize()); | 1501 FreeList::zapFreedMemory(payload(), payloadSize()); |
| 1521 } else { | 1502 } else { |
| 1522 FreeList::zapFreedMemory(payload() + allocationPoint, | 1503 FreeList::zapFreedMemory(payload() + allocationPoint, |
| 1523 payloadSize() - allocationPoint); | 1504 payloadSize() - allocationPoint); |
| 1524 } | 1505 } |
| 1525 #endif | 1506 #endif |
| 1526 } | 1507 } |
| 1527 | 1508 |
| 1528 void NormalPage::makeConsistentForGC() { | |
| 1529 size_t markedObjectSize = 0; | |
| 1530 for (Address headerAddress = payload(); headerAddress < payloadEnd();) { | |
| 1531 HeapObjectHeader* header = | |
| 1532 reinterpret_cast<HeapObjectHeader*>(headerAddress); | |
| 1533 ASSERT(header->size() < blinkPagePayloadSize()); | |
| 1534 // Check if a free list entry first since we cannot call | |
| 1535 // isMarked on a free list entry. | |
| 1536 if (header->isFree()) { | |
| 1537 headerAddress += header->size(); | |
| 1538 continue; | |
| 1539 } | |
| 1540 if (header->isMarked()) { | |
| 1541 header->unmark(); | |
| 1542 markedObjectSize += header->size(); | |
| 1543 } else { | |
| 1544 header->markDead(); | |
| 1545 } | |
| 1546 headerAddress += header->size(); | |
| 1547 } | |
| 1548 if (markedObjectSize) | |
| 1549 arenaForNormalPage()->getThreadState()->increaseMarkedObjectSize( | |
| 1550 markedObjectSize); | |
| 1551 } | |
| 1552 | |
| 1553 void NormalPage::makeConsistentForMutator() { | 1509 void NormalPage::makeConsistentForMutator() { |
| 1554 Address startOfGap = payload(); | 1510 Address startOfGap = payload(); |
| 1555 NormalPageArena* normalArena = arenaForNormalPage(); | 1511 NormalPageArena* normalArena = arenaForNormalPage(); |
| 1556 for (Address headerAddress = payload(); headerAddress < payloadEnd();) { | 1512 for (Address headerAddress = payload(); headerAddress < payloadEnd();) { |
| 1557 HeapObjectHeader* header = | 1513 HeapObjectHeader* header = |
| 1558 reinterpret_cast<HeapObjectHeader*>(headerAddress); | 1514 reinterpret_cast<HeapObjectHeader*>(headerAddress); |
| 1559 size_t size = header->size(); | 1515 size_t size = header->size(); |
| 1560 ASSERT(size < blinkPagePayloadSize()); | 1516 ASSERT(size < blinkPagePayloadSize()); |
| 1561 if (header->isPromptlyFreed()) | 1517 if (header->isPromptlyFreed()) |
| 1562 arenaForNormalPage()->decreasePromptlyFreedSize(size); | 1518 arenaForNormalPage()->decreasePromptlyFreedSize(size); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1696 } else { | 1652 } else { |
| 1697 visitor->markHeader(header, gcInfo->m_trace); | 1653 visitor->markHeader(header, gcInfo->m_trace); |
| 1698 } | 1654 } |
| 1699 } | 1655 } |
| 1700 | 1656 |
| 1701 void NormalPage::checkAndMarkPointer(Visitor* visitor, Address address) { | 1657 void NormalPage::checkAndMarkPointer(Visitor* visitor, Address address) { |
| 1702 #if DCHECK_IS_ON() | 1658 #if DCHECK_IS_ON() |
| 1703 DCHECK(contains(address)); | 1659 DCHECK(contains(address)); |
| 1704 #endif | 1660 #endif |
| 1705 HeapObjectHeader* header = findHeaderFromAddress(address); | 1661 HeapObjectHeader* header = findHeaderFromAddress(address); |
| 1706 if (!header || header->isDead()) | 1662 if (!header) |
| 1707 return; | 1663 return; |
| 1708 markPointer(visitor, header); | 1664 markPointer(visitor, header); |
| 1709 } | 1665 } |
| 1710 | 1666 |
| 1711 #if DCHECK_IS_ON() | 1667 #if DCHECK_IS_ON() |
| 1712 void NormalPage::checkAndMarkPointer(Visitor* visitor, | 1668 void NormalPage::checkAndMarkPointer(Visitor* visitor, |
| 1713 Address address, | 1669 Address address, |
| 1714 MarkedPointerCallbackForTesting callback) { | 1670 MarkedPointerCallbackForTesting callback) { |
| 1715 DCHECK(contains(address)); | 1671 DCHECK(contains(address)); |
| 1716 HeapObjectHeader* header = findHeaderFromAddress(address); | 1672 HeapObjectHeader* header = findHeaderFromAddress(address); |
| 1717 if (!header || header->isDead()) | 1673 if (!header) |
| 1718 return; | 1674 return; |
| 1719 if (!callback(header)) | 1675 if (!callback(header)) |
| 1720 markPointer(visitor, header); | 1676 markPointer(visitor, header); |
| 1721 } | 1677 } |
| 1722 #endif | 1678 #endif |
| 1723 | 1679 |
| 1724 void NormalPage::markOrphaned() { | 1680 void NormalPage::markOrphaned() { |
| 1725 // Zap the payload with a recognizable value to detect any incorrect | 1681 // Zap the payload with a recognizable value to detect any incorrect |
| 1726 // cross thread pointer usage. | 1682 // cross thread pointer usage. |
| 1727 #if defined(ADDRESS_SANITIZER) | 1683 #if defined(ADDRESS_SANITIZER) |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1809 | 1765 |
| 1810 void LargeObjectPage::removeFromHeap() { | 1766 void LargeObjectPage::removeFromHeap() { |
| 1811 static_cast<LargeObjectArena*>(arena())->freeLargeObjectPage(this); | 1767 static_cast<LargeObjectArena*>(arena())->freeLargeObjectPage(this); |
| 1812 } | 1768 } |
| 1813 | 1769 |
| 1814 void LargeObjectPage::sweep() { | 1770 void LargeObjectPage::sweep() { |
| 1815 heapObjectHeader()->unmark(); | 1771 heapObjectHeader()->unmark(); |
| 1816 arena()->getThreadState()->increaseMarkedObjectSize(size()); | 1772 arena()->getThreadState()->increaseMarkedObjectSize(size()); |
| 1817 } | 1773 } |
| 1818 | 1774 |
| 1819 void LargeObjectPage::makeConsistentForGC() { | |
| 1820 HeapObjectHeader* header = heapObjectHeader(); | |
| 1821 if (header->isMarked()) { | |
| 1822 header->unmark(); | |
| 1823 arena()->getThreadState()->increaseMarkedObjectSize(size()); | |
| 1824 } else { | |
| 1825 header->markDead(); | |
| 1826 } | |
| 1827 } | |
| 1828 | |
| 1829 void LargeObjectPage::makeConsistentForMutator() { | 1775 void LargeObjectPage::makeConsistentForMutator() { |
| 1830 HeapObjectHeader* header = heapObjectHeader(); | 1776 HeapObjectHeader* header = heapObjectHeader(); |
| 1831 if (header->isMarked()) | 1777 if (header->isMarked()) |
| 1832 header->unmark(); | 1778 header->unmark(); |
| 1833 } | 1779 } |
| 1834 | 1780 |
| 1835 #if defined(ADDRESS_SANITIZER) | 1781 #if defined(ADDRESS_SANITIZER) |
| 1836 void LargeObjectPage::poisonUnmarkedObjects() { | 1782 void LargeObjectPage::poisonUnmarkedObjects() { |
| 1837 HeapObjectHeader* header = heapObjectHeader(); | 1783 HeapObjectHeader* header = heapObjectHeader(); |
| 1838 if (!header->isMarked()) | 1784 if (!header->isMarked()) |
| 1839 ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); | 1785 ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
| 1840 } | 1786 } |
| 1841 #endif | 1787 #endif |
| 1842 | 1788 |
| 1843 void LargeObjectPage::checkAndMarkPointer(Visitor* visitor, Address address) { | 1789 void LargeObjectPage::checkAndMarkPointer(Visitor* visitor, Address address) { |
| 1844 #if DCHECK_IS_ON() | 1790 #if DCHECK_IS_ON() |
| 1845 DCHECK(contains(address)); | 1791 DCHECK(contains(address)); |
| 1846 #endif | 1792 #endif |
| 1847 if (!containedInObjectPayload(address) || heapObjectHeader()->isDead()) | 1793 if (!containedInObjectPayload(address)) |
| 1848 return; | 1794 return; |
| 1849 markPointer(visitor, heapObjectHeader()); | 1795 markPointer(visitor, heapObjectHeader()); |
| 1850 } | 1796 } |
| 1851 | 1797 |
| 1852 #if DCHECK_IS_ON() | 1798 #if DCHECK_IS_ON() |
| 1853 void LargeObjectPage::checkAndMarkPointer( | 1799 void LargeObjectPage::checkAndMarkPointer( |
| 1854 Visitor* visitor, | 1800 Visitor* visitor, |
| 1855 Address address, | 1801 Address address, |
| 1856 MarkedPointerCallbackForTesting callback) { | 1802 MarkedPointerCallbackForTesting callback) { |
| 1857 DCHECK(contains(address)); | 1803 DCHECK(contains(address)); |
| 1858 if (!containedInObjectPayload(address) || heapObjectHeader()->isDead()) | 1804 if (!containedInObjectPayload(address)) |
| 1859 return; | 1805 return; |
| 1860 if (!callback(heapObjectHeader())) | 1806 if (!callback(heapObjectHeader())) |
| 1861 markPointer(visitor, heapObjectHeader()); | 1807 markPointer(visitor, heapObjectHeader()); |
| 1862 } | 1808 } |
| 1863 #endif | 1809 #endif |
| 1864 | 1810 |
| 1865 void LargeObjectPage::markOrphaned() { | 1811 void LargeObjectPage::markOrphaned() { |
| 1866 // Zap the payload with a recognizable value to detect any incorrect | 1812 // Zap the payload with a recognizable value to detect any incorrect |
| 1867 // cross thread pointer usage. | 1813 // cross thread pointer usage. |
| 1868 OrphanedPagePool::asanDisabledMemset( | 1814 OrphanedPagePool::asanDisabledMemset( |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1940 | 1886 |
| 1941 m_hasEntries = true; | 1887 m_hasEntries = true; |
| 1942 size_t index = hash(address); | 1888 size_t index = hash(address); |
| 1943 ASSERT(!(index & 1)); | 1889 ASSERT(!(index & 1)); |
| 1944 Address cachePage = roundToBlinkPageStart(address); | 1890 Address cachePage = roundToBlinkPageStart(address); |
| 1945 m_entries[index + 1] = m_entries[index]; | 1891 m_entries[index + 1] = m_entries[index]; |
| 1946 m_entries[index] = cachePage; | 1892 m_entries[index] = cachePage; |
| 1947 } | 1893 } |
| 1948 | 1894 |
| 1949 } // namespace blink | 1895 } // namespace blink |
| OLD | NEW |