Chromium Code Reviews| Index: Source/platform/heap/Heap.cpp |
| diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/Heap.cpp |
| index dfe3e0e773fac5a0817483677da6f0fd45d8706c..e5cad5d0ad52344472c19d7b94baac9b5a78bd72 100644 |
| --- a/Source/platform/heap/Heap.cpp |
| +++ b/Source/platform/heap/Heap.cpp |
| @@ -40,6 +40,7 @@ |
| #include "public/platform/Platform.h" |
| #include "wtf/AddressSpaceRandomization.h" |
| #include "wtf/Assertions.h" |
| +#include "wtf/ContainerAnnotations.h" |
| #include "wtf/LeakAnnotations.h" |
| #include "wtf/PassOwnPtr.h" |
| #if ENABLE(GC_PROFILING) |
| @@ -59,6 +60,39 @@ |
| #include <windows.h> |
| #endif |
| +#ifdef ANNOTATE_CONTIGUOUS_CONTAINER |
| +// FIXME: have ContainerAnnotations.h define an ENABLE_-style name instead. |
| +#define ENABLE_ASAN_CONTAINER_ANNOTATIONS 1 |
| + |
| +// When finalizing a non-inlined vector backing store/container, remove |
| +// its contiguous container annotation. Required as it will not be destructed |
| +// from its Vector. |
| +#define ASAN_RETIRE_CONTAINER_ANNOTATION(object, objectSize) \ |
| + do { \ |
| + BasePage* page = pageFromObject(object); \ |
| + ASSERT(page); \ |
| + bool isContainer = page->heap()->heapIndex() == VectorHeapIndex; \ |
| + if (!isContainer && page->isLargeObjectPage()) \ |
| + isContainer = static_cast<LargeObjectPage*>(page)->isVectorBackingPage(); \ |
| + if (isContainer) \ |
| + ANNOTATE_DELETE_BUFFER(object, objectSize, 0); \ |
| + } while (0) |
| + |
| +// A vector backing store represented by a large object is marked |
| +// so that when it is finalized, its ASan annotation will be |
| +// correctly retired. |
| +#define ASAN_MARK_LARGE_VECTOR_CONTAINER(heap, largeObject) \ |
|
haraken
2015/02/21 22:45:41
ASAN_ADD_CONTAINER_ANNOTATION ? (for consistency w
sof
2015/02/22 07:22:11
That would be imprecise consistency, as it doesn't
|
| + if (heap->heapIndex() == VectorHeapIndex) { \ |
| + BasePage* largePage = pageFromObject(largeObject); \ |
| + ASSERT(largePage->isLargeObjectPage()); \ |
| + static_cast<LargeObjectPage*>(largePage)->setIsVectorBackingPage(); \ |
| + } |
| +#else |
| +#define ENABLE_ASAN_CONTAINER_ANNOTATIONS 0 |
| +#define ASAN_RETIRE_CONTAINER_ANNOTATION(payload, payloadSize) |
| +#define ASAN_MARK_LARGE_VECTOR_CONTAINER(heap, largeObject) |
| +#endif |
| + |
| namespace blink { |
| #if ENABLE(GC_PROFILING) |
| @@ -459,6 +493,8 @@ void HeapObjectHeader::finalize(Address object, size_t objectSize) |
| gcInfo->m_finalize(object); |
| } |
| + ASAN_RETIRE_CONTAINER_ANNOTATION(object, objectSize); |
| + |
| #if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) |
| // In Debug builds, memory is zapped when it's freed, and the zapped memory |
| // is zeroed out when the memory is reused. Memory is also zapped when |
| @@ -1019,8 +1055,12 @@ Address NormalPageHeap::outOfLineAllocate(size_t allocationSize, size_t gcInfoIn |
| #endif |
| // 1. If this allocation is big enough, allocate a large object. |
| - if (allocationSize >= largeObjectSizeThreshold) |
| - return static_cast<LargeObjectHeap*>(threadState()->heap(LargeObjectHeapIndex))->allocateLargeObjectPage(allocationSize, gcInfoIndex); |
| + if (allocationSize >= largeObjectSizeThreshold) { |
| + LargeObjectHeap* largeObjectHeap = static_cast<LargeObjectHeap*>(threadState()->heap(LargeObjectHeapIndex)); |
| + Address largeObject = largeObjectHeap->allocateLargeObjectPage(allocationSize, gcInfoIndex); |
| + ASAN_MARK_LARGE_VECTOR_CONTAINER(this, largeObject); |
| + return largeObject; |
| + } |
| // 2. Check if we should trigger a GC. |
| updateRemainingAllocationSize(); |
| @@ -1774,6 +1814,9 @@ NormalPageHeap* NormalPage::heapForNormalPage() |
| LargeObjectPage::LargeObjectPage(PageMemory* storage, BaseHeap* heap, size_t payloadSize) |
| : BasePage(storage, heap) |
| , m_payloadSize(payloadSize) |
| +#if ENABLE(ASAN_CONTAINER_ANNOTATIONS) |
| + , m_isVectorBackingPage(false) |
| +#endif |
| { |
| } |