Ignore:
Timestamp:
Apr 28, 2012, 6:44:37 PM (13 years ago)
Author:
[email protected]
Message:

Factored threaded block allocation into a separate object
https://bugs.webkit.org/show_bug.cgi?id=85148

Reviewed by Sam Weinig.

99% of this patch just moves duplicated block allocation and
deallocation code into a new object named BlockAllocator, with these
exceptions:

  • heap/BlockAllocator.h: Added.

(BlockAllocator::BlockAllocator): The order of declarations here now
guards us against an unlikely race condition during startup.

  • heap/BlockAllocator.cpp:

JSC::BlockAllocator::blockFreeingThreadMain): Added a FIXME to
highlight a lack of clarity we have in our block deallocation routines.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r115586 r115590  
    320320    , m_objectSpace(this)
    321321    , m_storageSpace(this)
    322     , m_blockFreeingThreadShouldQuit(false)
    323322    , m_markListSet(0)
    324323    , m_activityCallback(DefaultGCActivityCallback::create(this))
     
    333332    , m_lastCodeDiscardTime(WTF::currentTime())
    334333{
    335     m_numberOfFreeBlocks = 0;
    336     m_blockFreeingThread = createThread(blockFreeingThreadStartFunc, this, "JavaScriptCore::BlockFree");
    337    
    338     ASSERT(m_blockFreeingThread);
    339334    m_storageSpace.init();
    340335}
     
    346341    m_objectSpace.shrink();
    347342    m_storageSpace.freeAllBlocks();
    348     releaseFreeBlocks();
    349     {
    350         MutexLocker locker(m_freeBlockLock);
    351         m_blockFreeingThreadShouldQuit = true;
    352         m_freeBlockCondition.broadcast();
    353     }
    354     waitForThreadCompletion(m_blockFreeingThread);
    355343
    356344    ASSERT(!size());
     
    379367    m_destroyedTypeCounts.dump(WTF::dataFile(), "Destroyed Type Counts");
    380368#endif
    381 }
    382 
    383 void Heap::waitForRelativeTimeWhileHoldingLock(double relative)
    384 {
    385     if (m_blockFreeingThreadShouldQuit)
    386         return;
    387     m_freeBlockCondition.timedWait(m_freeBlockLock, currentTime() + relative);
    388 }
    389 
    390 void Heap::waitForRelativeTime(double relative)
    391 {
    392     // If this returns early, that's fine, so long as it doesn't do it too
    393     // frequently. It would only be a bug if this function failed to return
    394     // when it was asked to do so.
    395    
    396     MutexLocker locker(m_freeBlockLock);
    397     waitForRelativeTimeWhileHoldingLock(relative);
    398 }
    399 
    400 void Heap::blockFreeingThreadStartFunc(void* heap)
    401 {
    402     static_cast<Heap*>(heap)->blockFreeingThreadMain();
    403 }
    404 
    405 void Heap::blockFreeingThreadMain()
    406 {
    407     while (!m_blockFreeingThreadShouldQuit) {
    408         // Generally wait for one second before scavenging free blocks. This
    409         // may return early, particularly when we're being asked to quit.
    410         waitForRelativeTime(1.0);
    411         if (m_blockFreeingThreadShouldQuit)
    412             break;
    413        
    414         // Now process the list of free blocks. Keep freeing until half of the
    415         // blocks that are currently on the list are gone. Assume that a size_t
    416         // field can be accessed atomically.
    417         size_t currentNumberOfFreeBlocks = m_numberOfFreeBlocks;
    418         if (!currentNumberOfFreeBlocks)
    419             continue;
    420        
    421         size_t desiredNumberOfFreeBlocks = currentNumberOfFreeBlocks / 2;
    422        
    423         while (!m_blockFreeingThreadShouldQuit) {
    424             MarkedBlock* block;
    425             {
    426                 MutexLocker locker(m_freeBlockLock);
    427                 if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks)
    428                     block = 0;
    429                 else {
    430                     block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead());
    431                     ASSERT(block);
    432                     m_numberOfFreeBlocks--;
    433                 }
    434             }
    435            
    436             if (!block)
    437                 break;
    438            
    439             MarkedBlock::destroy(block);
    440         }
    441     }
    442369}
    443370
     
    913840}
    914841
    915 void Heap::freeBlocks(MarkedBlock* head)
    916 {
    917     m_objectSpace.freeBlocks(head);
    918 }
    919 
    920 void Heap::releaseFreeBlocks()
    921 {
    922     while (true) {
    923         MarkedBlock* block;
    924         {
    925             MutexLocker locker(m_freeBlockLock);
    926             if (!m_numberOfFreeBlocks)
    927                 block = 0;
    928             else {
    929                 block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead());
    930                 ASSERT(block);
    931                 m_numberOfFreeBlocks--;
    932             }
    933         }
    934        
    935         if (!block)
    936             break;
    937        
    938         MarkedBlock::destroy(block);
    939     }
    940 }
    941 
    942842void Heap::addFinalizer(JSCell* cell, Finalizer finalizer)
    943843{
Note: See TracChangeset for help on using the changeset viewer.