Index: third_party/WebKit/Source/platform/heap/HeapCompact.h |
diff --git a/third_party/WebKit/Source/platform/heap/HeapCompact.h b/third_party/WebKit/Source/platform/heap/HeapCompact.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6c24a0a90cfa458509b3836945a2c2768ffa04e7 |
--- /dev/null |
+++ b/third_party/WebKit/Source/platform/heap/HeapCompact.h |
@@ -0,0 +1,227 @@ |
+// Copyright 2016 Opera Software AS. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef HeapCompact_h |
+#define HeapCompact_h |
+ |
+#include "platform/PlatformExport.h" |
+#include "platform/heap/BlinkGC.h" |
+#include "wtf/PtrUtil.h" |
+#include "wtf/ThreadingPrimitives.h" |
+#include "wtf/Vector.h" |
+ |
+#include <bitset> |
+#include <utility> |
+ |
+// Global dev/debug switches: |
+ |
+// Set to 0 to prevent compaction GCs, disabling the heap compaction feature. |
+#define ENABLE_HEAP_COMPACTION 1 |
+ |
+// Emit debug info during compaction. |
+#define DEBUG_HEAP_COMPACTION 0 |
+ |
+// Emit stats on freelist occupancy. |
+// 0 - disabled, 1 - minimal, 2 - verbose. |
+#define DEBUG_HEAP_FREELIST 0 |
+ |
+// Log the amount of time spent compacting. |
+#define DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME 0 |
+ |
+// Compact during all idle + precise GCs; for debugging. |
+#define STRESS_TEST_HEAP_COMPACTION 0 |
+ |
+// TODO(sof): clean up and simplify logging macros before finalizing this CL. |
+ |
+#if OS(WIN) |
+// TODO: use standard logging facilities. |
+#define LOG_HEAP_COMPACTION_INTERNAL(msg, ...) \ |
+ do { \ |
+ char output[512]; \ |
+ sprintf(output, msg, ##__VA_ARGS__); \ |
+ OutputDebugStringA(output); \ |
+ } while (0) |
+#else |
+#define LOG_HEAP_COMPACTION_INTERNAL(msg, ...) \ |
+ fprintf(stderr, msg, ##__VA_ARGS__) |
+#endif |
+ |
+#if DEBUG_HEAP_COMPACTION |
+#define LOG_HEAP_COMPACTION(msg, ...) \ |
+ LOG_HEAP_COMPACTION_INTERNAL(msg, ##__VA_ARGS__) |
+#else |
+#define LOG_HEAP_COMPACTION(msg, ...) \ |
+ do { \ |
+ } while (0) |
+#endif |
+ |
+#if DEBUG_HEAP_FREELIST |
+#define LOG_HEAP_FREELIST(msg, ...) \ |
+ LOG_HEAP_COMPACTION_INTERNAL(msg, ##__VA_ARGS__) |
+#else |
+#define LOG_HEAP_FREELIST(msg, ...) \ |
+ do { \ |
+ } while (0) |
+#endif |
+ |
+#if DEBUG_HEAP_FREELIST == 2 |
+#define LOG_HEAP_FREELIST_VERBOSE(msg, ...) \ |
+ LOG_HEAP_COMPACTION_INTERNAL(msg, ##__VA_ARGS__) |
+#else |
+#define LOG_HEAP_FREELIST_VERBOSE(msg, ...) \ |
+ do { \ |
+ } while (0) |
+#endif |
+ |
+namespace blink { |
+ |
+class NormalPageArena; |
+class BasePage; |
+class ThreadState; |
+ |
+class PLATFORM_EXPORT HeapCompact final { |
+ public: |
+ static std::unique_ptr<HeapCompact> create() { |
+ return wrapUnique(new HeapCompact); |
+ } |
+ |
+ ~HeapCompact(); |
+ |
+ // Check if a GC for the given type and reason should also perform |
+ // additional heap compaction. |
+ // |
+ // If deemed worthy, heap compaction is initialized and set up, |
+ // returning GCWithSweepCompaction to instruct the caller that the |
+ // marking phase must visit the heap with compaction enabled. |
+ BlinkGC::GCType checkIfCompacting(ThreadState*, |
+ BlinkGC::GCType, |
+ BlinkGC::GCReason); |
+ |
+ // Returns true if the ongoing GC will perform compaction. |
+ bool isCompacting() const { return m_doCompact; } |
+ |
+ // Returns true if the ongoing GC will perform compaction for the given |
+ // heap arena. |
+ bool isCompactingArena(int arenaIndex) const { |
+ return m_doCompact && (m_compactableArenas & (0x1u << arenaIndex)); |
+ } |
+ |
+ // Returns |true| if the ongoing GC may compact the given arena/sub-heap. |
+ static bool isCompactableArena(int arenaIndex) { |
+ return arenaIndex >= BlinkGC::Vector1ArenaIndex && |
+ arenaIndex <= BlinkGC::HashTableArenaIndex; |
+ } |
+ |
+ // See |Heap::registerMovingObjectReference()| documentation. |
+ void registerMovingObjectReference(MovableReference* slot); |
+ |
+ // See |Heap::registerMovingObjectCallback()| documentation. |
+ void registerMovingObjectCallback(MovableReference, |
+ MovingObjectCallback, |
+ void* callbackData); |
+ |
+ // Register |slot| as containing a reference to the interior of a movable |
+ // object. |
+ // |
+ // |registerMovingObjectReference()| handles the common case of holding |
+ // an external reference to a backing store object. |registerRelocation()| |
+ // handles the relocation of external references into backing store |
+ // objects -- something not currently done & needed by the Blink codebase, |
+ // but kept open as a possibility..until further notice. |
+ void registerRelocation(MovableReference* slot); |
+ |
+ // Thread signalling that a compaction pass is being started or have |
+ // finished. |
+ // |
+ // A thread participating in a heap GC will wait on the completion |
+ // of compaction across all threads. No thread can be allowed to |
+ // potentially access another thread's heap arenas while they're |
+ // still being compacted. |
+ void startThreadCompaction(ThreadState*); |
+ void finishedThreadCompaction(ThreadState*); |
+ |
+ // Perform any relocation post-processing after having completed compacting |
+ // the given sub heap. Pass along the number of pages that were freed from |
+ // the arena, along with their total size. |
+ void finishedArenaCompaction(NormalPageArena*, |
+ size_t freedPages, |
+ size_t freedSize); |
+ |
+ // Register the heap page as containing live objects that will all be |
+ // compacted. When the GC is compacting, that is. |
+ void addCompactablePage(BasePage*); |
+ |
+ // Notify heap compaction that object at |from| has been moved to.. |to|. |
+ // (Called by the sweep compaction pass.) |
+ void movedObject(Address from, Address to); |
+ |
+ // For unit testing only: arrange for a compaction GC to be triggered |
+ // next time a non-conservative GC is run. Sets the compact-next flag |
+ // to the new value, returning old. |
+ static bool scheduleCompactionGCForTesting(bool); |
+ |
+ private: |
+ class MovableObjectFixups; |
+ |
+ HeapCompact(); |
+ |
+ // Sample the amount of fragmentation and heap memory currently residing |
+ // on the freelists of the arenas we're able to compact. The computed |
+ // numbers will be subsequently used to determine if a heap compaction |
+ // is on order (checkIfCompacting()). |
+ void updateHeapResidency(ThreadState*); |
+ |
+ // Parameters controlling when compaction should be done: |
+ |
+ // Number of GCs that must have passed since last compaction GC. |
+ static const int kGCCountSinceLastCompactionThreshold = 10; |
+ |
+ // Freelist size threshold that must be exceeded before compaction |
+ // should be considered. |
+ static const size_t kFreeListSizeThreshold = 512 * 1024; |
+ |
+ MovableObjectFixups& fixups(); |
+ |
+ std::unique_ptr<MovableObjectFixups> m_fixups; |
+ |
+ // Set to |true| when a compacting sweep will go ahead. |
+ bool m_doCompact; |
+ size_t m_gcCountSinceLastCompaction; |
+ |
+ // Lock protecting finishedThreadCompaction() signalling. |
+ Mutex m_mutex; |
+ |
+ // All threads performing a GC must synchronize on completion |
+ // of all heap compactions. Not doing so risks one thread resuming |
+ // the mutator, which could perform cross-thread access to a heap |
+ // that's still in the process of being compacted. |
+ ThreadCondition m_finished; |
+ |
+ // Number of heap threads participating in the compaction. |
+ int m_threadCount; |
+ |
+ // Last reported freelist size, across all compactable arenas. |
+ size_t m_freeListSize; |
+ |
+ // If compacting, i'th heap arena will be compacted |
+ // if corresponding bit is set. Indexes are in |
+ // the range of BlinkGC::HeapIndices. |
+ unsigned m_compactableArenas; |
+ |
+ // Stats, number of (complete) pages freed/decommitted + |
+ // bytes freed (which will include partial pages.) |
+ size_t m_freedPages; |
+ size_t m_freedSize; |
+ |
+#if DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME |
+ int m_startCompaction; |
+ double m_startCompactionTimeMS; |
+#endif |
+ |
+ static bool s_forceCompactionGC; |
+}; |
+ |
+} // namespace blink |
+ |
+#endif // HeapCompact_h |