Index: Source/platform/heap/Heap.cpp |
diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/Heap.cpp |
index 6162d06af097165c83358aa6de169e0fd8e0f7e4..30ddefbc5e4bc7c610403645b3f24137f8b91be8 100644 |
--- a/Source/platform/heap/Heap.cpp |
+++ b/Source/platform/heap/Heap.cpp |
@@ -356,13 +356,29 @@ void BaseHeap::prepareForSweep() |
} |
#if defined(ADDRESS_SANITIZER) |
-void BaseHeap::poisonUnmarkedObjects() |
+void BaseHeap::poisonHeap(ObjectsToPoison objectsToPoison, Poisoning poisoning) |
{ |
- // This method is called just before starting sweeping. |
- // Thus all dead objects are in the list of m_firstUnsweptPage. |
- for (BasePage* page = m_firstUnsweptPage; page; page = page->next()) { |
- page->poisonUnmarkedObjects(); |
+ // TODO(sof): support complete poisoning of all heaps. |
+ ASSERT(objectsToPoison != MarkedAndUnmarked || heapIndex() == EagerSweepHeapIndex); |
+ |
+ // This method may either be called to poison (SetPoison) heap |
+ // object payloads prior to sweeping, or it may be called at |
+ // the completion of a sweep to unpoison (ClearPoison) the |
+ // objects remaining in the heap. Those will all be live and unmarked. |
+ // |
+ // Poisoning may be limited to unmarked objects only, or apply to all. |
+ if (poisoning == SetPoison) { |
+ ASSERT(!m_firstPage); |
+ for (BasePage* page = m_firstUnsweptPage; page; page = page->next()) |
+ page->poisonObjects(objectsToPoison, poisoning); |
+ return; |
} |
+ // Support clearing of poisoning after sweeping has completed, |
+ // in which case the pages of the live objects are reachable |
+ // via m_firstPage. |
+ ASSERT(!m_firstUnsweptPage); |
+ for (BasePage* page = m_firstPage; page; page = page->next()) |
+ page->poisonObjects(objectsToPoison, poisoning); |
} |
#endif |
@@ -796,6 +812,8 @@ Address NormalPageHeap::outOfLineAllocate(size_t allocationSize, size_t gcInfoIn |
// 1. If this allocation is big enough, allocate a large object. |
if (allocationSize >= largeObjectSizeThreshold) { |
+ // TODO(sof): support eagerly finalized large objects, if ever needed. |
+ RELEASE_ASSERT(heapIndex() != EagerSweepHeapIndex); |
LargeObjectHeap* largeObjectHeap = static_cast<LargeObjectHeap*>(threadState()->heap(LargeObjectHeapIndex)); |
Address largeObject = largeObjectHeap->allocateLargeObjectPage(allocationSize, gcInfoIndex); |
ASAN_MARK_LARGE_VECTOR_CONTAINER(this, largeObject); |
@@ -1166,7 +1184,6 @@ void NormalPage::sweep() |
headerAddress += size; |
continue; |
} |
- |
if (startOfGap != headerAddress) |
heapForNormalPage()->addToFreeList(startOfGap, headerAddress - startOfGap); |
header->unmark(); |
@@ -1207,7 +1224,7 @@ void NormalPage::makeConsistentForGC() |
} |
#if defined(ADDRESS_SANITIZER) |
-void NormalPage::poisonUnmarkedObjects() |
+void NormalPage::poisonObjects(ObjectsToPoison objectsToPoison, Poisoning poisoning) |
{ |
for (Address headerAddress = payload(); headerAddress < payloadEnd();) { |
HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAddress); |
@@ -1219,8 +1236,11 @@ void NormalPage::poisonUnmarkedObjects() |
continue; |
} |
header->checkHeader(); |
- if (!header->isMarked()) { |
- ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
+ if (objectsToPoison == MarkedAndUnmarked || !header->isMarked()) { |
+ if (poisoning == SetPoison) |
+ ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
+ else |
+ ASAN_UNPOISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
} |
headerAddress += header->size(); |
} |
@@ -1496,11 +1516,15 @@ void LargeObjectPage::makeConsistentForGC() |
} |
#if defined(ADDRESS_SANITIZER) |
-void LargeObjectPage::poisonUnmarkedObjects() |
+void LargeObjectPage::poisonObjects(ObjectsToPoison objectsToPoison, Poisoning poisoning) |
{ |
HeapObjectHeader* header = heapObjectHeader(); |
- if (!header->isMarked()) |
- ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
+ if (objectsToPoison == MarkedAndUnmarked || !header->isMarked()) { |
+ if (poisoning == SetPoison) |
+ ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
+ else |
+ ASAN_UNPOISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
+ } |
} |
#endif |