]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - heap/BlockAllocator.cpp
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / heap / BlockAllocator.cpp
index 211fb99734d40e3f404d3af3d65aa8a0e875f47f..bf408f8ef0ad024e338068041a31c4f2751aaa04 100644 (file)
 #include "CopiedBlock.h"
 #include "CopyWorkList.h"
 #include "MarkedBlock.h"
+#include "JSCInlines.h"
 #include "WeakBlock.h"
 #include <wtf/CurrentTime.h>
 
 namespace JSC {
 
+inline ThreadIdentifier createBlockFreeingThread(BlockAllocator* allocator)
+{
+    if (!GCActivityCallback::s_shouldCreateGCTimer)
+        return 0; // No block freeing thread.
+    ThreadIdentifier identifier = createThread(allocator->blockFreeingThreadStartFunc, allocator, "JavaScriptCore::BlockFree");
+    RELEASE_ASSERT(identifier);
+    return identifier;
+}
+
 BlockAllocator::BlockAllocator()
     : m_superRegion()
     , m_copiedRegionSet(CopiedBlock::blockSize)
@@ -43,18 +53,8 @@ BlockAllocator::BlockAllocator()
     , m_numberOfEmptyRegions(0)
     , m_isCurrentlyAllocating(false)
     , m_blockFreeingThreadShouldQuit(false)
-#if PLATFORM(IOS)
-    , m_blockFreeingThread(GCActivityCallback::s_shouldCreateGCTimer ?
-        createThread(blockFreeingThreadStartFunc, this, "JavaScriptCore::BlockFree") : 0)
-#else
-    , m_blockFreeingThread(createThread(blockFreeingThreadStartFunc, this, "JavaScriptCore::BlockFree"))
-#endif
+    , m_blockFreeingThread(createBlockFreeingThread(this))
 {
-#if PLATFORM(IOS)
-    RELEASE_ASSERT(m_blockFreeingThread || !GCActivityCallback::s_shouldCreateGCTimer);
-#else
-    RELEASE_ASSERT(m_blockFreeingThread);
-#endif
     m_regionLock.Init();
 }
 
@@ -62,16 +62,12 @@ BlockAllocator::~BlockAllocator()
 {
     releaseFreeRegions();
     {
-        MutexLocker locker(m_emptyRegionConditionLock);
+        std::lock_guard<std::mutex> lock(m_emptyRegionConditionMutex);
         m_blockFreeingThreadShouldQuit = true;
-        m_emptyRegionCondition.broadcast();
+        m_emptyRegionCondition.notify_all();
     }
-#if PLATFORM(IOS)
-    if (GCActivityCallback::s_shouldCreateGCTimer)
+    if (m_blockFreeingThread)
         waitForThreadCompletion(m_blockFreeingThread);
-#else
-    waitForThreadCompletion(m_blockFreeingThread);
-#endif
     ASSERT(allRegionSetsAreEmpty());
     ASSERT(m_emptyRegions.isEmpty());
 }
@@ -106,22 +102,17 @@ void BlockAllocator::releaseFreeRegions()
     }
 }
 
-void BlockAllocator::waitForRelativeTimeWhileHoldingLock(double relative)
+void BlockAllocator::waitForDuration(std::chrono::milliseconds duration)
 {
-    if (m_blockFreeingThreadShouldQuit)
-        return;
+    std::unique_lock<std::mutex> lock(m_emptyRegionConditionMutex);
 
-    m_emptyRegionCondition.timedWait(m_emptyRegionConditionLock, currentTime() + relative);
-}
-
-void BlockAllocator::waitForRelativeTime(double relative)
-{
     // If this returns early, that's fine, so long as it doesn't do it too
     // frequently. It would only be a bug if this function failed to return
     // when it was asked to do so.
-    
-    MutexLocker locker(m_emptyRegionConditionLock);
-    waitForRelativeTimeWhileHoldingLock(relative);
+    if (m_blockFreeingThreadShouldQuit)
+        return;
+
+    m_emptyRegionCondition.wait_for(lock, duration);
 }
 
 void BlockAllocator::blockFreeingThreadStartFunc(void* blockAllocator)
@@ -135,7 +126,7 @@ void BlockAllocator::blockFreeingThreadMain()
     while (!m_blockFreeingThreadShouldQuit) {
         // Generally wait for one second before scavenging free blocks. This
         // may return early, particularly when we're being asked to quit.
-        waitForRelativeTime(1.0);
+        waitForDuration(std::chrono::seconds(1));
         if (m_blockFreeingThreadShouldQuit)
             break;
         
@@ -146,11 +137,11 @@ void BlockAllocator::blockFreeingThreadMain()
 
         // Sleep until there is actually work to do rather than waking up every second to check.
         {
-            MutexLocker locker(m_emptyRegionConditionLock);
+            std::unique_lock<std::mutex> lock(m_emptyRegionConditionMutex);
             SpinLockHolder regionLocker(&m_regionLock);
             while (!m_numberOfEmptyRegions && !m_blockFreeingThreadShouldQuit) {
                 m_regionLock.Unlock();
-                m_emptyRegionCondition.wait(m_emptyRegionConditionLock);
+                m_emptyRegionCondition.wait(lock);
                 m_regionLock.Lock();
             }
             currentNumberOfEmptyRegions = m_numberOfEmptyRegions;