Changeset 92084 in webkit
- Timestamp:
- Jul 31, 2011 12:03:51 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r92071 r92084 1 2011-07-31 Filip Pizlo <fpizlo@apple.com> 2 3 The JSC garbage collector returns memory to the operating system too 4 eagerly. 5 https://bugs.webkit.org/show_bug.cgi?id=65382 6 7 Reviewed by Oliver Hunt. 8 9 This introduces a memory reuse model similar to the one in FastMalloc. 10 A periodic scavenger thread runs in the background and returns half the 11 free memory to the OS on each timer fire. New block allocations first 12 attempt to get the memory from the collector's internal pool, reverting 13 to OS allocation only when this pool is empty. 14 15 * heap/Heap.cpp: 16 (JSC::Heap::Heap): 17 (JSC::Heap::~Heap): 18 (JSC::Heap::destroy): 19 (JSC::Heap::waitForRelativeTimeWhileHoldingLock): 20 (JSC::Heap::waitForRelativeTime): 21 (JSC::Heap::blockFreeingThreadStartFunc): 22 (JSC::Heap::blockFreeingThreadMain): 23 (JSC::Heap::allocateBlock): 24 (JSC::Heap::freeBlocks): 25 (JSC::Heap::releaseFreeBlocks): 26 * heap/Heap.h: 27 * heap/MarkedBlock.cpp: 28 (JSC::MarkedBlock::destroy): 29 (JSC::MarkedBlock::MarkedBlock): 30 (JSC::MarkedBlock::initForCellSize): 31 (JSC::MarkedBlock::reset): 32 * heap/MarkedBlock.h: 33 * wtf/Platform.h: 34 1 35 2011-07-30 Filip Pizlo <fpizlo@apple.com> 2 36 -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r92046 r92084 245 245 m_newSpace.setHighWaterMark(minBytesPerCycle); 246 246 (*m_activityCallback)(); 247 #if ENABLE(LAZY_BLOCK_FREEING) 248 m_numberOfFreeBlocks = 0; 249 m_blockFreeingThread = createThread(blockFreeingThreadStartFunc, this, "JavaScriptCore::BlockFree"); 250 ASSERT(m_blockFreeingThread); 251 #endif 247 252 } 248 253 249 254 Heap::~Heap() 250 255 { 256 #if ENABLE(LAZY_BLOCK_FREEING) 257 // destroy our thread 258 { 259 MutexLocker locker(m_freeBlockLock); 260 m_blockFreeingThreadShouldQuit = true; 261 m_freeBlockCondition.broadcast(); 262 } 263 waitForThreadCompletion(m_blockFreeingThread, 0); 264 #endif 265 251 266 // The destroy function must already have been called, so assert this. 252 267 ASSERT(!m_globalData); … … 280 295 shrink(); 281 296 ASSERT(!size()); 297 298 #if ENABLE(LAZY_BLOCK_FREEING) 299 releaseFreeBlocks(); 300 #endif 282 301 283 302 m_globalData = 0; 284 303 } 304 305 #if ENABLE(LAZY_BLOCK_FREEING) 306 void Heap::waitForRelativeTimeWhileHoldingLock(double relative) 307 { 308 if (m_blockFreeingThreadShouldQuit) 309 return; 310 m_freeBlockCondition.timedWait(m_freeBlockLock, currentTime() + relative); 311 } 312 313 void Heap::waitForRelativeTime(double relative) 314 { 315 // If this returns early, that's fine, so long as it doesn't do it too 316 // frequently. It would only be a bug if this function failed to return 317 // when it was asked to do so. 318 319 MutexLocker locker(m_freeBlockLock); 320 waitForRelativeTimeWhileHoldingLock(relative); 321 } 322 323 void* Heap::blockFreeingThreadStartFunc(void* heap) 324 { 325 static_cast<Heap*>(heap)->blockFreeingThreadMain(); 326 return 0; 327 } 328 329 void Heap::blockFreeingThreadMain() 330 { 331 while (!m_blockFreeingThreadShouldQuit) { 332 // Generally wait for one second before scavenging free blocks. This 333 // may return early, particularly when we're being asked to quit. 334 waitForRelativeTime(1.0); 335 if (m_blockFreeingThreadShouldQuit) 336 break; 337 338 // Now process the list of free blocks. Keep freeing until half of the 339 // blocks that are currently on the list are gone. Assume that a size_t 340 // field can be accessed atomically. 341 size_t currentNumberOfFreeBlocks = m_numberOfFreeBlocks; 342 if (!currentNumberOfFreeBlocks) 343 continue; 344 345 size_t desiredNumberOfFreeBlocks = currentNumberOfFreeBlocks / 2; 346 347 while (!m_blockFreeingThreadShouldQuit) { 348 MarkedBlock* block; 349 { 350 MutexLocker locker(m_freeBlockLock); 351 if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks) 352 block = 0; 353 else { 354 block = m_freeBlocks.removeHead(); 355 ASSERT(block); 356 m_numberOfFreeBlocks--; 357 } 358 } 359 360 if (!block) 361 break; 362 363 MarkedBlock::destroy(block); 364 } 365 } 366 } 367 #endif // ENABLE(LAZY_BLOCK_FREEING) 285 368 286 369 void Heap::reportExtraMemoryCostSlowCase(size_t cost) … … 614 697 MarkedBlock* Heap::allocateBlock(size_t cellSize) 615 698 { 616 MarkedBlock* block = MarkedBlock::create(this, cellSize); 699 MarkedBlock* block; 700 701 #if !ENABLE(LAZY_BLOCK_FREEING) 702 block = MarkedBlock::create(this, cellSize); 703 #else 704 { 705 MutexLocker locker(m_freeBlockLock); 706 if (m_numberOfFreeBlocks) { 707 block = m_freeBlocks.removeHead(); 708 ASSERT(block); 709 m_numberOfFreeBlocks--; 710 } else 711 block = 0; 712 } 713 if (block) 714 block->initForCellSize(cellSize); 715 else 716 block = MarkedBlock::create(this, cellSize); 717 #endif 718 617 719 m_blocks.add(block); 618 720 … … 627 729 628 730 m_blocks.remove(block); 731 block->reset(); 732 #if !ENABLE(LAZY_BLOCK_FREEING) 629 733 MarkedBlock::destroy(block); 734 #else 735 MutexLocker locker(m_freeBlockLock); 736 m_freeBlocks.append(block); 737 m_numberOfFreeBlocks++; 738 #endif 630 739 } 631 740 } … … 638 747 } 639 748 749 #if ENABLE(LAZY_BLOCK_FREEING) 750 void Heap::releaseFreeBlocks() 751 { 752 while (true) { 753 MarkedBlock* block; 754 { 755 MutexLocker locker(m_freeBlockLock); 756 if (!m_numberOfFreeBlocks) 757 block = 0; 758 else { 759 block = m_freeBlocks.removeHead(); 760 ASSERT(block); 761 m_numberOfFreeBlocks--; 762 } 763 } 764 765 if (!block) 766 break; 767 768 MarkedBlock::destroy(block); 769 } 770 } 771 #endif 772 640 773 #if ENABLE(GGC) 641 774 void Heap::writeBarrierSlowCase(const JSCell* owner, JSCell* cell) -
trunk/Source/JavaScriptCore/heap/Heap.h
r91199 r92084 53 53 54 54 enum OperationInProgress { NoOperation, Allocation, Collection }; 55 55 56 56 class Heap { 57 57 WTF_MAKE_NONCOPYABLE(Heap); … … 145 145 void collect(SweepToggle); 146 146 void shrink(); 147 void releaseFreeBlocks(); 147 148 void sweep(); 148 149 … … 150 151 151 152 static void writeBarrierSlowCase(const JSCell*, JSCell*); 153 154 #if ENABLE(LAZY_BLOCK_FREEING) 155 void waitForRelativeTimeWhileHoldingLock(double relative); 156 void waitForRelativeTime(double relative); 157 void blockFreeingThreadMain(); 158 static void* blockFreeingThreadStartFunc(void* heap); 159 #endif 152 160 153 161 OperationInProgress m_operationInProgress; 154 162 NewSpace m_newSpace; 155 163 MarkedBlockSet m_blocks; 164 165 #if ENABLE(LAZY_BLOCK_FREEING) 166 DoublyLinkedList<MarkedBlock> m_freeBlocks; 167 size_t m_numberOfFreeBlocks; 168 169 ThreadIdentifier m_blockFreeingThread; 170 Mutex m_freeBlockLock; 171 ThreadCondition m_freeBlockCondition; 172 bool m_blockFreeingThreadShouldQuit; 173 #endif 156 174 157 175 size_t m_extraCost; -
trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp
r92046 r92084 43 43 void MarkedBlock::destroy(MarkedBlock* block) 44 44 { 45 for (size_t i = block->firstAtom(); i < block->m_endAtom; i += block->m_atomsPerCell)46 reinterpret_cast<JSCell*>(&block->atoms()[i])->~JSCell();47 45 block->m_allocation.deallocate(); 48 46 } … … 53 51 , m_heap(heap) 54 52 { 53 initForCellSize(cellSize); 54 } 55 56 void MarkedBlock::initForCellSize(size_t cellSize) 57 { 55 58 m_atomsPerCell = (cellSize + atomSize - 1) / atomSize; 56 59 m_endAtom = atomsPerBlock - m_atomsPerCell + 1; 60 } 61 62 void MarkedBlock::reset() 63 { 64 for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) 65 reinterpret_cast<JSCell*>(&atoms()[i])->~JSCell(); 57 66 } 58 67 -
trunk/Source/JavaScriptCore/heap/MarkedBlock.h
r92046 r92084 95 95 FreeCell* lazySweep(); 96 96 97 void initForCellSize(size_t cellSize); 98 97 99 // These should be called immediately after a block is created. 98 100 // Blessing for fast path creates a linked list, while blessing for … … 100 102 FreeCell* blessNewBlockForFastPath(); 101 103 void blessNewBlockForSlowPath(); 104 105 void reset(); 102 106 103 107 // This unmarks all cells on the free list, and allocates dummy JSCells -
trunk/Source/JavaScriptCore/wtf/Platform.h
r92046 r92084 1106 1106 #endif 1107 1107 1108 #if ENABLE(SINGLE_THREADED) 1109 #undef ENABLE_LAZY_BLOCK_FREEING 1110 #define ENABLE_LAZY_BLOCK_FREEING 0 1111 #else 1112 #define ENABLE_LAZY_BLOCK_FREEING 1 1113 #endif 1114 1108 1115 #if !defined(ENABLE_PAN_SCROLLING) && OS(WINDOWS) 1109 1116 #define ENABLE_PAN_SCROLLING 1
Note: See TracChangeset
for help on using the changeset viewer.