diff options
Diffstat (limited to 'Source/JavaScriptCore/heap/BlockAllocator.cpp')
-rw-r--r-- | Source/JavaScriptCore/heap/BlockAllocator.cpp | 172 |
1 files changed, 0 insertions, 172 deletions
diff --git a/Source/JavaScriptCore/heap/BlockAllocator.cpp b/Source/JavaScriptCore/heap/BlockAllocator.cpp deleted file mode 100644 index 7a7474913..000000000 --- a/Source/JavaScriptCore/heap/BlockAllocator.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "BlockAllocator.h" - -#include "CopiedBlock.h" -#include "CopyWorkList.h" -#include "MarkedBlock.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) - , m_markedRegionSet(MarkedBlock::blockSize) - , m_fourKBBlockRegionSet(WeakBlock::blockSize) - , m_workListRegionSet(CopyWorkListSegment::blockSize) - , m_numberOfEmptyRegions(0) - , m_isCurrentlyAllocating(false) - , m_blockFreeingThreadShouldQuit(false) - , m_blockFreeingThread(createBlockFreeingThread(this)) -{ - m_regionLock.Init(); -} - -BlockAllocator::~BlockAllocator() -{ - releaseFreeRegions(); - { - std::lock_guard<std::mutex> lock(m_emptyRegionConditionMutex); - m_blockFreeingThreadShouldQuit = true; - m_emptyRegionCondition.notify_all(); - } - if (m_blockFreeingThread) - waitForThreadCompletion(m_blockFreeingThread); - ASSERT(allRegionSetsAreEmpty()); - ASSERT(m_emptyRegions.isEmpty()); -} - -bool BlockAllocator::allRegionSetsAreEmpty() const -{ - return m_copiedRegionSet.isEmpty() - && m_markedRegionSet.isEmpty() - && m_fourKBBlockRegionSet.isEmpty() - && m_workListRegionSet.isEmpty(); -} - -void BlockAllocator::releaseFreeRegions() -{ - while (true) { - Region* region; - { - SpinLockHolder locker(&m_regionLock); - if (!m_numberOfEmptyRegions) - region = 0; - else { - region = m_emptyRegions.removeHead(); - RELEASE_ASSERT(region); - m_numberOfEmptyRegions--; - } - } - - if (!region) - break; - - region->destroy(); - } -} - -void BlockAllocator::waitForDuration(std::chrono::milliseconds duration) -{ - std::unique_lock<std::mutex> lock(m_emptyRegionConditionMutex); - - // 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. - if (m_blockFreeingThreadShouldQuit) - return; - - m_emptyRegionCondition.wait_for(lock, duration); -} - -void BlockAllocator::blockFreeingThreadStartFunc(void* blockAllocator) -{ - static_cast<BlockAllocator*>(blockAllocator)->blockFreeingThreadMain(); -} - -void BlockAllocator::blockFreeingThreadMain() -{ - size_t currentNumberOfEmptyRegions; - while (!m_blockFreeingThreadShouldQuit) { - // Generally wait for one second before scavenging free blocks. This - // may return early, particularly when we're being asked to quit. - waitForDuration(std::chrono::seconds(1)); - if (m_blockFreeingThreadShouldQuit) - break; - - if (m_isCurrentlyAllocating) { - m_isCurrentlyAllocating = false; - continue; - } - - // Sleep until there is actually work to do rather than waking up every second to check. - { - std::unique_lock<std::mutex> lock(m_emptyRegionConditionMutex); - SpinLockHolder regionLocker(&m_regionLock); - while (!m_numberOfEmptyRegions && !m_blockFreeingThreadShouldQuit) { - m_regionLock.Unlock(); - m_emptyRegionCondition.wait(lock); - m_regionLock.Lock(); - } - currentNumberOfEmptyRegions = m_numberOfEmptyRegions; - } - - size_t desiredNumberOfEmptyRegions = currentNumberOfEmptyRegions / 2; - - while (!m_blockFreeingThreadShouldQuit) { - Region* region; - { - SpinLockHolder locker(&m_regionLock); - if (m_numberOfEmptyRegions <= desiredNumberOfEmptyRegions) - region = 0; - else { - region = m_emptyRegions.removeHead(); - RELEASE_ASSERT(region); - m_numberOfEmptyRegions--; - } - } - - if (!region) - break; - - region->destroy(); - } - } -} - -} // namespace JSC |