| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 STATIC_ONLY(ObjectAliveTrait); | 96 STATIC_ONLY(ObjectAliveTrait); |
| 97 public: | 97 public: |
| 98 NO_LAZY_SWEEP_SANITIZE_ADDRESS | 98 NO_LAZY_SWEEP_SANITIZE_ADDRESS |
| 99 static bool isHeapObjectAlive(T* object) | 99 static bool isHeapObjectAlive(T* object) |
| 100 { | 100 { |
| 101 static_assert(sizeof(T), "T must be fully defined"); | 101 static_assert(sizeof(T), "T must be fully defined"); |
| 102 return object->isHeapObjectAlive(); | 102 return object->isHeapObjectAlive(); |
| 103 } | 103 } |
| 104 }; | 104 }; |
| 105 | 105 |
| 106 class PLATFORM_EXPORT Heap { | 106 class PLATFORM_EXPORT ProcessHeap { |
| 107 STATIC_ONLY(Heap); | 107 STATIC_ONLY(ProcessHeap); |
| 108 public: | 108 public: |
| 109 static void init(); | 109 static void init(); |
| 110 static void shutdown(); | 110 static void shutdown(); |
| 111 | 111 |
| 112 static CrossThreadPersistentRegion& crossThreadPersistentRegion(); | 112 static CrossThreadPersistentRegion& crossThreadPersistentRegion(); |
| 113 | 113 |
| 114 static bool isLowEndDevice() { return s_isLowEndDevice; } |
| 115 static void increaseTotalAllocatedObjectSize(size_t delta) { atomicAdd(&s_to
talAllocatedObjectSize, static_cast<long>(delta)); } |
| 116 static void decreaseTotalAllocatedObjectSize(size_t delta) { atomicSubtract(
&s_totalAllocatedObjectSize, static_cast<long>(delta)); } |
| 117 static size_t totalAllocatedObjectSize() { return acquireLoad(&s_totalAlloca
tedObjectSize); } |
| 118 static void increaseTotalMarkedObjectSize(size_t delta) { atomicAdd(&s_total
MarkedObjectSize, static_cast<long>(delta)); } |
| 119 static size_t totalMarkedObjectSize() { return acquireLoad(&s_totalMarkedObj
ectSize); } |
| 120 static void increaseTotalAllocatedSpace(size_t delta) { atomicAdd(&s_totalAl
locatedSpace, static_cast<long>(delta)); } |
| 121 static void decreaseTotalAllocatedSpace(size_t delta) { atomicSubtract(&s_to
talAllocatedSpace, static_cast<long>(delta)); } |
| 122 static size_t totalAllocatedSpace() { return acquireLoad(&s_totalAllocatedSp
ace); } |
| 123 |
| 124 private: |
| 125 static bool s_shutdownComplete; |
| 126 static bool s_isLowEndDevice; |
| 127 static size_t s_totalAllocatedSpace; |
| 128 static size_t s_totalAllocatedObjectSize; |
| 129 static size_t s_totalMarkedObjectSize; |
| 130 |
| 131 friend class ThreadState; |
| 132 }; |
| 133 |
| 134 // Stats for the heap. |
| 135 class ThreadHeapStats { |
| 136 public: |
| 137 ThreadHeapStats(); |
| 138 void setMarkedObjectSizeAtLastCompleteSweep(size_t size) { releaseStore(&m_m
arkedObjectSizeAtLastCompleteSweep, size); } |
| 139 size_t markedObjectSizeAtLastCompleteSweep() { return acquireLoad(&m_markedO
bjectSizeAtLastCompleteSweep); } |
| 140 void increaseAllocatedObjectSize(size_t delta); |
| 141 void decreaseAllocatedObjectSize(size_t delta); |
| 142 size_t allocatedObjectSize() { return acquireLoad(&m_allocatedObjectSize); } |
| 143 void increaseMarkedObjectSize(size_t delta); |
| 144 size_t markedObjectSize() { return acquireLoad(&m_markedObjectSize); } |
| 145 void increaseAllocatedSpace(size_t delta); |
| 146 void decreaseAllocatedSpace(size_t delta); |
| 147 size_t allocatedSpace() { return acquireLoad(&m_allocatedSpace); } |
| 148 size_t objectSizeAtLastGC() { return acquireLoad(&m_objectSizeAtLastGC); } |
| 149 void increaseWrapperCount(size_t delta) { atomicAdd(&m_wrapperCount, static_
cast<long>(delta)); } |
| 150 void decreaseWrapperCount(size_t delta) { atomicSubtract(&m_wrapperCount, st
atic_cast<long>(delta)); } |
| 151 size_t wrapperCount() { return acquireLoad(&m_wrapperCount); } |
| 152 size_t wrapperCountAtLastGC() { return acquireLoad(&m_wrapperCountAtLastGC);
} |
| 153 void increaseCollectedWrapperCount(size_t delta) { atomicAdd(&m_collectedWra
pperCount, static_cast<long>(delta)); } |
| 154 size_t collectedWrapperCount() { return acquireLoad(&m_collectedWrapperCount
); } |
| 155 size_t partitionAllocSizeAtLastGC() { return acquireLoad(&m_partitionAllocSi
zeAtLastGC); } |
| 156 void setEstimatedMarkingTimePerByte(double estimatedMarkingTimePerByte) { m_
estimatedMarkingTimePerByte = estimatedMarkingTimePerByte; } |
| 157 double estimatedMarkingTimePerByte() const { return m_estimatedMarkingTimePe
rByte; } |
| 158 double estimatedMarkingTime(); |
| 159 void reset(); |
| 160 |
| 161 private: |
| 162 size_t m_allocatedSpace; |
| 163 size_t m_allocatedObjectSize; |
| 164 size_t m_objectSizeAtLastGC; |
| 165 size_t m_markedObjectSize; |
| 166 size_t m_markedObjectSizeAtLastCompleteSweep; |
| 167 size_t m_wrapperCount; |
| 168 size_t m_wrapperCountAtLastGC; |
| 169 size_t m_collectedWrapperCount; |
| 170 size_t m_partitionAllocSizeAtLastGC; |
| 171 double m_estimatedMarkingTimePerByte; |
| 172 }; |
| 173 |
| 174 using ThreadStateSet = HashSet<ThreadState*>; |
| 175 |
| 176 class PLATFORM_EXPORT ThreadHeap { |
| 177 public: |
| 178 ThreadHeap(); |
| 179 ~ThreadHeap(); |
| 180 |
| 181 // Returns true for main thread's heap. |
| 182 // TODO(keishi): Per-thread-heap will return false. |
| 183 bool isMain() { return true; } |
| 184 |
| 185 RecursiveMutex& threadAttachMutex() { return m_threadAttachMutex; } |
| 186 const ThreadStateSet& threads() const { return m_threads; } |
| 187 ThreadHeapStats& heapStats() { return m_stats; } |
| 188 SafePointBarrier* safePointBarrier() { return m_safePointBarrier.get(); } |
| 189 CallbackStack* markingStack() const { return m_markingStack.get(); } |
| 190 CallbackStack* postMarkingCallbackStack() const { return m_postMarkingCallba
ckStack.get(); } |
| 191 CallbackStack* globalWeakCallbackStack() const { return m_globalWeakCallback
Stack.get(); } |
| 192 CallbackStack* ephemeronStack() const { return m_ephemeronStack.get(); } |
| 193 |
| 194 void attach(ThreadState*); |
| 195 void detach(ThreadState*); |
| 196 void lockThreadAttachMutex(); |
| 197 void unlockThreadAttachMutex(); |
| 198 bool park(); |
| 199 void resume(); |
| 200 |
| 114 #if ENABLE(ASSERT) | 201 #if ENABLE(ASSERT) |
| 115 static BasePage* findPageFromAddress(Address); | 202 bool isAtSafePoint(); |
| 116 static BasePage* findPageFromAddress(const void* pointer) { return findPageF
romAddress(reinterpret_cast<Address>(const_cast<void*>(pointer))); } | 203 BasePage* findPageFromAddress(Address); |
| 117 #endif | 204 #endif |
| 118 | 205 |
| 206 void visitPersistentRoots(Visitor*); |
| 207 void visitStackRoots(Visitor*); |
| 208 void checkAndPark(ThreadState*, SafePointAwareMutexLocker*); |
| 209 void enterSafePoint(ThreadState*); |
| 210 void leaveSafePoint(ThreadState*, SafePointAwareMutexLocker*); |
| 211 |
| 212 // Add a weak pointer callback to the weak callback work list. General |
| 213 // object pointer callbacks are added to a thread local weak callback work |
| 214 // list and the callback is called on the thread that owns the object, with |
| 215 // the closure pointer as an argument. Most of the time, the closure and |
| 216 // the containerObject can be the same thing, but the containerObject is |
| 217 // constrained to be on the heap, since the heap is used to identify the |
| 218 // correct thread. |
| 219 void pushThreadLocalWeakCallback(void* closure, void* containerObject, WeakC
allback); |
| 220 |
| 221 static RecursiveMutex& allHeapsMutex(); |
| 222 static HashSet<ThreadHeap*>& allHeaps(); |
| 223 |
| 119 template<typename T> | 224 template<typename T> |
| 120 static inline bool isHeapObjectAlive(T* object) | 225 static inline bool isHeapObjectAlive(T* object) |
| 121 { | 226 { |
| 122 static_assert(sizeof(T), "T must be fully defined"); | 227 static_assert(sizeof(T), "T must be fully defined"); |
| 123 // The strongification of collections relies on the fact that once a | 228 // The strongification of collections relies on the fact that once a |
| 124 // collection has been strongified, there is no way that it can contain | 229 // collection has been strongified, there is no way that it can contain |
| 125 // non-live entries, so no entries will be removed. Since you can't set | 230 // non-live entries, so no entries will be removed. Since you can't set |
| 126 // the mark bit on a null pointer, that means that null pointers are | 231 // the mark bit on a null pointer, that means that null pointers are |
| 127 // always 'alive'. | 232 // always 'alive'. |
| 128 if (!object) | 233 if (!object) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 template<typename T> | 266 template<typename T> |
| 162 NO_LAZY_SWEEP_SANITIZE_ADDRESS | 267 NO_LAZY_SWEEP_SANITIZE_ADDRESS |
| 163 static bool willObjectBeLazilySwept(const T* objectPointer) | 268 static bool willObjectBeLazilySwept(const T* objectPointer) |
| 164 { | 269 { |
| 165 static_assert(IsGarbageCollectedType<T>::value, "only objects deriving f
rom GarbageCollected can be used."); | 270 static_assert(IsGarbageCollectedType<T>::value, "only objects deriving f
rom GarbageCollected can be used."); |
| 166 BasePage* page = pageFromObject(objectPointer); | 271 BasePage* page = pageFromObject(objectPointer); |
| 167 if (page->hasBeenSwept()) | 272 if (page->hasBeenSwept()) |
| 168 return false; | 273 return false; |
| 169 ASSERT(page->arena()->getThreadState()->isSweepingInProgress()); | 274 ASSERT(page->arena()->getThreadState()->isSweepingInProgress()); |
| 170 | 275 |
| 171 return !Heap::isHeapObjectAlive(const_cast<T*>(objectPointer)); | 276 return !ThreadHeap::isHeapObjectAlive(const_cast<T*>(objectPointer)); |
| 172 } | 277 } |
| 173 | 278 |
| 174 // Push a trace callback on the marking stack. | 279 // Push a trace callback on the marking stack. |
| 175 static void pushTraceCallback(void* containerObject, TraceCallback); | 280 void pushTraceCallback(void* containerObject, TraceCallback); |
| 176 | 281 |
| 177 // Push a trace callback on the post-marking callback stack. These | 282 // Push a trace callback on the post-marking callback stack. These |
| 178 // callbacks are called after normal marking (including ephemeron | 283 // callbacks are called after normal marking (including ephemeron |
| 179 // iteration). | 284 // iteration). |
| 180 static void pushPostMarkingCallback(void*, TraceCallback); | 285 void pushPostMarkingCallback(void*, TraceCallback); |
| 181 | |
| 182 // Add a weak pointer callback to the weak callback work list. General | |
| 183 // object pointer callbacks are added to a thread local weak callback work | |
| 184 // list and the callback is called on the thread that owns the object, with | |
| 185 // the closure pointer as an argument. Most of the time, the closure and | |
| 186 // the containerObject can be the same thing, but the containerObject is | |
| 187 // constrained to be on the heap, since the heap is used to identify the | |
| 188 // correct thread. | |
| 189 static void pushThreadLocalWeakCallback(void* closure, void* containerObject
, WeakCallback); | |
| 190 | 286 |
| 191 // Similar to the more general pushThreadLocalWeakCallback, but cell | 287 // Similar to the more general pushThreadLocalWeakCallback, but cell |
| 192 // pointer callbacks are added to a static callback work list and the weak | 288 // pointer callbacks are added to a static callback work list and the weak |
| 193 // callback is performed on the thread performing garbage collection. This | 289 // callback is performed on the thread performing garbage collection. This |
| 194 // is OK because cells are just cleared and no deallocation can happen. | 290 // is OK because cells are just cleared and no deallocation can happen. |
| 195 static void pushGlobalWeakCallback(void** cell, WeakCallback); | 291 void pushGlobalWeakCallback(void** cell, WeakCallback); |
| 196 | 292 |
| 197 // Pop the top of a marking stack and call the callback with the visitor | 293 // Pop the top of a marking stack and call the callback with the visitor |
| 198 // and the object. Returns false when there is nothing more to do. | 294 // and the object. Returns false when there is nothing more to do. |
| 199 static bool popAndInvokeTraceCallback(Visitor*); | 295 bool popAndInvokeTraceCallback(Visitor*); |
| 200 | 296 |
| 201 // Remove an item from the post-marking callback stack and call | 297 // Remove an item from the post-marking callback stack and call |
| 202 // the callback with the visitor and the object pointer. Returns | 298 // the callback with the visitor and the object pointer. Returns |
| 203 // false when there is nothing more to do. | 299 // false when there is nothing more to do. |
| 204 static bool popAndInvokePostMarkingCallback(Visitor*); | 300 bool popAndInvokePostMarkingCallback(Visitor*); |
| 205 | 301 |
| 206 // Remove an item from the weak callback work list and call the callback | 302 // Remove an item from the weak callback work list and call the callback |
| 207 // with the visitor and the closure pointer. Returns false when there is | 303 // with the visitor and the closure pointer. Returns false when there is |
| 208 // nothing more to do. | 304 // nothing more to do. |
| 209 static bool popAndInvokeGlobalWeakCallback(Visitor*); | 305 bool popAndInvokeGlobalWeakCallback(Visitor*); |
| 210 | 306 |
| 211 // Register an ephemeron table for fixed-point iteration. | 307 // Register an ephemeron table for fixed-point iteration. |
| 212 static void registerWeakTable(void* containerObject, EphemeronCallback, Ephe
meronCallback); | 308 void registerWeakTable(void* containerObject, EphemeronCallback, EphemeronCa
llback); |
| 309 |
| 213 #if ENABLE(ASSERT) | 310 #if ENABLE(ASSERT) |
| 214 static bool weakTableRegistered(const void*); | 311 bool weakTableRegistered(const void*); |
| 215 #endif | 312 #endif |
| 216 | 313 |
| 314 BlinkGC::GCReason lastGCReason() { return m_lastGCReason; } |
| 315 RegionTree* getRegionTree() { return m_regionTree.get(); } |
| 316 |
| 217 static inline size_t allocationSizeFromSize(size_t size) | 317 static inline size_t allocationSizeFromSize(size_t size) |
| 218 { | 318 { |
| 219 // Check the size before computing the actual allocation size. The | 319 // Check the size before computing the actual allocation size. The |
| 220 // allocation size calculation can overflow for large sizes and the chec
k | 320 // allocation size calculation can overflow for large sizes and the chec
k |
| 221 // therefore has to happen before any calculation on the size. | 321 // therefore has to happen before any calculation on the size. |
| 222 RELEASE_ASSERT(size < maxHeapObjectSize); | 322 RELEASE_ASSERT(size < maxHeapObjectSize); |
| 223 | 323 |
| 224 // Add space for header. | 324 // Add space for header. |
| 225 size_t allocationSize = size + sizeof(HeapObjectHeader); | 325 size_t allocationSize = size + sizeof(HeapObjectHeader); |
| 226 // Align size with allocation granularity. | 326 // Align size with allocation granularity. |
| 227 allocationSize = (allocationSize + allocationMask) & ~allocationMask; | 327 allocationSize = (allocationSize + allocationMask) & ~allocationMask; |
| 228 return allocationSize; | 328 return allocationSize; |
| 229 } | 329 } |
| 230 static Address allocateOnArenaIndex(ThreadState*, size_t, int arenaIndex, si
ze_t gcInfoIndex, const char* typeName); | 330 static Address allocateOnArenaIndex(ThreadState*, size_t, int arenaIndex, si
ze_t gcInfoIndex, const char* typeName); |
| 231 template<typename T> static Address allocate(size_t, bool eagerlySweep = fal
se); | 331 template<typename T> static Address allocate(size_t, bool eagerlySweep = fal
se); |
| 232 template<typename T> static Address reallocate(void* previous, size_t); | 332 template<typename T> static Address reallocate(void* previous, size_t); |
| 233 | 333 |
| 234 static const char* gcReasonString(BlinkGC::GCReason); | 334 static const char* gcReasonString(BlinkGC::GCReason); |
| 235 static void collectGarbage(BlinkGC::StackState, BlinkGC::GCType, BlinkGC::GC
Reason); | 335 static void collectGarbage(BlinkGC::StackState, BlinkGC::GCType, BlinkGC::GC
Reason); |
| 236 static void collectGarbageForTerminatingThread(ThreadState*); | 336 static void collectGarbageForTerminatingThread(ThreadState*); |
| 237 static void collectAllGarbage(); | 337 static void collectAllGarbage(); |
| 238 | 338 |
| 239 static void processMarkingStack(Visitor*); | 339 void processMarkingStack(Visitor*); |
| 240 static void postMarkingProcessing(Visitor*); | 340 void postMarkingProcessing(Visitor*); |
| 241 static void globalWeakProcessing(Visitor*); | 341 void globalWeakProcessing(Visitor*); |
| 242 static void setForcePreciseGCForTesting(); | |
| 243 | 342 |
| 244 static void preGC(); | 343 void preGC(); |
| 245 static void postGC(BlinkGC::GCType); | 344 void postGC(BlinkGC::GCType); |
| 246 | 345 |
| 247 // Conservatively checks whether an address is a pointer in any of the | 346 // Conservatively checks whether an address is a pointer in any of the |
| 248 // thread heaps. If so marks the object pointed to as live. | 347 // thread heaps. If so marks the object pointed to as live. |
| 249 static Address checkAndMarkPointer(Visitor*, Address); | 348 Address checkAndMarkPointer(Visitor*, Address); |
| 250 | 349 |
| 251 static size_t objectPayloadSizeForTesting(); | 350 size_t objectPayloadSizeForTesting(); |
| 252 | 351 |
| 253 static void flushHeapDoesNotContainCache(); | 352 void flushHeapDoesNotContainCache(); |
| 254 | 353 |
| 255 static FreePagePool* getFreePagePool() { return s_freePagePool; } | 354 FreePagePool* getFreePagePool() { return m_freePagePool.get(); } |
| 256 static OrphanedPagePool* getOrphanedPagePool() { return s_orphanedPagePool;
} | 355 OrphanedPagePool* getOrphanedPagePool() { return m_orphanedPagePool.get(); } |
| 257 | 356 |
| 258 // This look-up uses the region search tree and a negative contains cache to | 357 // This look-up uses the region search tree and a negative contains cache to |
| 259 // provide an efficient mapping from arbitrary addresses to the containing | 358 // provide an efficient mapping from arbitrary addresses to the containing |
| 260 // heap-page if one exists. | 359 // heap-page if one exists. |
| 261 static BasePage* lookup(Address); | 360 BasePage* lookupPageForAddress(Address); |
| 262 static RegionTree* getRegionTree(); | |
| 263 | 361 |
| 264 static const GCInfo* gcInfo(size_t gcInfoIndex) | 362 static const GCInfo* gcInfo(size_t gcInfoIndex) |
| 265 { | 363 { |
| 266 ASSERT(gcInfoIndex >= 1); | 364 ASSERT(gcInfoIndex >= 1); |
| 267 ASSERT(gcInfoIndex < GCInfoTable::maxIndex); | 365 ASSERT(gcInfoIndex < GCInfoTable::maxIndex); |
| 268 ASSERT(s_gcInfoTable); | 366 ASSERT(s_gcInfoTable); |
| 269 const GCInfo* info = s_gcInfoTable[gcInfoIndex]; | 367 const GCInfo* info = s_gcInfoTable[gcInfoIndex]; |
| 270 ASSERT(info); | 368 ASSERT(info); |
| 271 return info; | 369 return info; |
| 272 } | 370 } |
| 273 | 371 |
| 274 static void setMarkedObjectSizeAtLastCompleteSweep(size_t size) { releaseSto
re(&s_markedObjectSizeAtLastCompleteSweep, size); } | |
| 275 static size_t markedObjectSizeAtLastCompleteSweep() { return acquireLoad(&s_
markedObjectSizeAtLastCompleteSweep); } | |
| 276 static void increaseAllocatedObjectSize(size_t delta) { atomicAdd(&s_allocat
edObjectSize, static_cast<long>(delta)); } | |
| 277 static void decreaseAllocatedObjectSize(size_t delta) { atomicSubtract(&s_al
locatedObjectSize, static_cast<long>(delta)); } | |
| 278 static size_t allocatedObjectSize() { return acquireLoad(&s_allocatedObjectS
ize); } | |
| 279 static void increaseMarkedObjectSize(size_t delta) { atomicAdd(&s_markedObje
ctSize, static_cast<long>(delta)); } | |
| 280 static size_t markedObjectSize() { return acquireLoad(&s_markedObjectSize);
} | |
| 281 static void increaseAllocatedSpace(size_t delta) { atomicAdd(&s_allocatedSpa
ce, static_cast<long>(delta)); } | |
| 282 static void decreaseAllocatedSpace(size_t delta) { atomicSubtract(&s_allocat
edSpace, static_cast<long>(delta)); } | |
| 283 static size_t allocatedSpace() { return acquireLoad(&s_allocatedSpace); } | |
| 284 static size_t objectSizeAtLastGC() { return acquireLoad(&s_objectSizeAtLastG
C); } | |
| 285 static void increaseWrapperCount(size_t delta) { atomicAdd(&s_wrapperCount,
static_cast<long>(delta)); } | |
| 286 static void decreaseWrapperCount(size_t delta) { atomicSubtract(&s_wrapperCo
unt, static_cast<long>(delta)); } | |
| 287 static size_t wrapperCount() { return acquireLoad(&s_wrapperCount); } | |
| 288 static size_t wrapperCountAtLastGC() { return acquireLoad(&s_wrapperCountAtL
astGC); } | |
| 289 static void increaseCollectedWrapperCount(size_t delta) { atomicAdd(&s_colle
ctedWrapperCount, static_cast<long>(delta)); } | |
| 290 static size_t collectedWrapperCount() { return acquireLoad(&s_collectedWrapp
erCount); } | |
| 291 static size_t partitionAllocSizeAtLastGC() { return acquireLoad(&s_partition
AllocSizeAtLastGC); } | |
| 292 | |
| 293 static double estimatedMarkingTime(); | |
| 294 static void reportMemoryUsageHistogram(); | 372 static void reportMemoryUsageHistogram(); |
| 295 static void reportMemoryUsageForTracing(); | 373 static void reportMemoryUsageForTracing(); |
| 296 static bool isLowEndDevice() { return s_isLowEndDevice; } | |
| 297 static BlinkGC::GCReason lastGCReason() { return s_lastGCReason; } | |
| 298 | |
| 299 #if ENABLE(ASSERT) | |
| 300 static uint16_t gcGeneration() { return s_gcGeneration; } | |
| 301 #endif | |
| 302 | 374 |
| 303 private: | 375 private: |
| 304 // Reset counters that track live and allocated-since-last-GC sizes. | 376 // Reset counters that track live and allocated-since-last-GC sizes. |
| 305 static void resetHeapCounters(); | 377 void resetHeapCounters(); |
| 306 | 378 |
| 307 static int arenaIndexForObjectSize(size_t); | 379 static int arenaIndexForObjectSize(size_t); |
| 308 static bool isNormalArenaIndex(int); | 380 static bool isNormalArenaIndex(int); |
| 309 | 381 |
| 310 static void decommitCallbackStacks(); | 382 void decommitCallbackStacks(); |
| 311 | 383 |
| 312 static CallbackStack* s_markingStack; | 384 RecursiveMutex m_threadAttachMutex; |
| 313 static CallbackStack* s_postMarkingCallbackStack; | 385 ThreadStateSet m_threads; |
| 314 static CallbackStack* s_globalWeakCallbackStack; | 386 ThreadHeapStats m_stats; |
| 315 static CallbackStack* s_ephemeronStack; | 387 OwnPtr<RegionTree> m_regionTree; |
| 316 static HeapDoesNotContainCache* s_heapDoesNotContainCache; | 388 OwnPtr<HeapDoesNotContainCache> m_heapDoesNotContainCache; |
| 317 static FreePagePool* s_freePagePool; | 389 OwnPtr<SafePointBarrier> m_safePointBarrier; |
| 318 static OrphanedPagePool* s_orphanedPagePool; | 390 OwnPtr<FreePagePool> m_freePagePool; |
| 319 static size_t s_allocatedSpace; | 391 OwnPtr<OrphanedPagePool> m_orphanedPagePool; |
| 320 static size_t s_allocatedObjectSize; | 392 OwnPtr<CallbackStack> m_markingStack; |
| 321 static size_t s_objectSizeAtLastGC; | 393 OwnPtr<CallbackStack> m_postMarkingCallbackStack; |
| 322 static size_t s_markedObjectSize; | 394 OwnPtr<CallbackStack> m_globalWeakCallbackStack; |
| 323 static size_t s_markedObjectSizeAtLastCompleteSweep; | 395 OwnPtr<CallbackStack> m_ephemeronStack; |
| 324 static size_t s_wrapperCount; | 396 BlinkGC::GCReason m_lastGCReason; |
| 325 static size_t s_wrapperCountAtLastGC; | |
| 326 static size_t s_collectedWrapperCount; | |
| 327 static size_t s_partitionAllocSizeAtLastGC; | |
| 328 static double s_estimatedMarkingTimePerByte; | |
| 329 static bool s_isLowEndDevice; | |
| 330 static BlinkGC::GCReason s_lastGCReason; | |
| 331 #if ENABLE(ASSERT) | |
| 332 static uint16_t s_gcGeneration; | |
| 333 #endif | |
| 334 | 397 |
| 335 friend class ThreadState; | 398 friend class ThreadState; |
| 336 }; | 399 }; |
| 337 | 400 |
| 338 template<typename T> | 401 template<typename T> |
| 339 struct IsEagerlyFinalizedType { | 402 struct IsEagerlyFinalizedType { |
| 340 STATIC_ONLY(IsEagerlyFinalizedType); | 403 STATIC_ONLY(IsEagerlyFinalizedType); |
| 341 private: | 404 private: |
| 342 typedef char YesType; | 405 typedef char YesType; |
| 343 struct NoType { | 406 struct NoType { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 374 public: | 437 public: |
| 375 using GarbageCollectedType = T; | 438 using GarbageCollectedType = T; |
| 376 | 439 |
| 377 void* operator new(size_t size) | 440 void* operator new(size_t size) |
| 378 { | 441 { |
| 379 return allocateObject(size, IsEagerlyFinalizedType<T>::value); | 442 return allocateObject(size, IsEagerlyFinalizedType<T>::value); |
| 380 } | 443 } |
| 381 | 444 |
| 382 static void* allocateObject(size_t size, bool eagerlySweep) | 445 static void* allocateObject(size_t size, bool eagerlySweep) |
| 383 { | 446 { |
| 384 return Heap::allocate<T>(size, eagerlySweep); | 447 return ThreadHeap::allocate<T>(size, eagerlySweep); |
| 385 } | 448 } |
| 386 | 449 |
| 387 void operator delete(void* p) | 450 void operator delete(void* p) |
| 388 { | 451 { |
| 389 ASSERT_NOT_REACHED(); | 452 ASSERT_NOT_REACHED(); |
| 390 } | 453 } |
| 391 | 454 |
| 392 protected: | 455 protected: |
| 393 GarbageCollected() | 456 GarbageCollected() |
| 394 { | 457 { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 407 // | 470 // |
| 408 // An exception to the use of sized arenas is made for class types that | 471 // An exception to the use of sized arenas is made for class types that |
| 409 // require prompt finalization after a garbage collection. That is, their | 472 // require prompt finalization after a garbage collection. That is, their |
| 410 // instances have to be finalized early and cannot be delayed until lazy | 473 // instances have to be finalized early and cannot be delayed until lazy |
| 411 // sweeping kicks in for their heap and page. The EAGERLY_FINALIZE() | 474 // sweeping kicks in for their heap and page. The EAGERLY_FINALIZE() |
| 412 // macro is used to declare a class (and its derived classes) as being | 475 // macro is used to declare a class (and its derived classes) as being |
| 413 // in need of eager finalization. Must be defined with 'public' visibility | 476 // in need of eager finalization. Must be defined with 'public' visibility |
| 414 // for a class. | 477 // for a class. |
| 415 // | 478 // |
| 416 | 479 |
| 417 inline int Heap::arenaIndexForObjectSize(size_t size) | 480 inline int ThreadHeap::arenaIndexForObjectSize(size_t size) |
| 418 { | 481 { |
| 419 if (size < 64) { | 482 if (size < 64) { |
| 420 if (size < 32) | 483 if (size < 32) |
| 421 return BlinkGC::NormalPage1ArenaIndex; | 484 return BlinkGC::NormalPage1ArenaIndex; |
| 422 return BlinkGC::NormalPage2ArenaIndex; | 485 return BlinkGC::NormalPage2ArenaIndex; |
| 423 } | 486 } |
| 424 if (size < 128) | 487 if (size < 128) |
| 425 return BlinkGC::NormalPage3ArenaIndex; | 488 return BlinkGC::NormalPage3ArenaIndex; |
| 426 return BlinkGC::NormalPage4ArenaIndex; | 489 return BlinkGC::NormalPage4ArenaIndex; |
| 427 } | 490 } |
| 428 | 491 |
| 429 inline bool Heap::isNormalArenaIndex(int index) | 492 inline bool ThreadHeap::isNormalArenaIndex(int index) |
| 430 { | 493 { |
| 431 return index >= BlinkGC::NormalPage1ArenaIndex && index <= BlinkGC::NormalPa
ge4ArenaIndex; | 494 return index >= BlinkGC::NormalPage1ArenaIndex && index <= BlinkGC::NormalPa
ge4ArenaIndex; |
| 432 } | 495 } |
| 433 | 496 |
| 434 #define DECLARE_EAGER_FINALIZATION_OPERATOR_NEW() \ | 497 #define DECLARE_EAGER_FINALIZATION_OPERATOR_NEW() \ |
| 435 public: \ | 498 public: \ |
| 436 GC_PLUGIN_IGNORE("491488") \ | 499 GC_PLUGIN_IGNORE("491488") \ |
| 437 void* operator new(size_t size) \ | 500 void* operator new(size_t size) \ |
| 438 { \ | 501 { \ |
| 439 return allocateObject(size, true); \ | 502 return allocateObject(size, true); \ |
| (...skipping 25 matching lines...) Expand all Loading... |
| 465 #else | 528 #else |
| 466 #define EAGERLY_FINALIZE() typedef int IsEagerlyFinalizedMarker | 529 #define EAGERLY_FINALIZE() typedef int IsEagerlyFinalizedMarker |
| 467 #endif | 530 #endif |
| 468 | 531 |
| 469 #if !ENABLE(OILPAN) | 532 #if !ENABLE(OILPAN) |
| 470 #define EAGERLY_FINALIZE_WILL_BE_REMOVED() EAGERLY_FINALIZE() | 533 #define EAGERLY_FINALIZE_WILL_BE_REMOVED() EAGERLY_FINALIZE() |
| 471 #else | 534 #else |
| 472 #define EAGERLY_FINALIZE_WILL_BE_REMOVED() | 535 #define EAGERLY_FINALIZE_WILL_BE_REMOVED() |
| 473 #endif | 536 #endif |
| 474 | 537 |
| 475 inline Address Heap::allocateOnArenaIndex(ThreadState* state, size_t size, int a
renaIndex, size_t gcInfoIndex, const char* typeName) | 538 inline Address ThreadHeap::allocateOnArenaIndex(ThreadState* state, size_t size,
int arenaIndex, size_t gcInfoIndex, const char* typeName) |
| 476 { | 539 { |
| 477 ASSERT(state->isAllocationAllowed()); | 540 ASSERT(state->isAllocationAllowed()); |
| 478 ASSERT(arenaIndex != BlinkGC::LargeObjectArenaIndex); | 541 ASSERT(arenaIndex != BlinkGC::LargeObjectArenaIndex); |
| 479 NormalPageArena* arena = static_cast<NormalPageArena*>(state->arena(arenaInd
ex)); | 542 NormalPageArena* arena = static_cast<NormalPageArena*>(state->arena(arenaInd
ex)); |
| 480 Address address = arena->allocateObject(allocationSizeFromSize(size), gcInfo
Index); | 543 Address address = arena->allocateObject(allocationSizeFromSize(size), gcInfo
Index); |
| 481 HeapAllocHooks::allocationHookIfEnabled(address, size, typeName); | 544 HeapAllocHooks::allocationHookIfEnabled(address, size, typeName); |
| 482 return address; | 545 return address; |
| 483 } | 546 } |
| 484 | 547 |
| 485 template<typename T> | 548 template<typename T> |
| 486 Address Heap::allocate(size_t size, bool eagerlySweep) | 549 Address ThreadHeap::allocate(size_t size, bool eagerlySweep) |
| 487 { | 550 { |
| 488 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); | 551 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); |
| 489 const char* typeName = WTF_HEAP_PROFILER_TYPE_NAME(T); | 552 const char* typeName = WTF_HEAP_PROFILER_TYPE_NAME(T); |
| 490 return Heap::allocateOnArenaIndex(state, size, eagerlySweep ? BlinkGC::Eager
SweepArenaIndex : Heap::arenaIndexForObjectSize(size), GCInfoTrait<T>::index(),
typeName); | 553 return ThreadHeap::allocateOnArenaIndex(state, size, eagerlySweep ? BlinkGC:
:EagerSweepArenaIndex : ThreadHeap::arenaIndexForObjectSize(size), GCInfoTrait<T
>::index(), typeName); |
| 491 } | 554 } |
| 492 | 555 |
| 493 template<typename T> | 556 template<typename T> |
| 494 Address Heap::reallocate(void* previous, size_t size) | 557 Address ThreadHeap::reallocate(void* previous, size_t size) |
| 495 { | 558 { |
| 496 // Not intended to be a full C realloc() substitute; | 559 // Not intended to be a full C realloc() substitute; |
| 497 // realloc(nullptr, size) is not a supported alias for malloc(size). | 560 // realloc(nullptr, size) is not a supported alias for malloc(size). |
| 498 | 561 |
| 499 // TODO(sof): promptly free the previous object. | 562 // TODO(sof): promptly free the previous object. |
| 500 if (!size) { | 563 if (!size) { |
| 501 // If the new size is 0 this is considered equivalent to free(previous). | 564 // If the new size is 0 this is considered equivalent to free(previous). |
| 502 return nullptr; | 565 return nullptr; |
| 503 } | 566 } |
| 504 | 567 |
| 505 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); | 568 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); |
| 506 HeapObjectHeader* previousHeader = HeapObjectHeader::fromPayload(previous); | 569 HeapObjectHeader* previousHeader = HeapObjectHeader::fromPayload(previous); |
| 507 BasePage* page = pageFromObject(previousHeader); | 570 BasePage* page = pageFromObject(previousHeader); |
| 508 ASSERT(page); | 571 ASSERT(page); |
| 509 int arenaIndex = page->arena()->arenaIndex(); | 572 int arenaIndex = page->arena()->arenaIndex(); |
| 510 // Recompute the effective heap index if previous allocation | 573 // Recompute the effective heap index if previous allocation |
| 511 // was on the normal arenas or a large object. | 574 // was on the normal arenas or a large object. |
| 512 if (isNormalArenaIndex(arenaIndex) || arenaIndex == BlinkGC::LargeObjectAren
aIndex) | 575 if (isNormalArenaIndex(arenaIndex) || arenaIndex == BlinkGC::LargeObjectAren
aIndex) |
| 513 arenaIndex = arenaIndexForObjectSize(size); | 576 arenaIndex = arenaIndexForObjectSize(size); |
| 514 | 577 |
| 515 // TODO(haraken): We don't support reallocate() for finalizable objects. | 578 // TODO(haraken): We don't support reallocate() for finalizable objects. |
| 516 ASSERT(!Heap::gcInfo(previousHeader->gcInfoIndex())->hasFinalizer()); | 579 ASSERT(!ThreadHeap::gcInfo(previousHeader->gcInfoIndex())->hasFinalizer()); |
| 517 ASSERT(previousHeader->gcInfoIndex() == GCInfoTrait<T>::index()); | 580 ASSERT(previousHeader->gcInfoIndex() == GCInfoTrait<T>::index()); |
| 518 const char* typeName = WTF_HEAP_PROFILER_TYPE_NAME(T); | 581 const char* typeName = WTF_HEAP_PROFILER_TYPE_NAME(T); |
| 519 HeapAllocHooks::freeHookIfEnabled(static_cast<Address>(previous)); | 582 HeapAllocHooks::freeHookIfEnabled(static_cast<Address>(previous)); |
| 520 Address address = Heap::allocateOnArenaIndex(state, size, arenaIndex, GCInfo
Trait<T>::index(), typeName); | 583 Address address = ThreadHeap::allocateOnArenaIndex(state, size, arenaIndex,
GCInfoTrait<T>::index(), typeName); |
| 521 size_t copySize = previousHeader->payloadSize(); | 584 size_t copySize = previousHeader->payloadSize(); |
| 522 if (copySize > size) | 585 if (copySize > size) |
| 523 copySize = size; | 586 copySize = size; |
| 524 memcpy(address, previous, copySize); | 587 memcpy(address, previous, copySize); |
| 525 return address; | 588 return address; |
| 526 } | 589 } |
| 527 | 590 |
| 528 template<typename Derived> | 591 template<typename Derived> |
| 529 template<typename T> | 592 template<typename T> |
| 530 void VisitorHelper<Derived>::handleWeakCell(Visitor* self, void* object) | 593 void VisitorHelper<Derived>::handleWeakCell(Visitor* self, void* object) |
| 531 { | 594 { |
| 532 T** cell = reinterpret_cast<T**>(object); | 595 T** cell = reinterpret_cast<T**>(object); |
| 533 if (*cell && !ObjectAliveTrait<T>::isHeapObjectAlive(*cell)) | 596 if (*cell && !ObjectAliveTrait<T>::isHeapObjectAlive(*cell)) |
| 534 *cell = nullptr; | 597 *cell = nullptr; |
| 535 } | 598 } |
| 536 | 599 |
| 537 } // namespace blink | 600 } // namespace blink |
| 538 | 601 |
| 539 #endif // Heap_h | 602 #endif // Heap_h |
| OLD | NEW |