Index: third_party/WebKit/Source/wtf/PartitionAlloc.h |
diff --git a/third_party/WebKit/Source/wtf/PartitionAlloc.h b/third_party/WebKit/Source/wtf/PartitionAlloc.h |
index b0e233f4e2d24a442be2936fc08401c1fddc2866..6ecdab32be8d7975c66eecd99fde52e6388ddc04 100644 |
--- a/third_party/WebKit/Source/wtf/PartitionAlloc.h |
+++ b/third_party/WebKit/Source/wtf/PartitionAlloc.h |
@@ -411,6 +411,46 @@ WTF_EXPORT NEVER_INLINE void* partitionReallocGeneric(PartitionRootGeneric*, voi |
WTF_EXPORT void partitionDumpStats(PartitionRoot*, const char* partitionName, bool isLightDump, PartitionStatsDumper*); |
WTF_EXPORT void partitionDumpStatsGeneric(PartitionRootGeneric*, const char* partitionName, bool isLightDump, PartitionStatsDumper*); |
+class WTF_EXPORT PartitionAllocHooks { |
+public: |
+ typedef void AllocationHook(void* address, size_t); |
+ typedef void FreeHook(void* address); |
+ |
+ static void setAllocationHook(AllocationHook* hook) { m_allocationHook = hook; } |
+ static void setFreeHook(FreeHook* hook) { m_freeHook = hook; } |
+ |
+ static void maybeInvokeAllocationHook(void* address, size_t size) |
+ { |
+ AllocationHook* hook = m_allocationHook; |
+ if (UNLIKELY(hook != nullptr)) |
+ hook(address, size); |
+ } |
+ |
+ static void maybeInvokeFreeHook(void* address) |
+ { |
+ FreeHook* hook = m_freeHook; |
+ if (UNLIKELY(hook != nullptr)) |
+ hook(address); |
+ } |
+ |
+ static void maybeInvokeReallocationHook(void* oldAddress, void* newAddress, size_t size) |
+ { |
+ // Report a reallocation as a free followed by an allocation. |
+ AllocationHook* allocHook = m_allocationHook; |
+ FreeHook* freeHook = m_freeHook; |
+ if (UNLIKELY(allocHook && freeHook)) { |
+ freeHook(oldAddress); |
+ allocHook(newAddress, size); |
+ } |
+ } |
+ |
+private: |
+ // Pointers to hook functions that PartitionAlloc will call on allocation and |
+ // free if the pointers are non-null. |
+ static AllocationHook* m_allocationHook; |
+ static FreeHook* m_freeHook; |
+}; |
+ |
ALWAYS_INLINE PartitionFreelistEntry* partitionFreelistMask(PartitionFreelistEntry* ptr) |
{ |
// We use bswap on little endian as a fast mask for two reasons: |
@@ -613,6 +653,9 @@ ALWAYS_INLINE void* partitionBucketAlloc(PartitionRootBase* root, int flags, siz |
partitionCookieWriteValue(charRet); |
partitionCookieWriteValue(charRet + kCookieSize + noCookieSize); |
#endif |
+ |
+ PartitionAllocHooks::maybeInvokeAllocationHook(ret, size); |
+ |
return ret; |
} |
@@ -645,6 +688,9 @@ ALWAYS_INLINE void partitionFreeWithPage(void* ptr, PartitionPage* page) |
partitionCookieCheckValue(reinterpret_cast<char*>(ptr) + slotSize - kCookieSize); |
memset(ptr, kFreedByte, slotSize); |
#endif |
+ |
+ PartitionAllocHooks::maybeInvokeFreeHook(ptr); |
+ |
ASSERT(page->numAllocatedSlots); |
PartitionFreelistEntry* freelistHead = page->freelistHead; |
ASSERT(!freelistHead || partitionPointerIsValid(freelistHead)); |