Index: Source/platform/heap/Heap.h |
diff --git a/Source/platform/heap/Heap.h b/Source/platform/heap/Heap.h |
index bda991799aa1a0beec3a85ee259b12a861ae5bb1..2dc38fc3ef57f9d49537564124aff75655d7d443 100644 |
--- a/Source/platform/heap/Heap.h |
+++ b/Source/platform/heap/Heap.h |
@@ -999,8 +999,25 @@ public: |
static void increaseAllocatedSpace(size_t delta) { atomicAdd(&s_allocatedSpace, static_cast<long>(delta)); } |
static void decreaseAllocatedSpace(size_t delta) { atomicSubtract(&s_allocatedSpace, static_cast<long>(delta)); } |
static size_t allocatedSpace() { return acquireLoad(&s_allocatedSpace); } |
+ |
static double estimatedMarkingTime(); |
+ // On object allocation, register the object's externally allocated memory. |
+ static inline void increaseExternallyAllocatedBytes(size_t); |
+ static size_t externallyAllocatedBytes() { return acquireLoad(&s_externallyAllocatedBytes); } |
+ |
+ // On object tracing, register the object's externally allocated memory (as still live.) |
+ static void increaseExternallyAllocatedBytesAlive(size_t delta) |
+ { |
+ ASSERT(ThreadState::current()->isInGC()); |
+ s_externallyAllocatedBytesAlive += delta; |
+ } |
+ static size_t externallyAllocatedBytesAlive() { return s_externallyAllocatedBytesAlive; } |
+ |
+ static void requestUrgentGC(); |
+ static void clearUrgentGC() { releaseStore(&s_requestedUrgentGC, 0); } |
+ static bool isUrgentGCRequested() { return acquireLoad(&s_requestedUrgentGC); } |
+ |
private: |
// A RegionTree is a simple binary search tree of PageMemoryRegions sorted |
// by base addresses. |
@@ -1021,8 +1038,8 @@ private: |
RegionTree* m_right; |
}; |
- static void resetAllocatedObjectSize() { ASSERT(ThreadState::current()->isInGC()); s_allocatedObjectSize = 0; } |
- static void resetMarkedObjectSize() { ASSERT(ThreadState::current()->isInGC()); s_markedObjectSize = 0; } |
+ // Reset counters that track live and allocated-since-last-GC sizes. |
+ static void resetHeapCounters(); |
static Visitor* s_markingVisitor; |
static CallbackStack* s_markingStack; |
@@ -1038,6 +1055,10 @@ private: |
static size_t s_allocatedSpace; |
static size_t s_allocatedObjectSize; |
static size_t s_markedObjectSize; |
+ static size_t s_externallyAllocatedBytes; |
+ static size_t s_externallyAllocatedBytesAlive; |
+ static unsigned s_requestedUrgentGC; |
+ |
friend class ThreadState; |
}; |
@@ -1505,6 +1526,28 @@ Address Heap::reallocate(void* previous, size_t size) |
return address; |
} |
+void Heap::increaseExternallyAllocatedBytes(size_t delta) |
+{ |
+ // Flag GC urgency on a 50% increase in external allocation |
+ // since the last GC, but not for less than 100M. |
+ // |
+ // FIXME: consider other, 'better' policies (e.g., have the count of |
+ // heap objects with external allocations be taken into |
+ // account, ...) The overall goal here is to trigger a |
+ // GC such that it considerably lessens memory pressure |
+ // for a renderer process, when absolutely needed. |
+ size_t externalBytesAllocatedSinceLastGC = atomicAdd(&s_externallyAllocatedBytes, static_cast<long>(delta)); |
+ if (LIKELY(externalBytesAllocatedSinceLastGC < 100 * 1024 * 1024)) |
+ return; |
+ |
+ if (UNLIKELY(isUrgentGCRequested())) |
+ return; |
+ |
+ size_t externalBytesAliveAtLastGC = externallyAllocatedBytesAlive(); |
+ if (UNLIKELY(externalBytesAllocatedSinceLastGC > externalBytesAliveAtLastGC / 2)) |
+ Heap::requestUrgentGC(); |
+} |
+ |
class HeapAllocatorQuantizer { |
public: |
template<typename T> |