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 729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 HeapPage* page = m_firstUnsweptPage; | 740 HeapPage* page = m_firstUnsweptPage; |
741 if (page->isEmpty()) { | 741 if (page->isEmpty()) { |
742 page->unlink(&m_firstUnsweptPage); | 742 page->unlink(&m_firstUnsweptPage); |
743 page->removeFromHeap(this); | 743 page->removeFromHeap(this); |
744 } else { | 744 } else { |
745 // Sweep a page and move the page from m_firstUnsweptPages to | 745 // Sweep a page and move the page from m_firstUnsweptPages to |
746 // m_firstPages. | 746 // m_firstPages. |
747 page->sweep(); | 747 page->sweep(); |
748 page->unlink(&m_firstUnsweptPage); | 748 page->unlink(&m_firstUnsweptPage); |
749 page->link(&m_firstPage); | 749 page->link(&m_firstPage); |
| 750 page->markAsSwept(); |
750 | 751 |
751 result = allocateFromFreeList(allocationSize, gcInfoIndex); | 752 result = allocateFromFreeList(allocationSize, gcInfoIndex); |
752 if (result) { | 753 if (result) |
753 break; | 754 break; |
754 } | |
755 } | 755 } |
756 } | 756 } |
757 | 757 |
758 if (threadState()->isMainThread()) | 758 if (threadState()->isMainThread()) |
759 ScriptForbiddenScope::exit(); | 759 ScriptForbiddenScope::exit(); |
760 return result; | 760 return result; |
761 } | 761 } |
762 | 762 |
763 bool ThreadHeap::lazySweepLargeObjects(size_t allocationSize) | 763 bool ThreadHeap::lazySweepLargeObjects(size_t allocationSize) |
764 { | 764 { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 if (sweptSize >= allocationSize) { | 797 if (sweptSize >= allocationSize) { |
798 result = true; | 798 result = true; |
799 break; | 799 break; |
800 } | 800 } |
801 } else { | 801 } else { |
802 // Sweep a large object and move the large object from | 802 // Sweep a large object and move the large object from |
803 // m_firstUnsweptLargeObjects to m_firstLargeObjects. | 803 // m_firstUnsweptLargeObjects to m_firstLargeObjects. |
804 largeObject->sweep(); | 804 largeObject->sweep(); |
805 largeObject->unlink(&m_firstUnsweptLargeObject); | 805 largeObject->unlink(&m_firstUnsweptLargeObject); |
806 largeObject->link(&m_firstLargeObject); | 806 largeObject->link(&m_firstLargeObject); |
| 807 largeObject->markAsSwept(); |
807 } | 808 } |
808 } | 809 } |
809 | 810 |
810 if (threadState()->isMainThread()) | 811 if (threadState()->isMainThread()) |
811 ScriptForbiddenScope::exit(); | 812 ScriptForbiddenScope::exit(); |
812 return result; | 813 return result; |
813 } | 814 } |
814 | 815 |
815 void ThreadHeap::completeSweep() | 816 void ThreadHeap::completeSweep() |
816 { | 817 { |
817 RELEASE_ASSERT(threadState()->isSweepingInProgress()); | 818 RELEASE_ASSERT(threadState()->isSweepingInProgress()); |
818 ASSERT(threadState()->sweepForbidden()); | 819 ASSERT(threadState()->sweepForbidden()); |
819 | 820 |
820 if (threadState()->isMainThread()) | 821 if (threadState()->isMainThread()) |
821 ScriptForbiddenScope::enter(); | 822 ScriptForbiddenScope::enter(); |
822 | 823 |
823 // Sweep normal pages. | 824 // Sweep normal pages. |
824 while (m_firstUnsweptPage) { | 825 while (m_firstUnsweptPage) { |
825 HeapPage* page = m_firstUnsweptPage; | 826 HeapPage* page = m_firstUnsweptPage; |
826 if (page->isEmpty()) { | 827 if (page->isEmpty()) { |
827 page->unlink(&m_firstUnsweptPage); | 828 page->unlink(&m_firstUnsweptPage); |
828 page->removeFromHeap(this); | 829 page->removeFromHeap(this); |
829 } else { | 830 } else { |
830 // Sweep a page and move the page from m_firstUnsweptPages to | 831 // Sweep a page and move the page from m_firstUnsweptPages to |
831 // m_firstPages. | 832 // m_firstPages. |
832 page->sweep(); | 833 page->sweep(); |
833 page->unlink(&m_firstUnsweptPage); | 834 page->unlink(&m_firstUnsweptPage); |
834 page->link(&m_firstPage); | 835 page->link(&m_firstPage); |
| 836 page->markAsSwept(); |
835 } | 837 } |
836 } | 838 } |
837 | 839 |
838 // Sweep large objects. | 840 // Sweep large objects. |
839 while (m_firstUnsweptLargeObject) { | 841 while (m_firstUnsweptLargeObject) { |
840 LargeObject* largeObject = m_firstUnsweptLargeObject; | 842 LargeObject* largeObject = m_firstUnsweptLargeObject; |
841 if (largeObject->isEmpty()) { | 843 if (largeObject->isEmpty()) { |
842 largeObject->unlink(&m_firstUnsweptLargeObject); | 844 largeObject->unlink(&m_firstUnsweptLargeObject); |
843 largeObject->removeFromHeap(this); | 845 largeObject->removeFromHeap(this); |
844 } else { | 846 } else { |
845 // Sweep a large object and move the large object from | 847 // Sweep a large object and move the large object from |
846 // m_firstUnsweptLargeObjects to m_firstLargeObjects. | 848 // m_firstUnsweptLargeObjects to m_firstLargeObjects. |
847 largeObject->sweep(); | 849 largeObject->sweep(); |
848 largeObject->unlink(&m_firstUnsweptLargeObject); | 850 largeObject->unlink(&m_firstUnsweptLargeObject); |
849 largeObject->link(&m_firstLargeObject); | 851 largeObject->link(&m_firstLargeObject); |
| 852 largeObject->markAsSwept(); |
850 } | 853 } |
851 } | 854 } |
852 | 855 |
853 if (threadState()->isMainThread()) | 856 if (threadState()->isMainThread()) |
854 ScriptForbiddenScope::exit(); | 857 ScriptForbiddenScope::exit(); |
855 } | 858 } |
856 | 859 |
857 #if ENABLE(ASSERT) | 860 #if ENABLE(ASSERT) |
858 static bool isLargeObjectAligned(LargeObject* largeObject, Address address) | 861 static bool isLargeObjectAligned(LargeObject* largeObject, Address address) |
859 { | 862 { |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1227 // We got some memory, but failed to commit it, try again. | 1230 // We got some memory, but failed to commit it, try again. |
1228 delete memory; | 1231 delete memory; |
1229 } | 1232 } |
1230 return nullptr; | 1233 return nullptr; |
1231 } | 1234 } |
1232 | 1235 |
1233 BaseHeapPage::BaseHeapPage(PageMemory* storage, ThreadHeap* heap) | 1236 BaseHeapPage::BaseHeapPage(PageMemory* storage, ThreadHeap* heap) |
1234 : m_storage(storage) | 1237 : m_storage(storage) |
1235 , m_heap(heap) | 1238 , m_heap(heap) |
1236 , m_terminating(false) | 1239 , m_terminating(false) |
| 1240 , m_swept(true) |
1237 { | 1241 { |
1238 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); | 1242 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); |
1239 } | 1243 } |
1240 | 1244 |
1241 void BaseHeapPage::markOrphaned() | 1245 void BaseHeapPage::markOrphaned() |
1242 { | 1246 { |
1243 m_heap = nullptr; | 1247 m_heap = nullptr; |
1244 m_terminating = false; | 1248 m_terminating = false; |
1245 // Since we zap the page payload for orphaned pages we need to mark it as | 1249 // Since we zap the page payload for orphaned pages we need to mark it as |
1246 // unused so a conservative pointer won't interpret the object headers. | 1250 // unused so a conservative pointer won't interpret the object headers. |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1436 if (hasCurrentAllocationArea()) { | 1440 if (hasCurrentAllocationArea()) { |
1437 if (pagesToBeSweptContains(currentAllocationPoint())) | 1441 if (pagesToBeSweptContains(currentAllocationPoint())) |
1438 return false; | 1442 return false; |
1439 } | 1443 } |
1440 return true; | 1444 return true; |
1441 } | 1445 } |
1442 #endif | 1446 #endif |
1443 | 1447 |
1444 void ThreadHeap::makeConsistentForSweeping() | 1448 void ThreadHeap::makeConsistentForSweeping() |
1445 { | 1449 { |
1446 markUnmarkedObjectsDead(); | 1450 preparePagesForSweeping(); |
1447 setAllocationPoint(nullptr, 0); | 1451 setAllocationPoint(nullptr, 0); |
1448 clearFreeLists(); | 1452 clearFreeLists(); |
1449 } | 1453 } |
1450 | 1454 |
1451 void ThreadHeap::markUnmarkedObjectsDead() | 1455 void ThreadHeap::preparePagesForSweeping() |
1452 { | 1456 { |
1453 ASSERT(isConsistentForSweeping()); | 1457 ASSERT(isConsistentForSweeping()); |
| 1458 for (HeapPage* page = m_firstPage; page; page = page->next()) |
| 1459 page->markAsUnswept(); |
| 1460 |
1454 // If a new GC is requested before this thread got around to sweep, | 1461 // If a new GC is requested before this thread got around to sweep, |
1455 // ie. due to the thread doing a long running operation, we clear | 1462 // ie. due to the thread doing a long running operation, we clear |
1456 // the mark bits and mark any of the dead objects as dead. The latter | 1463 // the mark bits and mark any of the dead objects as dead. The latter |
1457 // is used to ensure the next GC marking does not trace already dead | 1464 // is used to ensure the next GC marking does not trace already dead |
1458 // objects. If we trace a dead object we could end up tracing into | 1465 // objects. If we trace a dead object we could end up tracing into |
1459 // garbage or the middle of another object via the newly conservatively | 1466 // garbage or the middle of another object via the newly conservatively |
1460 // found object. | 1467 // found object. |
1461 HeapPage* previousPage = nullptr; | 1468 HeapPage* previousPage = nullptr; |
1462 for (HeapPage* page = m_firstUnsweptPage; page; previousPage = page, page =
page->next()) { | 1469 for (HeapPage* page = m_firstUnsweptPage; page; previousPage = page, page =
page->next()) { |
1463 page->markUnmarkedObjectsDead(); | 1470 page->markUnmarkedObjectsDead(); |
| 1471 ASSERT(!page->hasBeenSwept()); |
1464 } | 1472 } |
1465 if (previousPage) { | 1473 if (previousPage) { |
1466 ASSERT(m_firstUnsweptPage); | 1474 ASSERT(m_firstUnsweptPage); |
1467 previousPage->m_next = m_firstPage; | 1475 previousPage->m_next = m_firstPage; |
1468 m_firstPage = m_firstUnsweptPage; | 1476 m_firstPage = m_firstUnsweptPage; |
1469 m_firstUnsweptPage = nullptr; | 1477 m_firstUnsweptPage = nullptr; |
1470 } | 1478 } |
1471 ASSERT(!m_firstUnsweptPage); | 1479 ASSERT(!m_firstUnsweptPage); |
1472 | 1480 |
| 1481 for (LargeObject* largeObject = m_firstLargeObject; largeObject; largeObject
= largeObject->next()) |
| 1482 largeObject->markAsUnswept(); |
| 1483 |
1473 LargeObject* previousLargeObject = nullptr; | 1484 LargeObject* previousLargeObject = nullptr; |
1474 for (LargeObject* largeObject = m_firstUnsweptLargeObject; largeObject; prev
iousLargeObject = largeObject, largeObject = largeObject->next()) { | 1485 for (LargeObject* largeObject = m_firstUnsweptLargeObject; largeObject; prev
iousLargeObject = largeObject, largeObject = largeObject->next()) { |
1475 largeObject->markUnmarkedObjectsDead(); | 1486 largeObject->markUnmarkedObjectsDead(); |
| 1487 ASSERT(!largeObject->hasBeenSwept()); |
1476 } | 1488 } |
1477 if (previousLargeObject) { | 1489 if (previousLargeObject) { |
1478 ASSERT(m_firstUnsweptLargeObject); | 1490 ASSERT(m_firstUnsweptLargeObject); |
1479 previousLargeObject->m_next = m_firstLargeObject; | 1491 previousLargeObject->m_next = m_firstLargeObject; |
1480 m_firstLargeObject = m_firstUnsweptLargeObject; | 1492 m_firstLargeObject = m_firstUnsweptLargeObject; |
1481 m_firstUnsweptLargeObject = nullptr; | 1493 m_firstUnsweptLargeObject = nullptr; |
1482 } | 1494 } |
1483 ASSERT(!m_firstUnsweptLargeObject); | 1495 ASSERT(!m_firstUnsweptLargeObject); |
1484 } | 1496 } |
1485 | 1497 |
(...skipping 25 matching lines...) Expand all Loading... |
1511 , m_next(nullptr) | 1523 , m_next(nullptr) |
1512 { | 1524 { |
1513 m_objectStartBitMapComputed = false; | 1525 m_objectStartBitMapComputed = false; |
1514 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); | 1526 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); |
1515 } | 1527 } |
1516 | 1528 |
1517 size_t HeapPage::objectPayloadSizeForTesting() | 1529 size_t HeapPage::objectPayloadSizeForTesting() |
1518 { | 1530 { |
1519 size_t objectPayloadSize = 0; | 1531 size_t objectPayloadSize = 0; |
1520 Address headerAddress = payload(); | 1532 Address headerAddress = payload(); |
| 1533 markAsSwept(); |
1521 ASSERT(headerAddress != payloadEnd()); | 1534 ASSERT(headerAddress != payloadEnd()); |
1522 do { | 1535 do { |
1523 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAdd
ress); | 1536 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAdd
ress); |
1524 if (!header->isFree()) { | 1537 if (!header->isFree()) { |
1525 header->checkHeader(); | 1538 header->checkHeader(); |
1526 objectPayloadSize += header->payloadSize(); | 1539 objectPayloadSize += header->payloadSize(); |
1527 } | 1540 } |
1528 ASSERT(header->size() < blinkPagePayloadSize()); | 1541 ASSERT(header->size() < blinkPagePayloadSize()); |
1529 headerAddress += header->size(); | 1542 headerAddress += header->size(); |
1530 ASSERT(headerAddress <= payloadEnd()); | 1543 ASSERT(headerAddress <= payloadEnd()); |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1745 // Count objects that are dead before the final generation. | 1758 // Count objects that are dead before the final generation. |
1746 if (age < maxHeapObjectAge) | 1759 if (age < maxHeapObjectAge) |
1747 info->generations[tag][age] += 1; | 1760 info->generations[tag][age] += 1; |
1748 } | 1761 } |
1749 } | 1762 } |
1750 } | 1763 } |
1751 #endif | 1764 #endif |
1752 | 1765 |
1753 size_t LargeObject::objectPayloadSizeForTesting() | 1766 size_t LargeObject::objectPayloadSizeForTesting() |
1754 { | 1767 { |
| 1768 markAsSwept(); |
1755 return payloadSize(); | 1769 return payloadSize(); |
1756 } | 1770 } |
1757 | 1771 |
1758 #if ENABLE(GC_PROFILE_HEAP) | 1772 #if ENABLE(GC_PROFILE_HEAP) |
1759 void LargeObject::snapshot(TracedValue* json, ThreadState::SnapshotInfo* info) | 1773 void LargeObject::snapshot(TracedValue* json, ThreadState::SnapshotInfo* info) |
1760 { | 1774 { |
1761 HeapObjectHeader* header = heapObjectHeader(); | 1775 HeapObjectHeader* header = heapObjectHeader(); |
1762 size_t tag = info->getClassTag(Heap::gcInfo(header->gcInfoIndex())); | 1776 size_t tag = info->getClassTag(Heap::gcInfo(header->gcInfoIndex())); |
1763 size_t age = header->age(); | 1777 size_t age = header->age(); |
1764 if (header->isMarked()) { | 1778 if (header->isMarked()) { |
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2694 bool Heap::s_shutdownCalled = false; | 2708 bool Heap::s_shutdownCalled = false; |
2695 bool Heap::s_lastGCWasConservative = false; | 2709 bool Heap::s_lastGCWasConservative = false; |
2696 FreePagePool* Heap::s_freePagePool; | 2710 FreePagePool* Heap::s_freePagePool; |
2697 OrphanedPagePool* Heap::s_orphanedPagePool; | 2711 OrphanedPagePool* Heap::s_orphanedPagePool; |
2698 Heap::RegionTree* Heap::s_regionTree = nullptr; | 2712 Heap::RegionTree* Heap::s_regionTree = nullptr; |
2699 size_t Heap::s_allocatedObjectSize = 0; | 2713 size_t Heap::s_allocatedObjectSize = 0; |
2700 size_t Heap::s_allocatedSpace = 0; | 2714 size_t Heap::s_allocatedSpace = 0; |
2701 size_t Heap::s_markedObjectSize = 0; | 2715 size_t Heap::s_markedObjectSize = 0; |
2702 | 2716 |
2703 } // namespace blink | 2717 } // namespace blink |
OLD | NEW |