Index: Source/platform/heap/Heap.cpp |
diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/Heap.cpp |
index c3c3eaddbfea5bb8fecfd098a1bce0840bbdaae0..f15d428ab73bd7af2dc2d10fdcdfb824c07b606d 100644 |
--- a/Source/platform/heap/Heap.cpp |
+++ b/Source/platform/heap/Heap.cpp |
@@ -581,6 +581,12 @@ void BaseHeap::prepareForSweep() |
// Move all pages to a list of unswept pages. |
m_firstUnsweptPage = m_firstPage; |
m_firstPage = nullptr; |
+ |
+#if defined(ADDRESS_SANITIZER) |
+ for (BasePage* page = m_firstPage; page; page = page->next()) { |
sof
2015/04/28 06:12:24
Don't you clear m_firstPage just above, so what wo
haraken
2015/04/28 06:18:35
Very good point. I now understand why I observed n
|
+ page->poisonUnmarkedObjects(); |
+ } |
+#endif |
} |
Address BaseHeap::lazySweep(size_t allocationSize, size_t gcInfoIndex) |
@@ -1506,8 +1512,9 @@ void NormalPage::sweep() |
Address payload = header->payload(); |
// For ASan we unpoison the specific object when calling the |
// finalizer and poison it again when done to allow the object's own |
- // finalizer to operate on the object, but not have other finalizers |
- // be allowed to access it. |
+ // finalizer to operate on the object. Given all other unmarked |
+ // objects are poisoned, ASan will detech an error if the finalizer |
+ // touches any other on-heap object that die at the same GC cycle. |
ASAN_UNPOISON_MEMORY_REGION(payload, payloadSize); |
header->finalize(payload, payloadSize); |
// This memory will be added to the freelist. Maintain the invariant |
@@ -1557,6 +1564,27 @@ void NormalPage::markUnmarkedObjectsDead() |
Heap::increaseMarkedObjectSize(markedObjectSize); |
} |
+#if defined(ADDRESS_SANITIZER) |
+void NormalPage::poisonUnmarkedObjects() |
+{ |
+ for (Address headerAddress = payload(); headerAddress < payloadEnd();) { |
+ HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAddress); |
+ ASSERT(header->size() < blinkPagePayloadSize()); |
+ // Check if a free list entry first since we cannot call |
+ // isMarked on a free list entry. |
+ if (header->isFree()) { |
+ headerAddress += header->size(); |
+ continue; |
+ } |
+ header->checkHeader(); |
+ if (!header->isMarked()) { |
+ ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
+ } |
+ headerAddress += header->size(); |
+ } |
+} |
+#endif |
+ |
void NormalPage::populateObjectStartBitMap() |
{ |
memset(&m_objectStartBitMap, 0, objectStartBitMapSize); |
@@ -1823,6 +1851,15 @@ void LargeObjectPage::markUnmarkedObjectsDead() |
} |
} |
+#if defined(ADDRESS_SANITIZER) |
+void LargeObjectPage::poisonUnmarkedObjects() |
+{ |
+ HeapObjectHeader* header = heapObjectHeader(); |
+ if (!header->isMarked()) |
+ ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
+} |
+#endif |
+ |
void LargeObjectPage::checkAndMarkPointer(Visitor* visitor, Address address) |
{ |
ASSERT(contains(address)); |