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 525 matching lines...) Loading... | |
536 { | 536 { |
537 HeapObjectHeader* header = heapObjectHeader(); | 537 HeapObjectHeader* header = heapObjectHeader(); |
538 if (header->isMarked()) | 538 if (header->isMarked()) |
539 header->unmark(); | 539 header->unmark(); |
540 else | 540 else |
541 header->markDead(); | 541 header->markDead(); |
542 } | 542 } |
543 | 543 |
544 void LargeObject::removeFromHeap(ThreadHeap* heap) | 544 void LargeObject::removeFromHeap(ThreadHeap* heap) |
545 { | 545 { |
546 markAsUnswept(); | |
haraken
2015/01/16 17:29:49
Isn't it guaranteed that the page is already marke
sof
2015/01/16 19:30:17
Removed.
| |
546 heap->freeLargeObject(this); | 547 heap->freeLargeObject(this); |
547 } | 548 } |
548 | 549 |
549 ThreadHeap::ThreadHeap(ThreadState* state, int index) | 550 ThreadHeap::ThreadHeap(ThreadState* state, int index) |
550 : m_currentAllocationPoint(nullptr) | 551 : m_currentAllocationPoint(nullptr) |
551 , m_remainingAllocationSize(0) | 552 , m_remainingAllocationSize(0) |
552 , m_lastRemainingAllocationSize(0) | 553 , m_lastRemainingAllocationSize(0) |
553 , m_firstPage(nullptr) | 554 , m_firstPage(nullptr) |
554 , m_firstLargeObject(nullptr) | 555 , m_firstLargeObject(nullptr) |
555 , m_firstUnsweptPage(nullptr) | 556 , m_firstUnsweptPage(nullptr) |
(...skipping 184 matching lines...) Loading... | |
740 HeapPage* page = m_firstUnsweptPage; | 741 HeapPage* page = m_firstUnsweptPage; |
741 if (page->isEmpty()) { | 742 if (page->isEmpty()) { |
742 page->unlink(&m_firstUnsweptPage); | 743 page->unlink(&m_firstUnsweptPage); |
743 page->removeFromHeap(this); | 744 page->removeFromHeap(this); |
744 } else { | 745 } else { |
745 // Sweep a page and move the page from m_firstUnsweptPages to | 746 // Sweep a page and move the page from m_firstUnsweptPages to |
746 // m_firstPages. | 747 // m_firstPages. |
747 page->sweep(); | 748 page->sweep(); |
748 page->unlink(&m_firstUnsweptPage); | 749 page->unlink(&m_firstUnsweptPage); |
749 page->link(&m_firstPage); | 750 page->link(&m_firstPage); |
751 page->markAsSwept(); | |
750 | 752 |
751 result = allocateFromFreeList(allocationSize, gcInfoIndex); | 753 result = allocateFromFreeList(allocationSize, gcInfoIndex); |
752 if (result) { | 754 if (result) |
753 break; | 755 break; |
754 } | |
755 } | 756 } |
756 } | 757 } |
757 | 758 |
758 if (threadState()->isMainThread()) | 759 if (threadState()->isMainThread()) |
759 ScriptForbiddenScope::exit(); | 760 ScriptForbiddenScope::exit(); |
760 return result; | 761 return result; |
761 } | 762 } |
762 | 763 |
763 bool ThreadHeap::lazySweepLargeObjects(size_t allocationSize) | 764 bool ThreadHeap::lazySweepLargeObjects(size_t allocationSize) |
764 { | 765 { |
(...skipping 32 matching lines...) Loading... | |
797 if (sweptSize >= allocationSize) { | 798 if (sweptSize >= allocationSize) { |
798 result = true; | 799 result = true; |
799 break; | 800 break; |
800 } | 801 } |
801 } else { | 802 } else { |
802 // Sweep a large object and move the large object from | 803 // Sweep a large object and move the large object from |
803 // m_firstUnsweptLargeObjects to m_firstLargeObjects. | 804 // m_firstUnsweptLargeObjects to m_firstLargeObjects. |
804 largeObject->sweep(); | 805 largeObject->sweep(); |
805 largeObject->unlink(&m_firstUnsweptLargeObject); | 806 largeObject->unlink(&m_firstUnsweptLargeObject); |
806 largeObject->link(&m_firstLargeObject); | 807 largeObject->link(&m_firstLargeObject); |
808 largeObject->markAsSwept(); | |
807 } | 809 } |
808 } | 810 } |
809 | 811 |
810 if (threadState()->isMainThread()) | 812 if (threadState()->isMainThread()) |
811 ScriptForbiddenScope::exit(); | 813 ScriptForbiddenScope::exit(); |
812 return result; | 814 return result; |
813 } | 815 } |
814 | 816 |
815 void ThreadHeap::completeSweep() | 817 void ThreadHeap::completeSweep() |
816 { | 818 { |
817 RELEASE_ASSERT(threadState()->isSweepingInProgress()); | 819 RELEASE_ASSERT(threadState()->isSweepingInProgress()); |
818 ASSERT(threadState()->sweepForbidden()); | 820 ASSERT(threadState()->sweepForbidden()); |
819 | 821 |
820 if (threadState()->isMainThread()) | 822 if (threadState()->isMainThread()) |
821 ScriptForbiddenScope::enter(); | 823 ScriptForbiddenScope::enter(); |
822 | 824 |
823 // Sweep normal pages. | 825 // Sweep normal pages. |
824 while (m_firstUnsweptPage) { | 826 while (m_firstUnsweptPage) { |
825 HeapPage* page = m_firstUnsweptPage; | 827 HeapPage* page = m_firstUnsweptPage; |
826 if (page->isEmpty()) { | 828 if (page->isEmpty()) { |
827 page->unlink(&m_firstUnsweptPage); | 829 page->unlink(&m_firstUnsweptPage); |
828 page->removeFromHeap(this); | 830 page->removeFromHeap(this); |
829 } else { | 831 } else { |
830 // Sweep a page and move the page from m_firstUnsweptPages to | 832 // Sweep a page and move the page from m_firstUnsweptPages to |
831 // m_firstPages. | 833 // m_firstPages. |
832 page->sweep(); | 834 page->sweep(); |
833 page->unlink(&m_firstUnsweptPage); | 835 page->unlink(&m_firstUnsweptPage); |
834 page->link(&m_firstPage); | 836 page->link(&m_firstPage); |
837 page->markAsSwept(); | |
835 } | 838 } |
836 } | 839 } |
837 | 840 |
838 // Sweep large objects. | 841 // Sweep large objects. |
839 while (m_firstUnsweptLargeObject) { | 842 while (m_firstUnsweptLargeObject) { |
840 LargeObject* largeObject = m_firstUnsweptLargeObject; | 843 LargeObject* largeObject = m_firstUnsweptLargeObject; |
841 if (largeObject->isEmpty()) { | 844 if (largeObject->isEmpty()) { |
842 largeObject->unlink(&m_firstUnsweptLargeObject); | 845 largeObject->unlink(&m_firstUnsweptLargeObject); |
843 largeObject->removeFromHeap(this); | 846 largeObject->removeFromHeap(this); |
844 } else { | 847 } else { |
845 // Sweep a large object and move the large object from | 848 // Sweep a large object and move the large object from |
846 // m_firstUnsweptLargeObjects to m_firstLargeObjects. | 849 // m_firstUnsweptLargeObjects to m_firstLargeObjects. |
847 largeObject->sweep(); | 850 largeObject->sweep(); |
848 largeObject->unlink(&m_firstUnsweptLargeObject); | 851 largeObject->unlink(&m_firstUnsweptLargeObject); |
849 largeObject->link(&m_firstLargeObject); | 852 largeObject->link(&m_firstLargeObject); |
853 largeObject->markAsSwept(); | |
850 } | 854 } |
851 } | 855 } |
852 | 856 |
853 if (threadState()->isMainThread()) | 857 if (threadState()->isMainThread()) |
854 ScriptForbiddenScope::exit(); | 858 ScriptForbiddenScope::exit(); |
855 } | 859 } |
856 | 860 |
857 #if ENABLE(ASSERT) | 861 #if ENABLE(ASSERT) |
858 static bool isLargeObjectAligned(LargeObject* largeObject, Address address) | 862 static bool isLargeObjectAligned(LargeObject* largeObject, Address address) |
859 { | 863 { |
(...skipping 279 matching lines...) Loading... | |
1139 Address result = headerAddress + sizeof(*header); | 1143 Address result = headerAddress + sizeof(*header); |
1140 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); | 1144 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); |
1141 LargeObject* largeObject = new (largeObjectAddress) LargeObject(pageMemory, this, size); | 1145 LargeObject* largeObject = new (largeObjectAddress) LargeObject(pageMemory, this, size); |
1142 header->checkHeader(); | 1146 header->checkHeader(); |
1143 | 1147 |
1144 // Poison the object header and allocationGranularity bytes after the object | 1148 // Poison the object header and allocationGranularity bytes after the object |
1145 ASAN_POISON_MEMORY_REGION(header, sizeof(*header)); | 1149 ASAN_POISON_MEMORY_REGION(header, sizeof(*header)); |
1146 ASAN_POISON_MEMORY_REGION(largeObject->address() + largeObject->size(), allo cationGranularity); | 1150 ASAN_POISON_MEMORY_REGION(largeObject->address() + largeObject->size(), allo cationGranularity); |
1147 | 1151 |
1148 largeObject->link(&m_firstLargeObject); | 1152 largeObject->link(&m_firstLargeObject); |
1153 if (threadState()->isSweepingInProgress()) | |
1154 largeObject->markAsSwept(); | |
haraken
2015/01/16 17:29:49
It's a bit inconsistent that a page allocated duri
sof
2015/01/16 19:30:17
We can flip defaults that way.
| |
1149 | 1155 |
1150 Heap::increaseAllocatedSpace(largeObject->size()); | 1156 Heap::increaseAllocatedSpace(largeObject->size()); |
1151 Heap::increaseAllocatedObjectSize(largeObject->size()); | 1157 Heap::increaseAllocatedObjectSize(largeObject->size()); |
1152 return result; | 1158 return result; |
1153 } | 1159 } |
1154 | 1160 |
1155 void ThreadHeap::freeLargeObject(LargeObject* object) | 1161 void ThreadHeap::freeLargeObject(LargeObject* object) |
1156 { | 1162 { |
1157 object->heapObjectHeader()->finalize(object->payload(), object->payloadSize( )); | 1163 object->heapObjectHeader()->finalize(object->payload(), object->payloadSize( )); |
1158 Heap::decreaseAllocatedSpace(object->size()); | 1164 Heap::decreaseAllocatedSpace(object->size()); |
(...skipping 68 matching lines...) Loading... | |
1227 // We got some memory, but failed to commit it, try again. | 1233 // We got some memory, but failed to commit it, try again. |
1228 delete memory; | 1234 delete memory; |
1229 } | 1235 } |
1230 return nullptr; | 1236 return nullptr; |
1231 } | 1237 } |
1232 | 1238 |
1233 BaseHeapPage::BaseHeapPage(PageMemory* storage, ThreadHeap* heap) | 1239 BaseHeapPage::BaseHeapPage(PageMemory* storage, ThreadHeap* heap) |
1234 : m_storage(storage) | 1240 : m_storage(storage) |
1235 , m_heap(heap) | 1241 , m_heap(heap) |
1236 , m_terminating(false) | 1242 , m_terminating(false) |
1243 , m_swept(false) | |
haraken
2015/01/16 17:29:49
As commented above, m_swept(true) will make the co
sof
2015/01/16 19:30:17
Done.
| |
1237 { | 1244 { |
1238 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); | 1245 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); |
1239 } | 1246 } |
1240 | 1247 |
1241 void BaseHeapPage::markOrphaned() | 1248 void BaseHeapPage::markOrphaned() |
1242 { | 1249 { |
1243 m_heap = nullptr; | 1250 m_heap = nullptr; |
1244 m_terminating = false; | 1251 m_terminating = false; |
1245 // Since we zap the page payload for orphaned pages we need to mark it as | 1252 // 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. | 1253 // unused so a conservative pointer won't interpret the object headers. |
(...skipping 138 matching lines...) Loading... | |
1385 delete memory; | 1392 delete memory; |
1386 } else { | 1393 } else { |
1387 Heap::freePagePool()->addFreePage(m_index, memory); | 1394 Heap::freePagePool()->addFreePage(m_index, memory); |
1388 } | 1395 } |
1389 offset += blinkPageSize; | 1396 offset += blinkPageSize; |
1390 } | 1397 } |
1391 } | 1398 } |
1392 HeapPage* page = new (pageMemory->writableStart()) HeapPage(pageMemory, this ); | 1399 HeapPage* page = new (pageMemory->writableStart()) HeapPage(pageMemory, this ); |
1393 | 1400 |
1394 page->link(&m_firstPage); | 1401 page->link(&m_firstPage); |
1402 if (threadState()->isSweepingInProgress()) | |
1403 page->markAsSwept(); | |
haraken
2015/01/16 17:29:49
Ditto. I think we can remove this code.
sof
2015/01/16 19:30:17
Done.
| |
1395 | 1404 |
1396 Heap::increaseAllocatedSpace(blinkPageSize); | 1405 Heap::increaseAllocatedSpace(blinkPageSize); |
1397 addToFreeList(page->payload(), page->payloadSize()); | 1406 addToFreeList(page->payload(), page->payloadSize()); |
1398 } | 1407 } |
1399 | 1408 |
1400 #if ENABLE(ASSERT) | 1409 #if ENABLE(ASSERT) |
1401 bool ThreadHeap::pagesToBeSweptContains(Address address) | 1410 bool ThreadHeap::pagesToBeSweptContains(Address address) |
1402 { | 1411 { |
1403 for (HeapPage* page = m_firstUnsweptPage; page; page = page->next()) { | 1412 for (HeapPage* page = m_firstUnsweptPage; page; page = page->next()) { |
1404 if (page->contains(address)) | 1413 if (page->contains(address)) |
(...skipping 31 matching lines...) Loading... | |
1436 if (hasCurrentAllocationArea()) { | 1445 if (hasCurrentAllocationArea()) { |
1437 if (pagesToBeSweptContains(currentAllocationPoint())) | 1446 if (pagesToBeSweptContains(currentAllocationPoint())) |
1438 return false; | 1447 return false; |
1439 } | 1448 } |
1440 return true; | 1449 return true; |
1441 } | 1450 } |
1442 #endif | 1451 #endif |
1443 | 1452 |
1444 void ThreadHeap::makeConsistentForSweeping() | 1453 void ThreadHeap::makeConsistentForSweeping() |
1445 { | 1454 { |
1446 markUnmarkedObjectsDead(); | 1455 preparePagesForSweeping(); |
1447 setAllocationPoint(nullptr, 0); | 1456 setAllocationPoint(nullptr, 0); |
1448 clearFreeLists(); | 1457 clearFreeLists(); |
1449 } | 1458 } |
1450 | 1459 |
1451 void ThreadHeap::markUnmarkedObjectsDead() | 1460 void ThreadHeap::preparePagesForSweeping() |
1452 { | 1461 { |
1453 ASSERT(isConsistentForSweeping()); | 1462 ASSERT(isConsistentForSweeping()); |
1463 for (HeapPage* page = m_firstPage; page; page = page->next()) | |
haraken
2015/01/16 17:29:49
You can move this loop to after line 1484.
sof
2015/01/16 19:30:17
It's preferable to have this loop here & over thes
| |
1464 page->markAsUnswept(); | |
1465 | |
1454 // If a new GC is requested before this thread got around to sweep, | 1466 // 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 | 1467 // 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 | 1468 // 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 | 1469 // 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 | 1470 // 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 | 1471 // garbage or the middle of another object via the newly conservatively |
1460 // found object. | 1472 // found object. |
1461 HeapPage* previousPage = nullptr; | 1473 HeapPage* previousPage = nullptr; |
1462 for (HeapPage* page = m_firstUnsweptPage; page; previousPage = page, page = page->next()) { | 1474 for (HeapPage* page = m_firstUnsweptPage; page; previousPage = page, page = page->next()) { |
1463 page->markUnmarkedObjectsDead(); | 1475 page->markUnmarkedObjectsDead(); |
1476 page->markAsUnswept(); | |
haraken
2015/01/16 17:29:49
Then you won't need this.
| |
1464 } | 1477 } |
1465 if (previousPage) { | 1478 if (previousPage) { |
1466 ASSERT(m_firstUnsweptPage); | 1479 ASSERT(m_firstUnsweptPage); |
1467 previousPage->m_next = m_firstPage; | 1480 previousPage->m_next = m_firstPage; |
1468 m_firstPage = m_firstUnsweptPage; | 1481 m_firstPage = m_firstUnsweptPage; |
1469 m_firstUnsweptPage = nullptr; | 1482 m_firstUnsweptPage = nullptr; |
1470 } | 1483 } |
1471 ASSERT(!m_firstUnsweptPage); | 1484 ASSERT(!m_firstUnsweptPage); |
1472 | 1485 |
1486 for (LargeObject* largeObject = m_firstLargeObject; largeObject; largeObject = largeObject->next()) | |
haraken
2015/01/16 17:29:49
Ditto.
sof
2015/01/16 19:30:17
See above.
| |
1487 largeObject->markAsUnswept(); | |
1488 | |
1473 LargeObject* previousLargeObject = nullptr; | 1489 LargeObject* previousLargeObject = nullptr; |
1474 for (LargeObject* largeObject = m_firstUnsweptLargeObject; largeObject; prev iousLargeObject = largeObject, largeObject = largeObject->next()) { | 1490 for (LargeObject* largeObject = m_firstUnsweptLargeObject; largeObject; prev iousLargeObject = largeObject, largeObject = largeObject->next()) { |
1475 largeObject->markUnmarkedObjectsDead(); | 1491 largeObject->markUnmarkedObjectsDead(); |
1492 largeObject->markAsUnswept(); | |
1476 } | 1493 } |
1477 if (previousLargeObject) { | 1494 if (previousLargeObject) { |
1478 ASSERT(m_firstUnsweptLargeObject); | 1495 ASSERT(m_firstUnsweptLargeObject); |
1479 previousLargeObject->m_next = m_firstLargeObject; | 1496 previousLargeObject->m_next = m_firstLargeObject; |
1480 m_firstLargeObject = m_firstUnsweptLargeObject; | 1497 m_firstLargeObject = m_firstUnsweptLargeObject; |
1481 m_firstUnsweptLargeObject = nullptr; | 1498 m_firstUnsweptLargeObject = nullptr; |
1482 } | 1499 } |
1483 ASSERT(!m_firstUnsweptLargeObject); | 1500 ASSERT(!m_firstUnsweptLargeObject); |
1484 } | 1501 } |
1485 | 1502 |
(...skipping 125 matching lines...) Loading... | |
1611 if (header->isMarked()) | 1628 if (header->isMarked()) |
1612 header->unmark(); | 1629 header->unmark(); |
1613 else | 1630 else |
1614 header->markDead(); | 1631 header->markDead(); |
1615 headerAddress += header->size(); | 1632 headerAddress += header->size(); |
1616 } | 1633 } |
1617 } | 1634 } |
1618 | 1635 |
1619 void HeapPage::removeFromHeap(ThreadHeap* heap) | 1636 void HeapPage::removeFromHeap(ThreadHeap* heap) |
1620 { | 1637 { |
1638 markAsUnswept(); | |
haraken
2015/01/16 17:29:49
I think the page is already marked as unswept. ASS
sof
2015/01/16 19:30:17
Removed.
| |
1621 heap->freePage(this); | 1639 heap->freePage(this); |
1622 } | 1640 } |
1623 | 1641 |
1624 void HeapPage::populateObjectStartBitMap() | 1642 void HeapPage::populateObjectStartBitMap() |
1625 { | 1643 { |
1626 memset(&m_objectStartBitMap, 0, objectStartBitMapSize); | 1644 memset(&m_objectStartBitMap, 0, objectStartBitMapSize); |
1627 Address start = payload(); | 1645 Address start = payload(); |
1628 for (Address headerAddress = start; headerAddress < payloadEnd();) { | 1646 for (Address headerAddress = start; headerAddress < payloadEnd();) { |
1629 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAdd ress); | 1647 HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAdd ress); |
1630 size_t objectOffset = headerAddress - start; | 1648 size_t objectOffset = headerAddress - start; |
(...skipping 1063 matching lines...) Loading... | |
2694 bool Heap::s_shutdownCalled = false; | 2712 bool Heap::s_shutdownCalled = false; |
2695 bool Heap::s_lastGCWasConservative = false; | 2713 bool Heap::s_lastGCWasConservative = false; |
2696 FreePagePool* Heap::s_freePagePool; | 2714 FreePagePool* Heap::s_freePagePool; |
2697 OrphanedPagePool* Heap::s_orphanedPagePool; | 2715 OrphanedPagePool* Heap::s_orphanedPagePool; |
2698 Heap::RegionTree* Heap::s_regionTree = nullptr; | 2716 Heap::RegionTree* Heap::s_regionTree = nullptr; |
2699 size_t Heap::s_allocatedObjectSize = 0; | 2717 size_t Heap::s_allocatedObjectSize = 0; |
2700 size_t Heap::s_allocatedSpace = 0; | 2718 size_t Heap::s_allocatedSpace = 0; |
2701 size_t Heap::s_markedObjectSize = 0; | 2719 size_t Heap::s_markedObjectSize = 0; |
2702 | 2720 |
2703 } // namespace blink | 2721 } // namespace blink |
OLD | NEW |