OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 Opera Software AS. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef HeapCompact_h |
| 6 #define HeapCompact_h |
| 7 |
| 8 #include "platform/PlatformExport.h" |
| 9 #include "platform/heap/BlinkGC.h" |
| 10 #include "wtf/PtrUtil.h" |
| 11 #include "wtf/Vector.h" |
| 12 |
| 13 #include <bitset> |
| 14 #include <utility> |
| 15 |
| 16 // Global dev/debug switches: |
| 17 |
| 18 // Set to 0 to prevent compaction GCs, disabling the heap compaction feature. |
| 19 #define ENABLE_HEAP_COMPACTION 1 |
| 20 |
| 21 // Emit debug info during compaction. |
| 22 #define DEBUG_HEAP_COMPACTION 0 |
| 23 |
| 24 // Emit stats on freelist occupancy. |
| 25 // 0 - disabled, 1 - minimal, 2 - verbose. |
| 26 #define DEBUG_HEAP_FREELIST 0 |
| 27 |
| 28 // Log the amount of time spent compacting. |
| 29 #define DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME 0 |
| 30 |
| 31 // Compact during all idle + precise GCs; for debugging. |
| 32 #define STRESS_TEST_HEAP_COMPACTION 0 |
| 33 |
| 34 #if OS(WIN) |
| 35 // TODO: use standard logging facilities. |
| 36 #define LOG_HEAP_COMPACTION_INTERNAL(msg, ...) \ |
| 37 do { \ |
| 38 char output[512]; \ |
| 39 sprintf(output, msg, ##__VA_ARGS__); \ |
| 40 OutputDebugStringA(output); \ |
| 41 } while (0) |
| 42 #else |
| 43 #define LOG_HEAP_COMPACTION_INTERNAL(msg, ...) \ |
| 44 fprintf(stderr, msg, ##__VA_ARGS__) |
| 45 #endif |
| 46 |
| 47 #if DEBUG_HEAP_COMPACTION |
| 48 #define LOG_HEAP_COMPACTION(msg, ...) \ |
| 49 LOG_HEAP_COMPACTION_INTERNAL(msg, ##__VA_ARGS__) |
| 50 #else |
| 51 #define LOG_HEAP_COMPACTION(msg, ...) \ |
| 52 do { \ |
| 53 } while (0) |
| 54 #endif |
| 55 |
| 56 #if DEBUG_HEAP_FREELIST |
| 57 #define LOG_HEAP_FREELIST(msg, ...) \ |
| 58 LOG_HEAP_COMPACTION_INTERNAL(msg, ##__VA_ARGS__) |
| 59 #else |
| 60 #define LOG_HEAP_FREELIST(msg, ...) \ |
| 61 do { \ |
| 62 } while (0) |
| 63 #endif |
| 64 |
| 65 #if DEBUG_HEAP_FREELIST == 2 |
| 66 #define LOG_HEAP_FREELIST_VERBOSE(msg, ...) \ |
| 67 LOG_HEAP_COMPACTION_INTERNAL(msg, ##__VA_ARGS__) |
| 68 #else |
| 69 #define LOG_HEAP_FREELIST_VERBOSE(msg, ...) \ |
| 70 do { \ |
| 71 } while (0) |
| 72 #endif |
| 73 |
| 74 namespace blink { |
| 75 |
| 76 class NormalPageArena; |
| 77 class BasePage; |
| 78 class ThreadHeap; |
| 79 class ThreadState; |
| 80 |
| 81 class PLATFORM_EXPORT HeapCompact final { |
| 82 public: |
| 83 static std::unique_ptr<HeapCompact> create() { |
| 84 return std::unique_ptr<HeapCompact>(new HeapCompact); |
| 85 } |
| 86 |
| 87 ~HeapCompact(); |
| 88 |
| 89 // Check if a GC for the given type and reason should perform additional |
| 90 // heap compaction once it has run. |
| 91 // |
| 92 // If deemed worthy, heap compaction is implicitly initialized and set up. |
| 93 void checkIfCompacting(ThreadHeap*, |
| 94 Visitor*, |
| 95 BlinkGC::GCType, |
| 96 BlinkGC::GCReason); |
| 97 |
| 98 // Returns true if the ongoing GC will perform compaction. |
| 99 bool isCompacting() const { return m_doCompact; } |
| 100 |
| 101 // Returns true if the ongoing GC will perform compaction. |
| 102 bool isCompactingArena(int arenaIndex) const { |
| 103 return m_doCompact && (m_compactableHeaps & (0x1u << arenaIndex)); |
| 104 } |
| 105 |
| 106 // Returns |true| if the ongoing GC may compact the given arena/sub-heap. |
| 107 static bool isCompactableArena(int arenaIndex) { |
| 108 return arenaIndex >= BlinkGC::Vector1ArenaIndex && |
| 109 arenaIndex <= BlinkGC::HashTableArenaIndex; |
| 110 } |
| 111 |
| 112 // See |Heap::registerMovingObjectReference()| documentation. |
| 113 void registerMovingObjectReference(MovableReference* slot); |
| 114 |
| 115 // See |Heap::registerMovingObjectCallback()| documentation. |
| 116 void registerMovingObjectCallback(MovableReference, |
| 117 MovingObjectCallback, |
| 118 void* callbackData); |
| 119 |
| 120 // Register |slot| as containing a reference to the interior of a movable |
| 121 // object. |
| 122 // |
| 123 // |registerMovingObjectReference()| handles the common case of holding an |
| 124 // external |
| 125 // reference to a backing store object. |registerRelocation()| handles the |
| 126 // relocation |
| 127 // of external references into backing store objects - something very rarely |
| 128 // done by |
| 129 // the Blink codebase, but a possibility. |
| 130 void registerRelocation(MovableReference* slot); |
| 131 |
| 132 // Signal that the compaction pass is being started, finished by some |
| 133 // ThreadState. |
| 134 void startCompacting(ThreadState*); |
| 135 void finishedCompacting(ThreadState*); |
| 136 |
| 137 // Perform any relocation post-processing after having completed compacting |
| 138 // the |
| 139 // given sub heap. Pass along the number of pages that were freed from the |
| 140 // arena, |
| 141 // along with their total size. |
| 142 void finishedArenaCompaction(NormalPageArena*, |
| 143 size_t freedPages, |
| 144 size_t freedSize); |
| 145 |
| 146 // Record the main thread's compactable freelist residency (in bytes), |
| 147 // along with with overall size. Sizes are relative to the compactable |
| 148 // sub-heaps, and not a total count. Along with the totals, per-heap |
| 149 // numbers are also provided. |
| 150 // |
| 151 // The recording is done after the decision has been made on whether |
| 152 // or not to compact during the _current_ GC. If compacting, the size |
| 153 // sampling will be ignored and the internal counters are reset. |
| 154 // |
| 155 // However, if not compacting, the values will be consulted the next time |
| 156 // a GC goes ahead and it decides whether to compact or not. |
| 157 void setHeapResidency( |
| 158 size_t liveSize, |
| 159 size_t freeSize, |
| 160 const Vector<std::pair<size_t, size_t>>& heapResidencies); |
| 161 |
| 162 // Register the heap page as containing live objects that will all be |
| 163 // compacted. When the GC is compacting, that is. |
| 164 void addCompactablePage(BasePage*); |
| 165 |
| 166 // Notify heap compaction that object at |from| has been moved to.. |to|. |
| 167 // (Called by the sweep compaction pass.) |
| 168 void movedObject(Address from, Address to); |
| 169 |
| 170 // For unit testing only: arrange for a compaction GC to be triggered |
| 171 // next time a non-conservative GC is run. Sets the compact-next flag |
| 172 // to the new value, returning old. |
| 173 static bool scheduleCompactionGCForTesting(bool); |
| 174 |
| 175 private: |
| 176 class MovableObjectFixups; |
| 177 |
| 178 HeapCompact(); |
| 179 |
| 180 // Parameters controlling when compaction should be done: |
| 181 |
| 182 // Number of GCs that must have passed since last compaction GC. |
| 183 static const int kCompactIntervalThreshold = 10; |
| 184 |
| 185 // Freelist size threshold that must be exceeded before compaction |
| 186 // should be considered. |
| 187 static const size_t kFreeThreshold = 512 * 1024; |
| 188 |
| 189 MovableObjectFixups& fixups(); |
| 190 |
| 191 std::unique_ptr<MovableObjectFixups> m_fixups; |
| 192 |
| 193 // Set to |true| when a compacting sweep will go ahead. |
| 194 bool m_doCompact; |
| 195 size_t m_gcCountSinceLastCompaction; |
| 196 |
| 197 // Number of heap threads participating in the compaction. |
| 198 int m_threadCount; |
| 199 |
| 200 // Last reported freelist size, across all heaps. |
| 201 size_t m_freeListAllocations; |
| 202 // If compacting, i'th sub heap will be compacted |
| 203 // if corresponding bit is set. |
| 204 unsigned m_compactableHeaps; |
| 205 |
| 206 // Stats, number of (complete) pages freed/decommitted + |
| 207 // bytes freed (which will include partial pages.) |
| 208 size_t m_freedPages; |
| 209 size_t m_freedSize; |
| 210 |
| 211 #if DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME |
| 212 int m_startCompaction; |
| 213 double m_startCompactionTimeMS; |
| 214 #endif |
| 215 |
| 216 static bool s_forceCompactionGC; |
| 217 }; |
| 218 |
| 219 } // namespace blink |
| 220 |
| 221 #endif // HeapCompact_h |
OLD | NEW |