From 470286ecfe79d59df14944e5b5d34630fc739391 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 22 Nov 2012 09:09:45 +0100 Subject: Imported WebKit commit e89504fa9195b2063b2530961d4b73dd08de3242 (http://svn.webkit.org/repository/webkit/trunk@135485) Change-Id: I03774e5ac79721c13ffa30d152537a74d0b12e66 Reviewed-by: Simon Hausmann --- Source/JavaScriptCore/heap/BlockAllocator.cpp | 2 +- Source/JavaScriptCore/heap/BlockAllocator.h | 20 ++- Source/JavaScriptCore/heap/ConservativeRoots.cpp | 4 +- Source/JavaScriptCore/heap/CopiedBlock.h | 2 +- Source/JavaScriptCore/heap/CopiedSpace.cpp | 2 +- .../JavaScriptCore/heap/CopiedSpaceInlineMethods.h | 185 -------------------- Source/JavaScriptCore/heap/CopiedSpaceInlines.h | 186 +++++++++++++++++++++ Source/JavaScriptCore/heap/CopyVisitor.cpp | 2 +- .../JavaScriptCore/heap/CopyVisitorInlineMethods.h | 119 ------------- Source/JavaScriptCore/heap/CopyVisitorInlines.h | 120 +++++++++++++ Source/JavaScriptCore/heap/GCThread.cpp | 2 +- Source/JavaScriptCore/heap/GCThreadSharedData.cpp | 7 +- Source/JavaScriptCore/heap/GCThreadSharedData.h | 2 - Source/JavaScriptCore/heap/HandleStack.cpp | 2 +- Source/JavaScriptCore/heap/Heap.cpp | 8 +- Source/JavaScriptCore/heap/Heap.h | 2 + Source/JavaScriptCore/heap/HeapRootVisitor.h | 2 +- Source/JavaScriptCore/heap/HeapStatistics.cpp | 38 ++--- Source/JavaScriptCore/heap/HeapStatistics.h | 4 +- Source/JavaScriptCore/heap/JITStubRoutineSet.h | 3 + Source/JavaScriptCore/heap/MarkStack.cpp | 154 ++++++----------- Source/JavaScriptCore/heap/MarkStack.h | 59 ++++--- .../JavaScriptCore/heap/MarkStackInlineMethods.h | 113 ------------- Source/JavaScriptCore/heap/MarkStackInlines.h | 119 +++++++++++++ Source/JavaScriptCore/heap/MarkedBlock.h | 2 +- Source/JavaScriptCore/heap/SlotVisitor.cpp | 11 +- Source/JavaScriptCore/heap/SlotVisitor.h | 5 +- .../JavaScriptCore/heap/SlotVisitorInlineMethods.h | 174 ------------------- Source/JavaScriptCore/heap/SlotVisitorInlines.h | 183 ++++++++++++++++++++ Source/JavaScriptCore/heap/Weak.h | 5 + 30 files changed, 763 insertions(+), 774 deletions(-) delete mode 100644 Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h create mode 100644 Source/JavaScriptCore/heap/CopiedSpaceInlines.h delete mode 100644 Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h create mode 100644 Source/JavaScriptCore/heap/CopyVisitorInlines.h delete mode 100644 Source/JavaScriptCore/heap/MarkStackInlineMethods.h create mode 100644 Source/JavaScriptCore/heap/MarkStackInlines.h delete mode 100644 Source/JavaScriptCore/heap/SlotVisitorInlineMethods.h create mode 100644 Source/JavaScriptCore/heap/SlotVisitorInlines.h (limited to 'Source/JavaScriptCore/heap') diff --git a/Source/JavaScriptCore/heap/BlockAllocator.cpp b/Source/JavaScriptCore/heap/BlockAllocator.cpp index daba93805..2d7b57f9a 100644 --- a/Source/JavaScriptCore/heap/BlockAllocator.cpp +++ b/Source/JavaScriptCore/heap/BlockAllocator.cpp @@ -36,7 +36,7 @@ namespace JSC { BlockAllocator::BlockAllocator() : m_copiedRegionSet(CopiedBlock::blockSize) , m_markedRegionSet(MarkedBlock::blockSize) - , m_weakRegionSet(WeakBlock::blockSize) + , m_weakAndMarkStackRegionSet(WeakBlock::blockSize) , m_numberOfEmptyRegions(0) , m_isCurrentlyAllocating(false) , m_blockFreeingThreadShouldQuit(false) diff --git a/Source/JavaScriptCore/heap/BlockAllocator.h b/Source/JavaScriptCore/heap/BlockAllocator.h index f8ce39530..75c59b783 100644 --- a/Source/JavaScriptCore/heap/BlockAllocator.h +++ b/Source/JavaScriptCore/heap/BlockAllocator.h @@ -37,6 +37,7 @@ namespace JSC { class BlockAllocator; class CopiedBlock; +class MarkStackSegment; class MarkedBlock; class Region; class WeakBlock; @@ -185,7 +186,8 @@ private: RegionSet m_copiedRegionSet; RegionSet m_markedRegionSet; - RegionSet m_weakRegionSet; + // WeakBlocks and MarkStackSegments use the same RegionSet since they're the same size. + RegionSet m_weakAndMarkStackRegionSet; DoublyLinkedList m_emptyRegions; size_t m_numberOfEmptyRegions; @@ -315,7 +317,13 @@ inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor() template <> inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor() { - return m_weakRegionSet; + return m_weakAndMarkStackRegionSet; +} + +template <> +inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor() +{ + return m_weakAndMarkStackRegionSet; } template <> @@ -333,7 +341,13 @@ inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor >() { - return m_weakRegionSet; + return m_weakAndMarkStackRegionSet; +} + +template <> +inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor >() +{ + return m_weakAndMarkStackRegionSet; } template diff --git a/Source/JavaScriptCore/heap/ConservativeRoots.cpp b/Source/JavaScriptCore/heap/ConservativeRoots.cpp index 7fe22dfff..752ce2775 100644 --- a/Source/JavaScriptCore/heap/ConservativeRoots.cpp +++ b/Source/JavaScriptCore/heap/ConservativeRoots.cpp @@ -26,9 +26,9 @@ #include "config.h" #include "ConservativeRoots.h" -#include "CopiedSpace.h" -#include "CopiedSpaceInlineMethods.h" #include "CodeBlock.h" +#include "CopiedSpace.h" +#include "CopiedSpaceInlines.h" #include "DFGCodeBlocks.h" #include "JSCell.h" #include "JSObject.h" diff --git a/Source/JavaScriptCore/heap/CopiedBlock.h b/Source/JavaScriptCore/heap/CopiedBlock.h index af36f55df..83fdb08da 100644 --- a/Source/JavaScriptCore/heap/CopiedBlock.h +++ b/Source/JavaScriptCore/heap/CopiedBlock.h @@ -29,7 +29,7 @@ #include "BlockAllocator.h" #include "HeapBlock.h" #include "JSValue.h" -#include "JSValueInlineMethods.h" +#include "JSValueInlines.h" #include "Options.h" #include diff --git a/Source/JavaScriptCore/heap/CopiedSpace.cpp b/Source/JavaScriptCore/heap/CopiedSpace.cpp index c228f9460..e4141c1d7 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.cpp +++ b/Source/JavaScriptCore/heap/CopiedSpace.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "CopiedSpace.h" -#include "CopiedSpaceInlineMethods.h" +#include "CopiedSpaceInlines.h" #include "GCActivityCallback.h" #include "Options.h" diff --git a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h deleted file mode 100644 index c244015e7..000000000 --- a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2011 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. ``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 - * 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. - */ - -#ifndef CopiedSpaceInlineMethods_h -#define CopiedSpaceInlineMethods_h - -#include "CopiedBlock.h" -#include "CopiedSpace.h" -#include "Heap.h" -#include "HeapBlock.h" -#include "JSGlobalData.h" -#include - -namespace JSC { - -inline bool CopiedSpace::contains(CopiedBlock* block) -{ - return !m_blockFilter.ruleOut(reinterpret_cast(block)) && m_blockSet.contains(block); -} - -inline bool CopiedSpace::contains(void* ptr, CopiedBlock*& result) -{ - CopiedBlock* block = blockFor(ptr); - if (contains(block)) { - result = block; - return true; - } - block = oversizeBlockFor(ptr); - result = block; - return contains(block); -} - -inline void CopiedSpace::pin(CopiedBlock* block) -{ - block->m_isPinned = true; -} - -inline void CopiedSpace::pinIfNecessary(void* opaquePointer) -{ - // Pointers into the copied space come in the following varieties: - // 1) Pointers to the start of a span of memory. This is the most - // natural though not necessarily the most common. - // 2) Pointers to one value-sized (8 byte) word past the end of - // a span of memory. This currently occurs with semi-butterflies - // and should be fixed soon, once the other half of the - // butterfly lands. - // 3) Pointers to the innards arising from loop induction variable - // optimizations (either manual ones or automatic, by the - // compiler). - // 4) Pointers to the end of a span of memory in arising from - // induction variable optimizations combined with the - // GC-to-compiler contract laid out in the C spec: a pointer to - // the end of a span of memory must be considered to be a - // pointer to that memory. - - EncodedJSValue* pointer = reinterpret_cast(opaquePointer); - CopiedBlock* block; - - // Handle (1) and (3). - if (contains(pointer, block)) - pin(block); - - // Handle (4). We don't have to explicitly check and pin the block under this - // pointer because it cannot possibly point to something that cases (1) and - // (3) above or case (2) below wouldn't already catch. - pointer--; - - // Handle (2) - pointer--; - if (contains(pointer, block)) - pin(block); -} - -inline void CopiedSpace::recycleEvacuatedBlock(CopiedBlock* block) -{ - ASSERT(block); - ASSERT(block->canBeRecycled()); - ASSERT(!block->m_isPinned); - { - SpinLockHolder locker(&m_toSpaceLock); - m_blockSet.remove(block); - m_fromSpace->remove(block); - } - m_heap->blockAllocator().deallocate(CopiedBlock::destroy(block)); -} - -inline void CopiedSpace::recycleBorrowedBlock(CopiedBlock* block) -{ - m_heap->blockAllocator().deallocate(CopiedBlock::destroy(block)); - - { - MutexLocker locker(m_loanedBlocksLock); - ASSERT(m_numberOfLoanedBlocks > 0); - ASSERT(m_inCopyingPhase); - m_numberOfLoanedBlocks--; - if (!m_numberOfLoanedBlocks) - m_loanedBlocksCondition.signal(); - } -} - -inline CopiedBlock* CopiedSpace::allocateBlockForCopyingPhase() -{ - ASSERT(m_inCopyingPhase); - CopiedBlock* block = CopiedBlock::createNoZeroFill(m_heap->blockAllocator().allocate()); - - { - MutexLocker locker(m_loanedBlocksLock); - m_numberOfLoanedBlocks++; - } - - ASSERT(!block->dataSize()); - return block; -} - -inline void CopiedSpace::allocateBlock() -{ - if (m_heap->shouldCollect()) - m_heap->collect(Heap::DoNotSweep); - - m_allocator.resetCurrentBlock(); - - CopiedBlock* block = CopiedBlock::create(m_heap->blockAllocator().allocate()); - - m_toSpace->push(block); - m_blockFilter.add(reinterpret_cast(block)); - m_blockSet.add(block); - m_allocator.setCurrentBlock(block); -} - -inline CheckedBoolean CopiedSpace::tryAllocate(size_t bytes, void** outPtr) -{ - ASSERT(!m_heap->globalData()->isInitializingObject()); - - if (isOversize(bytes) || !m_allocator.tryAllocate(bytes, outPtr)) - return tryAllocateSlowCase(bytes, outPtr); - - ASSERT(*outPtr); - return true; -} - -inline bool CopiedSpace::isOversize(size_t bytes) -{ - return bytes > s_maxAllocationSize; -} - -inline bool CopiedSpace::isPinned(void* ptr) -{ - return blockFor(ptr)->m_isPinned; -} - -inline CopiedBlock* CopiedSpace::oversizeBlockFor(void* ptr) -{ - return reinterpret_cast(reinterpret_cast(ptr) & WTF::pageMask()); -} - -inline CopiedBlock* CopiedSpace::blockFor(void* ptr) -{ - return reinterpret_cast(reinterpret_cast(ptr) & s_blockMask); -} - -} // namespace JSC - -#endif diff --git a/Source/JavaScriptCore/heap/CopiedSpaceInlines.h b/Source/JavaScriptCore/heap/CopiedSpaceInlines.h new file mode 100644 index 000000000..9d222f549 --- /dev/null +++ b/Source/JavaScriptCore/heap/CopiedSpaceInlines.h @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2011 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. ``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 + * 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. + */ + +#ifndef CopiedSpaceInlines_h +#define CopiedSpaceInlines_h + +#include "CopiedBlock.h" +#include "CopiedSpace.h" +#include "Heap.h" +#include "HeapBlock.h" +#include "JSGlobalData.h" +#include + +namespace JSC { + +inline bool CopiedSpace::contains(CopiedBlock* block) +{ + return !m_blockFilter.ruleOut(reinterpret_cast(block)) && m_blockSet.contains(block); +} + +inline bool CopiedSpace::contains(void* ptr, CopiedBlock*& result) +{ + CopiedBlock* block = blockFor(ptr); + if (contains(block)) { + result = block; + return true; + } + block = oversizeBlockFor(ptr); + result = block; + return contains(block); +} + +inline void CopiedSpace::pin(CopiedBlock* block) +{ + block->m_isPinned = true; +} + +inline void CopiedSpace::pinIfNecessary(void* opaquePointer) +{ + // Pointers into the copied space come in the following varieties: + // 1) Pointers to the start of a span of memory. This is the most + // natural though not necessarily the most common. + // 2) Pointers to one value-sized (8 byte) word past the end of + // a span of memory. This currently occurs with semi-butterflies + // and should be fixed soon, once the other half of the + // butterfly lands. + // 3) Pointers to the innards arising from loop induction variable + // optimizations (either manual ones or automatic, by the + // compiler). + // 4) Pointers to the end of a span of memory in arising from + // induction variable optimizations combined with the + // GC-to-compiler contract laid out in the C spec: a pointer to + // the end of a span of memory must be considered to be a + // pointer to that memory. + + EncodedJSValue* pointer = reinterpret_cast(opaquePointer); + CopiedBlock* block; + + // Handle (1) and (3). + if (contains(pointer, block)) + pin(block); + + // Handle (4). We don't have to explicitly check and pin the block under this + // pointer because it cannot possibly point to something that cases (1) and + // (3) above or case (2) below wouldn't already catch. + pointer--; + + // Handle (2) + pointer--; + if (contains(pointer, block)) + pin(block); +} + +inline void CopiedSpace::recycleEvacuatedBlock(CopiedBlock* block) +{ + ASSERT(block); + ASSERT(block->canBeRecycled()); + ASSERT(!block->m_isPinned); + { + SpinLockHolder locker(&m_toSpaceLock); + m_blockSet.remove(block); + m_fromSpace->remove(block); + } + m_heap->blockAllocator().deallocate(CopiedBlock::destroy(block)); +} + +inline void CopiedSpace::recycleBorrowedBlock(CopiedBlock* block) +{ + m_heap->blockAllocator().deallocate(CopiedBlock::destroy(block)); + + { + MutexLocker locker(m_loanedBlocksLock); + ASSERT(m_numberOfLoanedBlocks > 0); + ASSERT(m_inCopyingPhase); + m_numberOfLoanedBlocks--; + if (!m_numberOfLoanedBlocks) + m_loanedBlocksCondition.signal(); + } +} + +inline CopiedBlock* CopiedSpace::allocateBlockForCopyingPhase() +{ + ASSERT(m_inCopyingPhase); + CopiedBlock* block = CopiedBlock::createNoZeroFill(m_heap->blockAllocator().allocate()); + + { + MutexLocker locker(m_loanedBlocksLock); + m_numberOfLoanedBlocks++; + } + + ASSERT(!block->dataSize()); + return block; +} + +inline void CopiedSpace::allocateBlock() +{ + if (m_heap->shouldCollect()) + m_heap->collect(Heap::DoNotSweep); + + m_allocator.resetCurrentBlock(); + + CopiedBlock* block = CopiedBlock::create(m_heap->blockAllocator().allocate()); + + m_toSpace->push(block); + m_blockFilter.add(reinterpret_cast(block)); + m_blockSet.add(block); + m_allocator.setCurrentBlock(block); +} + +inline CheckedBoolean CopiedSpace::tryAllocate(size_t bytes, void** outPtr) +{ + ASSERT(!m_heap->globalData()->isInitializingObject()); + + if (isOversize(bytes) || !m_allocator.tryAllocate(bytes, outPtr)) + return tryAllocateSlowCase(bytes, outPtr); + + ASSERT(*outPtr); + return true; +} + +inline bool CopiedSpace::isOversize(size_t bytes) +{ + return bytes > s_maxAllocationSize; +} + +inline bool CopiedSpace::isPinned(void* ptr) +{ + return blockFor(ptr)->m_isPinned; +} + +inline CopiedBlock* CopiedSpace::oversizeBlockFor(void* ptr) +{ + return reinterpret_cast(reinterpret_cast(ptr) & WTF::pageMask()); +} + +inline CopiedBlock* CopiedSpace::blockFor(void* ptr) +{ + return reinterpret_cast(reinterpret_cast(ptr) & s_blockMask); +} + +} // namespace JSC + +#endif // CopiedSpaceInlines_h + diff --git a/Source/JavaScriptCore/heap/CopyVisitor.cpp b/Source/JavaScriptCore/heap/CopyVisitor.cpp index ae826f0d2..22ab57882 100644 --- a/Source/JavaScriptCore/heap/CopyVisitor.cpp +++ b/Source/JavaScriptCore/heap/CopyVisitor.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "CopyVisitor.h" -#include "CopyVisitorInlineMethods.h" +#include "CopyVisitorInlines.h" #include "GCThreadSharedData.h" #include "JSCell.h" #include "JSObject.h" diff --git a/Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h b/Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h deleted file mode 100644 index eb7bd2e82..000000000 --- a/Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h +++ /dev/null @@ -1,119 +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. - */ - -#ifndef CopyVisitorInlineMethods_h -#define CopyVisitorInlineMethods_h - -#include "ClassInfo.h" -#include "CopyVisitor.h" -#include "GCThreadSharedData.h" -#include "JSCell.h" -#include "JSDestructibleObject.h" - -namespace JSC { - -class GCCopyPhaseFunctor : public MarkedBlock::VoidFunctor { -public: - GCCopyPhaseFunctor(CopyVisitor& visitor) - : m_visitor(visitor) - { - } - - void operator()(JSCell* cell) - { - Structure* structure = cell->structure(); - if (!structure->outOfLineCapacity() && !hasIndexedProperties(structure->indexingType())) - return; - ASSERT(structure->classInfo()->methodTable.copyBackingStore == JSObject::copyBackingStore); - JSObject::copyBackingStore(cell, m_visitor); - } - -private: - CopyVisitor& m_visitor; -}; - -inline bool CopyVisitor::checkIfShouldCopy(void* oldPtr, size_t bytes) -{ - if (CopiedSpace::isOversize(bytes)) - return false; - - if (CopiedSpace::blockFor(oldPtr)->isPinned()) - return false; - - return true; -} - -inline void* CopyVisitor::allocateNewSpace(size_t bytes) -{ - void* result = 0; // Compilers don't realize that this will be assigned. - if (LIKELY(m_copiedAllocator.tryAllocate(bytes, &result))) - return result; - - result = allocateNewSpaceSlow(bytes); - ASSERT(result); - return result; -} - -inline void* CopyVisitor::allocateNewSpaceSlow(size_t bytes) -{ - CopiedBlock* newBlock = 0; - m_shared.m_copiedSpace->doneFillingBlock(m_copiedAllocator.resetCurrentBlock(), &newBlock); - m_copiedAllocator.setCurrentBlock(newBlock); - - void* result = 0; - CheckedBoolean didSucceed = m_copiedAllocator.tryAllocate(bytes, &result); - ASSERT(didSucceed); - return result; -} - -inline void CopyVisitor::startCopying() -{ - ASSERT(!m_copiedAllocator.isValid()); - CopiedBlock* block = 0; - m_shared.m_copiedSpace->doneFillingBlock(m_copiedAllocator.resetCurrentBlock(), &block); - m_copiedAllocator.setCurrentBlock(block); -} - -inline void CopyVisitor::doneCopying() -{ - if (!m_copiedAllocator.isValid()) - return; - - m_shared.m_copiedSpace->doneFillingBlock(m_copiedAllocator.resetCurrentBlock(), 0); -} - -inline void CopyVisitor::didCopy(void* ptr, size_t bytes) -{ - ASSERT(!CopiedSpace::isOversize(bytes)); - CopiedBlock* block = CopiedSpace::blockFor(ptr); - ASSERT(!block->isPinned()); - - if (block->didEvacuateBytes(bytes)) - m_shared.m_copiedSpace->recycleEvacuatedBlock(block); -} - -} // namespace JSC - -#endif diff --git a/Source/JavaScriptCore/heap/CopyVisitorInlines.h b/Source/JavaScriptCore/heap/CopyVisitorInlines.h new file mode 100644 index 000000000..bd7879429 --- /dev/null +++ b/Source/JavaScriptCore/heap/CopyVisitorInlines.h @@ -0,0 +1,120 @@ +/* + * 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. + */ + +#ifndef CopyVisitorInlines_h +#define CopyVisitorInlines_h + +#include "ClassInfo.h" +#include "CopyVisitor.h" +#include "GCThreadSharedData.h" +#include "JSCell.h" +#include "JSDestructibleObject.h" + +namespace JSC { + +class GCCopyPhaseFunctor : public MarkedBlock::VoidFunctor { +public: + GCCopyPhaseFunctor(CopyVisitor& visitor) + : m_visitor(visitor) + { + } + + void operator()(JSCell* cell) + { + Structure* structure = cell->structure(); + if (!structure->outOfLineCapacity() && !hasIndexedProperties(structure->indexingType())) + return; + ASSERT(structure->classInfo()->methodTable.copyBackingStore == JSObject::copyBackingStore); + JSObject::copyBackingStore(cell, m_visitor); + } + +private: + CopyVisitor& m_visitor; +}; + +inline bool CopyVisitor::checkIfShouldCopy(void* oldPtr, size_t bytes) +{ + if (CopiedSpace::isOversize(bytes)) + return false; + + if (CopiedSpace::blockFor(oldPtr)->isPinned()) + return false; + + return true; +} + +inline void* CopyVisitor::allocateNewSpace(size_t bytes) +{ + void* result = 0; // Compilers don't realize that this will be assigned. + if (LIKELY(m_copiedAllocator.tryAllocate(bytes, &result))) + return result; + + result = allocateNewSpaceSlow(bytes); + ASSERT(result); + return result; +} + +inline void* CopyVisitor::allocateNewSpaceSlow(size_t bytes) +{ + CopiedBlock* newBlock = 0; + m_shared.m_copiedSpace->doneFillingBlock(m_copiedAllocator.resetCurrentBlock(), &newBlock); + m_copiedAllocator.setCurrentBlock(newBlock); + + void* result = 0; + CheckedBoolean didSucceed = m_copiedAllocator.tryAllocate(bytes, &result); + ASSERT(didSucceed); + return result; +} + +inline void CopyVisitor::startCopying() +{ + ASSERT(!m_copiedAllocator.isValid()); + CopiedBlock* block = 0; + m_shared.m_copiedSpace->doneFillingBlock(m_copiedAllocator.resetCurrentBlock(), &block); + m_copiedAllocator.setCurrentBlock(block); +} + +inline void CopyVisitor::doneCopying() +{ + if (!m_copiedAllocator.isValid()) + return; + + m_shared.m_copiedSpace->doneFillingBlock(m_copiedAllocator.resetCurrentBlock(), 0); +} + +inline void CopyVisitor::didCopy(void* ptr, size_t bytes) +{ + ASSERT(!CopiedSpace::isOversize(bytes)); + CopiedBlock* block = CopiedSpace::blockFor(ptr); + ASSERT(!block->isPinned()); + + if (block->didEvacuateBytes(bytes)) + m_shared.m_copiedSpace->recycleEvacuatedBlock(block); +} + +} // namespace JSC + +#endif // CopyVisitorInlines_h + diff --git a/Source/JavaScriptCore/heap/GCThread.cpp b/Source/JavaScriptCore/heap/GCThread.cpp index ce3bbedc9..7caa7d588 100644 --- a/Source/JavaScriptCore/heap/GCThread.cpp +++ b/Source/JavaScriptCore/heap/GCThread.cpp @@ -27,7 +27,7 @@ #include "GCThread.h" #include "CopyVisitor.h" -#include "CopyVisitorInlineMethods.h" +#include "CopyVisitorInlines.h" #include "GCThreadSharedData.h" #include "SlotVisitor.h" #include diff --git a/Source/JavaScriptCore/heap/GCThreadSharedData.cpp b/Source/JavaScriptCore/heap/GCThreadSharedData.cpp index 446b41c2f..f513fafab 100644 --- a/Source/JavaScriptCore/heap/GCThreadSharedData.cpp +++ b/Source/JavaScriptCore/heap/GCThreadSharedData.cpp @@ -27,12 +27,12 @@ #include "GCThreadSharedData.h" #include "CopyVisitor.h" -#include "CopyVisitorInlineMethods.h" +#include "CopyVisitorInlines.h" #include "GCThread.h" #include "JSGlobalData.h" #include "MarkStack.h" #include "SlotVisitor.h" -#include "SlotVisitorInlineMethods.h" +#include "SlotVisitorInlines.h" namespace JSC { @@ -56,7 +56,7 @@ GCThreadSharedData::GCThreadSharedData(JSGlobalData* globalData) : m_globalData(globalData) , m_copiedSpace(&globalData->heap.m_storageSpace) , m_shouldHashConst(false) - , m_sharedMarkStack(m_segmentAllocator) + , m_sharedMarkStack(globalData->heap.blockAllocator()) , m_numberOfActiveParallelMarkers(0) , m_parallelMarkersShouldExit(false) , m_blocksToCopy(globalData->heap.m_blockSnapshot) @@ -110,7 +110,6 @@ void GCThreadSharedData::reset() ASSERT(m_sharedMarkStack.isEmpty()); #if ENABLE(PARALLEL_GC) - m_segmentAllocator.shrinkReserve(); m_opaqueRoots.clear(); #else ASSERT(m_opaqueRoots.isEmpty()); diff --git a/Source/JavaScriptCore/heap/GCThreadSharedData.h b/Source/JavaScriptCore/heap/GCThreadSharedData.h index f341afc04..b80cc5af2 100644 --- a/Source/JavaScriptCore/heap/GCThreadSharedData.h +++ b/Source/JavaScriptCore/heap/GCThreadSharedData.h @@ -80,8 +80,6 @@ private: JSGlobalData* m_globalData; CopiedSpace* m_copiedSpace; - MarkStackSegmentAllocator m_segmentAllocator; - bool m_shouldHashConst; Vector m_gcThreads; diff --git a/Source/JavaScriptCore/heap/HandleStack.cpp b/Source/JavaScriptCore/heap/HandleStack.cpp index 42eb326a5..a5653c748 100644 --- a/Source/JavaScriptCore/heap/HandleStack.cpp +++ b/Source/JavaScriptCore/heap/HandleStack.cpp @@ -27,8 +27,8 @@ #include "HandleStack.h" #include "HeapRootVisitor.h" -#include "JSValueInlineMethods.h" #include "JSObject.h" +#include "JSValueInlines.h" namespace JSC { diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp index c455fc2b1..9ff318b08 100644 --- a/Source/JavaScriptCore/heap/Heap.cpp +++ b/Source/JavaScriptCore/heap/Heap.cpp @@ -24,8 +24,8 @@ #include "CodeBlock.h" #include "ConservativeRoots.h" #include "CopiedSpace.h" -#include "CopiedSpaceInlineMethods.h" -#include "CopyVisitorInlineMethods.h" +#include "CopiedSpaceInlines.h" +#include "CopyVisitorInlines.h" #include "GCActivityCallback.h" #include "HeapRootVisitor.h" #include "HeapStatistics.h" @@ -76,7 +76,7 @@ struct GCTimer { } ~GCTimer() { - dataLog("%s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf)\n", m_name, m_time * 1000, m_time * 1000 / m_count, m_min*1000, m_max*1000); + dataLogF("%s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf)\n", m_name, m_time * 1000, m_time * 1000 / m_count, m_min*1000, m_max*1000); } double m_time; double m_min; @@ -126,7 +126,7 @@ struct GCCounter { } ~GCCounter() { - dataLog("%s: %zu values (avg. %zu, min. %zu, max. %zu)\n", m_name, m_total, m_total / m_count, m_min, m_max); + dataLogF("%s: %zu values (avg. %zu, min. %zu, max. %zu)\n", m_name, m_total, m_total / m_count, m_min, m_max); } const char* m_name; size_t m_count; diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h index d0d03959b..90c9f2ab1 100644 --- a/Source/JavaScriptCore/heap/Heap.h +++ b/Source/JavaScriptCore/heap/Heap.h @@ -174,6 +174,8 @@ namespace JSC { bool isPagedOut(double deadline); void didStartVMShutdown(); + + const JITStubRoutineSet& jitStubRoutines() { return m_jitStubRoutines; } private: friend class CodeBlock; diff --git a/Source/JavaScriptCore/heap/HeapRootVisitor.h b/Source/JavaScriptCore/heap/HeapRootVisitor.h index 9849d7c39..5b11a5ead 100644 --- a/Source/JavaScriptCore/heap/HeapRootVisitor.h +++ b/Source/JavaScriptCore/heap/HeapRootVisitor.h @@ -27,7 +27,7 @@ #define HeapRootVisitor_h #include "SlotVisitor.h" -#include "SlotVisitorInlineMethods.h" +#include "SlotVisitorInlines.h" namespace JSC { diff --git a/Source/JavaScriptCore/heap/HeapStatistics.cpp b/Source/JavaScriptCore/heap/HeapStatistics.cpp index 8340bfa37..2b98fe711 100644 --- a/Source/JavaScriptCore/heap/HeapStatistics.cpp +++ b/Source/JavaScriptCore/heap/HeapStatistics.cpp @@ -41,8 +41,8 @@ namespace JSC { double HeapStatistics::s_startTime = 0.0; double HeapStatistics::s_endTime = 0.0; -Deque* HeapStatistics::s_pauseTimeStarts = 0; -Deque* HeapStatistics::s_pauseTimeEnds = 0; +Vector* HeapStatistics::s_pauseTimeStarts = 0; +Vector* HeapStatistics::s_pauseTimeEnds = 0; #if OS(UNIX) @@ -50,8 +50,8 @@ void HeapStatistics::initialize() { ASSERT(Options::recordGCPauseTimes()); s_startTime = WTF::monotonicallyIncreasingTime(); - s_pauseTimeStarts = new Deque(); - s_pauseTimeEnds = new Deque(); + s_pauseTimeStarts = new Vector(); + s_pauseTimeEnds = new Vector(); } void HeapStatistics::recordGCPauseTime(double start, double end) @@ -75,28 +75,28 @@ void HeapStatistics::logStatistics() #error "The HeapStatistics module is not supported on this platform." #endif if (!vmName || !suiteName || !benchmarkName) - dataLog("HeapStatistics: {\"max_rss\": %ld", usage.ru_maxrss); + dataLogF("HeapStatistics: {\"max_rss\": %ld", usage.ru_maxrss); else - dataLog("HeapStatistics: {\"max_rss\": %ld, \"vm_name\": \"%s\", \"suite_name\": \"%s\", \"benchmark_name\": \"%s\"", + dataLogF("HeapStatistics: {\"max_rss\": %ld, \"vm_name\": \"%s\", \"suite_name\": \"%s\", \"benchmark_name\": \"%s\"", usage.ru_maxrss, vmName, suiteName, benchmarkName); if (Options::recordGCPauseTimes()) { - dataLog(", \"pause_times\": ["); - Deque::iterator startIt = s_pauseTimeStarts->begin(); - Deque::iterator endIt = s_pauseTimeEnds->begin(); + dataLogF(", \"pause_times\": ["); + Vector::iterator startIt = s_pauseTimeStarts->begin(); + Vector::iterator endIt = s_pauseTimeEnds->begin(); if (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) { - dataLog("[%f, %f]", *startIt, *endIt); + dataLogF("[%f, %f]", *startIt, *endIt); ++startIt; ++endIt; } while (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) { - dataLog(", [%f, %f]", *startIt, *endIt); + dataLogF(", [%f, %f]", *startIt, *endIt); ++startIt; ++endIt; } - dataLog("], \"start_time\": %f, \"end_time\": %f", s_startTime, s_endTime); + dataLogF("], \"start_time\": %f, \"end_time\": %f", s_startTime, s_endTime); } - dataLog("}\n"); + dataLogF("}\n"); } void HeapStatistics::exitWithFailure() @@ -228,20 +228,20 @@ inline size_t StorageStatistics::storageCapacity() void HeapStatistics::showObjectStatistics(Heap* heap) { - dataLog("\n=== Heap Statistics: ===\n"); - dataLog("size: %ldkB\n", static_cast(heap->m_sizeAfterLastCollect / KB)); - dataLog("capacity: %ldkB\n", static_cast(heap->capacity() / KB)); - dataLog("pause time: %lfms\n\n", heap->m_lastGCLength); + dataLogF("\n=== Heap Statistics: ===\n"); + dataLogF("size: %ldkB\n", static_cast(heap->m_sizeAfterLastCollect / KB)); + dataLogF("capacity: %ldkB\n", static_cast(heap->capacity() / KB)); + dataLogF("pause time: %lfms\n\n", heap->m_lastGCLength); StorageStatistics storageStatistics; heap->m_objectSpace.forEachLiveCell(storageStatistics); - dataLog("wasted .property storage: %ldkB (%ld%%)\n", + dataLogF("wasted .property storage: %ldkB (%ld%%)\n", static_cast( (storageStatistics.storageCapacity() - storageStatistics.storageSize()) / KB), static_cast( (storageStatistics.storageCapacity() - storageStatistics.storageSize()) * 100 / storageStatistics.storageCapacity())); - dataLog("objects with out-of-line .property storage: %ld (%ld%%)\n", + dataLogF("objects with out-of-line .property storage: %ld (%ld%%)\n", static_cast( storageStatistics.objectWithOutOfLineStorageCount()), static_cast( diff --git a/Source/JavaScriptCore/heap/HeapStatistics.h b/Source/JavaScriptCore/heap/HeapStatistics.h index 0800f0c16..ce7a40a79 100644 --- a/Source/JavaScriptCore/heap/HeapStatistics.h +++ b/Source/JavaScriptCore/heap/HeapStatistics.h @@ -49,8 +49,8 @@ public: private: static void logStatistics(); - static Deque* s_pauseTimeStarts; - static Deque* s_pauseTimeEnds; + static Vector* s_pauseTimeStarts; + static Vector* s_pauseTimeEnds; static double s_startTime; static double s_endTime; }; diff --git a/Source/JavaScriptCore/heap/JITStubRoutineSet.h b/Source/JavaScriptCore/heap/JITStubRoutineSet.h index cb76ac8bd..2c2e9fa86 100644 --- a/Source/JavaScriptCore/heap/JITStubRoutineSet.h +++ b/Source/JavaScriptCore/heap/JITStubRoutineSet.h @@ -65,6 +65,9 @@ public: void traceMarkedStubRoutines(SlotVisitor&); + unsigned size() const { return m_listOfRoutines.size(); } + GCAwareJITStubRoutine* at(unsigned i) const { return m_listOfRoutines[i]; } + private: void markSlow(uintptr_t address); diff --git a/Source/JavaScriptCore/heap/MarkStack.cpp b/Source/JavaScriptCore/heap/MarkStack.cpp index 582439fd2..755a0ad50 100644 --- a/Source/JavaScriptCore/heap/MarkStack.cpp +++ b/Source/JavaScriptCore/heap/MarkStack.cpp @@ -25,18 +25,18 @@ #include "config.h" #include "MarkStack.h" -#include "MarkStackInlineMethods.h" +#include "MarkStackInlines.h" -#include "CopiedSpace.h" -#include "CopiedSpaceInlineMethods.h" #include "ConservativeRoots.h" +#include "CopiedSpace.h" +#include "CopiedSpaceInlines.h" #include "Heap.h" #include "Options.h" #include "JSArray.h" #include "JSCell.h" #include "JSObject.h" -#include "SlotVisitorInlineMethods.h" +#include "SlotVisitorInlines.h" #include "Structure.h" #include "WriteBarrier.h" #include @@ -45,84 +45,35 @@ namespace JSC { -MarkStackSegmentAllocator::MarkStackSegmentAllocator() - : m_nextFreeSegment(0) -{ - m_lock.Init(); -} - -MarkStackSegmentAllocator::~MarkStackSegmentAllocator() -{ - shrinkReserve(); -} - -MarkStackSegment* MarkStackSegmentAllocator::allocate() -{ - { - SpinLockHolder locker(&m_lock); - if (m_nextFreeSegment) { - MarkStackSegment* result = m_nextFreeSegment; - m_nextFreeSegment = result->m_previous; - return result; - } - } - - return static_cast(OSAllocator::reserveAndCommit(Options::gcMarkStackSegmentSize())); -} - -void MarkStackSegmentAllocator::release(MarkStackSegment* segment) -{ - SpinLockHolder locker(&m_lock); - segment->m_previous = m_nextFreeSegment; - m_nextFreeSegment = segment; -} - -void MarkStackSegmentAllocator::shrinkReserve() -{ - MarkStackSegment* segments; - { - SpinLockHolder locker(&m_lock); - segments = m_nextFreeSegment; - m_nextFreeSegment = 0; - } - while (segments) { - MarkStackSegment* toFree = segments; - segments = segments->m_previous; - OSAllocator::decommitAndRelease(toFree, Options::gcMarkStackSegmentSize()); - } -} - -MarkStackArray::MarkStackArray(MarkStackSegmentAllocator& allocator) - : m_allocator(allocator) +MarkStackArray::MarkStackArray(BlockAllocator& blockAllocator) + : m_blockAllocator(blockAllocator) , m_segmentCapacity(MarkStackSegment::capacityFromSize(Options::gcMarkStackSegmentSize())) , m_top(0) - , m_numberOfPreviousSegments(0) + , m_numberOfSegments(0) { - m_topSegment = m_allocator.allocate(); -#if !ASSERT_DISABLED - m_topSegment->m_top = 0; -#endif - m_topSegment->m_previous = 0; + ASSERT(MarkStackSegment::blockSize == WeakBlock::blockSize); + m_segments.push(MarkStackSegment::create(m_blockAllocator.allocate())); + m_numberOfSegments++; } MarkStackArray::~MarkStackArray() { - ASSERT(!m_topSegment->m_previous); - m_allocator.release(m_topSegment); + ASSERT(m_numberOfSegments == 1 && m_segments.size() == 1); + m_blockAllocator.deallocate(MarkStackSegment::destroy(m_segments.removeHead())); } void MarkStackArray::expand() { - ASSERT(m_topSegment->m_top == m_segmentCapacity); + ASSERT(m_segments.head()->m_top == m_segmentCapacity); - m_numberOfPreviousSegments++; + MarkStackSegment* nextSegment = MarkStackSegment::create(m_blockAllocator.allocate()); + m_numberOfSegments++; - MarkStackSegment* nextSegment = m_allocator.allocate(); #if !ASSERT_DISABLED nextSegment->m_top = 0; #endif - nextSegment->m_previous = m_topSegment; - m_topSegment = nextSegment; + + m_segments.push(nextSegment); setTopForEmptySegment(); validatePrevious(); } @@ -132,14 +83,9 @@ bool MarkStackArray::refill() validatePrevious(); if (top()) return true; - MarkStackSegment* toFree = m_topSegment; - MarkStackSegment* previous = m_topSegment->m_previous; - if (!previous) - return false; - ASSERT(m_numberOfPreviousSegments); - m_numberOfPreviousSegments--; - m_topSegment = previous; - m_allocator.release(toFree); + m_blockAllocator.deallocate(MarkStackSegment::destroy(m_segments.removeHead())); + ASSERT(m_numberOfSegments > 1); + m_numberOfSegments--; setTopForFullSegment(); validatePrevious(); return true; @@ -153,7 +99,7 @@ void MarkStackArray::donateSomeCellsTo(MarkStackArray& other) ASSERT(m_segmentCapacity == other.m_segmentCapacity); - size_t segmentsToDonate = (m_numberOfPreviousSegments + 2 - 1) / 2; // Round up to donate 1 / 1 previous segments. + size_t segmentsToDonate = m_numberOfSegments / 2; // If we only have one segment (our head) we don't donate any segments. if (!segmentsToDonate) { size_t cellsToDonate = m_top / 2; // Round down to donate 0 / 1 cells. @@ -167,21 +113,23 @@ void MarkStackArray::donateSomeCellsTo(MarkStackArray& other) validatePrevious(); other.validatePrevious(); - MarkStackSegment* previous = m_topSegment->m_previous; + // Remove our head and the head of the other list before we start moving segments around. + // We'll add them back on once we're done donating. + MarkStackSegment* myHead = m_segments.removeHead(); + MarkStackSegment* otherHead = other.m_segments.removeHead(); + while (segmentsToDonate--) { - ASSERT(previous); - ASSERT(m_numberOfPreviousSegments); - - MarkStackSegment* current = previous; - previous = current->m_previous; - - current->m_previous = other.m_topSegment->m_previous; - other.m_topSegment->m_previous = current; - - m_numberOfPreviousSegments--; - other.m_numberOfPreviousSegments++; + MarkStackSegment* current = m_segments.removeHead(); + ASSERT(current); + ASSERT(m_numberOfSegments > 1); + other.m_segments.push(current); + m_numberOfSegments--; + other.m_numberOfSegments++; } - m_topSegment->m_previous = previous; + + // Put the original heads back in their places. + m_segments.push(myHead); + other.m_segments.push(otherHead); validatePrevious(); other.validatePrevious(); @@ -198,21 +146,21 @@ void MarkStackArray::stealSomeCellsFrom(MarkStackArray& other, size_t idleThread other.validatePrevious(); // If other has an entire segment, steal it and return. - if (other.m_topSegment->m_previous) { - ASSERT(other.m_topSegment->m_previous->m_top == m_segmentCapacity); - - // First remove a segment from other. - MarkStackSegment* current = other.m_topSegment->m_previous; - other.m_topSegment->m_previous = current->m_previous; - other.m_numberOfPreviousSegments--; - - ASSERT(!!other.m_numberOfPreviousSegments == !!other.m_topSegment->m_previous); - - // Now add it to this. - current->m_previous = m_topSegment->m_previous; - m_topSegment->m_previous = current; - m_numberOfPreviousSegments++; - + if (other.m_numberOfSegments > 1) { + // Move the heads of the lists aside. We'll push them back on after. + MarkStackSegment* otherHead = other.m_segments.removeHead(); + MarkStackSegment* myHead = m_segments.removeHead(); + + ASSERT(other.m_segments.head()->m_top == m_segmentCapacity); + + m_segments.push(other.m_segments.removeHead()); + + m_numberOfSegments++; + other.m_numberOfSegments--; + + m_segments.push(myHead); + other.m_segments.push(otherHead); + validatePrevious(); other.validatePrevious(); return; diff --git a/Source/JavaScriptCore/heap/MarkStack.h b/Source/JavaScriptCore/heap/MarkStack.h index 0245e4be5..2a7f04450 100644 --- a/Source/JavaScriptCore/heap/MarkStack.h +++ b/Source/JavaScriptCore/heap/MarkStack.h @@ -27,19 +27,19 @@ #define MarkStack_h #if ENABLE(OBJECT_MARK_LOGGING) -#define MARK_LOG_MESSAGE0(message) dataLog(message) -#define MARK_LOG_MESSAGE1(message, arg1) dataLog(message, arg1) -#define MARK_LOG_MESSAGE2(message, arg1, arg2) dataLog(message, arg1, arg2) +#define MARK_LOG_MESSAGE0(message) dataLogF(message) +#define MARK_LOG_MESSAGE1(message, arg1) dataLogF(message, arg1) +#define MARK_LOG_MESSAGE2(message, arg1, arg2) dataLogF(message, arg1, arg2) #define MARK_LOG_ROOT(visitor, rootName) \ - dataLog("\n%s: ", rootName); \ + dataLogF("\n%s: ", rootName); \ (visitor).resetChildCount() #define MARK_LOG_PARENT(visitor, parent) \ - dataLog("\n%p (%s): ", parent, parent->className() ? parent->className() : "unknown"); \ + dataLogF("\n%p (%s): ", parent, parent->className() ? parent->className() : "unknown"); \ (visitor).resetChildCount() #define MARK_LOG_CHILD(visitor, child) \ if ((visitor).childCount()) \ - dataLogString(", "); \ - dataLog("%p", child); \ + dataLogFString(", "); \ + dataLogF("%p", child); \ (visitor).incrementChildCount() #else #define MARK_LOG_MESSAGE0(message) do { } while (false) @@ -50,19 +50,27 @@ #define MARK_LOG_CHILD(visitor, child) do { } while (false) #endif +#include "HeapBlock.h" #include -#include namespace JSC { +class BlockAllocator; +class DeadBlock; class JSCell; -struct MarkStackSegment { - MarkStackSegment* m_previous; +class MarkStackSegment : public HeapBlock { +public: + MarkStackSegment(Region* region) + : HeapBlock(region) #if !ASSERT_DISABLED - size_t m_top; + , m_top(0) #endif - + { + } + + static MarkStackSegment* create(DeadBlock*); + const JSCell** data() { return bitwise_cast(this + 1); @@ -77,26 +85,17 @@ struct MarkStackSegment { { return sizeof(MarkStackSegment) + capacity * sizeof(const JSCell*); } -}; -class MarkStackSegmentAllocator { -public: - MarkStackSegmentAllocator(); - ~MarkStackSegmentAllocator(); - - MarkStackSegment* allocate(); - void release(MarkStackSegment*); - - void shrinkReserve(); - -private: - SpinLock m_lock; - MarkStackSegment* m_nextFreeSegment; + static const size_t blockSize = 4 * KB; + +#if !ASSERT_DISABLED + size_t m_top; +#endif }; class MarkStackArray { public: - MarkStackArray(MarkStackSegmentAllocator&); + MarkStackArray(BlockAllocator&); ~MarkStackArray(); void append(const JSCell*); @@ -122,12 +121,12 @@ private: void validatePrevious(); - MarkStackSegment* m_topSegment; - MarkStackSegmentAllocator& m_allocator; + DoublyLinkedList m_segments; + BlockAllocator& m_blockAllocator; size_t m_segmentCapacity; size_t m_top; - size_t m_numberOfPreviousSegments; + size_t m_numberOfSegments; }; diff --git a/Source/JavaScriptCore/heap/MarkStackInlineMethods.h b/Source/JavaScriptCore/heap/MarkStackInlineMethods.h deleted file mode 100644 index d3276d7fa..000000000 --- a/Source/JavaScriptCore/heap/MarkStackInlineMethods.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2009, 2011 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. ``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 - * 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. - */ - -#ifndef MarkStackInlineMethods_h -#define MarkStackInlineMethods_h - -#include "GCThreadSharedData.h" -#include "MarkStack.h" - -namespace JSC { - -inline size_t MarkStackArray::postIncTop() -{ - size_t result = m_top++; - ASSERT(result == m_topSegment->m_top++); - return result; -} - -inline size_t MarkStackArray::preDecTop() -{ - size_t result = --m_top; - ASSERT(result == --m_topSegment->m_top); - return result; -} - -inline void MarkStackArray::setTopForFullSegment() -{ - ASSERT(m_topSegment->m_top == m_segmentCapacity); - m_top = m_segmentCapacity; -} - -inline void MarkStackArray::setTopForEmptySegment() -{ - ASSERT(!m_topSegment->m_top); - m_top = 0; -} - -inline size_t MarkStackArray::top() -{ - ASSERT(m_top == m_topSegment->m_top); - return m_top; -} - -#if ASSERT_DISABLED -inline void MarkStackArray::validatePrevious() { } -#else -inline void MarkStackArray::validatePrevious() -{ - unsigned count = 0; - for (MarkStackSegment* current = m_topSegment->m_previous; current; current = current->m_previous) - count++; - ASSERT(count == m_numberOfPreviousSegments); -} -#endif - -inline void MarkStackArray::append(const JSCell* cell) -{ - if (m_top == m_segmentCapacity) - expand(); - m_topSegment->data()[postIncTop()] = cell; -} - -inline bool MarkStackArray::canRemoveLast() -{ - return !!m_top; -} - -inline const JSCell* MarkStackArray::removeLast() -{ - return m_topSegment->data()[preDecTop()]; -} - -inline bool MarkStackArray::isEmpty() -{ - if (m_top) - return false; - if (m_topSegment->m_previous) { - ASSERT(m_topSegment->m_previous->m_top == m_segmentCapacity); - return false; - } - return true; -} - -inline size_t MarkStackArray::size() -{ - return m_top + m_segmentCapacity * m_numberOfPreviousSegments; -} - -} // namespace JSC - -#endif diff --git a/Source/JavaScriptCore/heap/MarkStackInlines.h b/Source/JavaScriptCore/heap/MarkStackInlines.h new file mode 100644 index 000000000..1595e843e --- /dev/null +++ b/Source/JavaScriptCore/heap/MarkStackInlines.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2009, 2011 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. ``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 + * 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. + */ + +#ifndef MarkStackInlines_h +#define MarkStackInlines_h + +#include "GCThreadSharedData.h" +#include "MarkStack.h" + +namespace JSC { + +inline MarkStackSegment* MarkStackSegment::create(DeadBlock* block) +{ + return new (NotNull, block) MarkStackSegment(block->region()); +} + +inline size_t MarkStackArray::postIncTop() +{ + size_t result = m_top++; + ASSERT(result == m_segments.head()->m_top++); + return result; +} + +inline size_t MarkStackArray::preDecTop() +{ + size_t result = --m_top; + ASSERT(result == --m_segments.head()->m_top); + return result; +} + +inline void MarkStackArray::setTopForFullSegment() +{ + ASSERT(m_segments.head()->m_top == m_segmentCapacity); + m_top = m_segmentCapacity; +} + +inline void MarkStackArray::setTopForEmptySegment() +{ + ASSERT(!m_segments.head()->m_top); + m_top = 0; +} + +inline size_t MarkStackArray::top() +{ + ASSERT(m_top == m_segments.head()->m_top); + return m_top; +} + +#if ASSERT_DISABLED +inline void MarkStackArray::validatePrevious() { } +#else +inline void MarkStackArray::validatePrevious() +{ + unsigned count = 0; + for (MarkStackSegment* current = m_segments.head(); current; current = current->next()) + count++; + ASSERT(m_segments.size() == m_numberOfSegments); +} +#endif + +inline void MarkStackArray::append(const JSCell* cell) +{ + if (m_top == m_segmentCapacity) + expand(); + m_segments.head()->data()[postIncTop()] = cell; +} + +inline bool MarkStackArray::canRemoveLast() +{ + return !!m_top; +} + +inline const JSCell* MarkStackArray::removeLast() +{ + return m_segments.head()->data()[preDecTop()]; +} + +inline bool MarkStackArray::isEmpty() +{ + if (m_top) + return false; + if (m_segments.head()->next()) { + ASSERT(m_segments.head()->next()->m_top == m_segmentCapacity); + return false; + } + return true; +} + +inline size_t MarkStackArray::size() +{ + return m_top + m_segmentCapacity * (m_numberOfSegments - 1); +} + +} // namespace JSC + +#endif // MarkStackInlines_h + diff --git a/Source/JavaScriptCore/heap/MarkedBlock.h b/Source/JavaScriptCore/heap/MarkedBlock.h index f2f2a720d..9080aaef4 100644 --- a/Source/JavaScriptCore/heap/MarkedBlock.h +++ b/Source/JavaScriptCore/heap/MarkedBlock.h @@ -40,7 +40,7 @@ #if HEAP_LOG_BLOCK_STATE_TRANSITIONS #define HEAP_LOG_BLOCK_STATE_TRANSITION(block) do { \ - dataLog( \ + dataLogF( \ "%s:%d %s: block %s = %p, %d\n", \ __FILE__, __LINE__, __FUNCTION__, \ #block, (block), (block)->m_state); \ diff --git a/Source/JavaScriptCore/heap/SlotVisitor.cpp b/Source/JavaScriptCore/heap/SlotVisitor.cpp index 3919705d0..3ff4b48fa 100644 --- a/Source/JavaScriptCore/heap/SlotVisitor.cpp +++ b/Source/JavaScriptCore/heap/SlotVisitor.cpp @@ -1,9 +1,10 @@ #include "config.h" #include "SlotVisitor.h" +#include "SlotVisitorInlines.h" #include "ConservativeRoots.h" #include "CopiedSpace.h" -#include "CopiedSpaceInlineMethods.h" +#include "CopiedSpaceInlines.h" #include "GCThread.h" #include "JSArray.h" #include "JSDestructibleObject.h" @@ -15,7 +16,7 @@ namespace JSC { SlotVisitor::SlotVisitor(GCThreadSharedData& shared) - : m_stack(shared.m_segmentAllocator) + : m_stack(shared.m_globalData->heap.blockAllocator()) , m_visitCount(0) , m_isInParallelMode(false) , m_shared(shared) @@ -335,12 +336,12 @@ void SlotVisitor::finalizeUnconditionalFinalizers() void SlotVisitor::validate(JSCell* cell) { if (!cell) { - dataLog("cell is NULL\n"); + dataLogF("cell is NULL\n"); CRASH(); } if (!cell->structure()) { - dataLog("cell at %p has a null structure\n" , cell); + dataLogF("cell at %p has a null structure\n" , cell); CRASH(); } @@ -353,7 +354,7 @@ void SlotVisitor::validate(JSCell* cell) parentClassName = cell->structure()->structure()->JSCell::classInfo()->className; if (cell->structure()->JSCell::classInfo()) ourClassName = cell->structure()->JSCell::classInfo()->className; - dataLog("parent structure (%p <%s>) of cell at %p doesn't match cell's structure (%p <%s>)\n", + dataLogF("parent structure (%p <%s>) of cell at %p doesn't match cell's structure (%p <%s>)\n", cell->structure()->structure(), parentClassName, cell, cell->structure(), ourClassName); CRASH(); } diff --git a/Source/JavaScriptCore/heap/SlotVisitor.h b/Source/JavaScriptCore/heap/SlotVisitor.h index dcd4b75ef..53c7de64f 100644 --- a/Source/JavaScriptCore/heap/SlotVisitor.h +++ b/Source/JavaScriptCore/heap/SlotVisitor.h @@ -27,7 +27,7 @@ #define SlotVisitor_h #include "HandleTypes.h" -#include "MarkStackInlineMethods.h" +#include "MarkStackInlines.h" #include @@ -36,6 +36,7 @@ namespace JSC { class ConservativeRoots; class GCThreadSharedData; class Heap; +template class Weak; template class WriteBarrierBase; template class JITWriteBarrier; @@ -56,6 +57,8 @@ public: template void appendUnbarrieredPointer(T**); void appendUnbarrieredValue(JSValue*); + template + void appendUnbarrieredWeak(Weak*); void addOpaqueRoot(void*); bool containsOpaqueRoot(void*); diff --git a/Source/JavaScriptCore/heap/SlotVisitorInlineMethods.h b/Source/JavaScriptCore/heap/SlotVisitorInlineMethods.h deleted file mode 100644 index e5908bf36..000000000 --- a/Source/JavaScriptCore/heap/SlotVisitorInlineMethods.h +++ /dev/null @@ -1,174 +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. - */ - -#ifndef SlotVisitorInlineMethods_h -#define SlotVisitorInlineMethods_h - -#include "CopiedSpaceInlineMethods.h" -#include "Options.h" -#include "SlotVisitor.h" - -namespace JSC { - -ALWAYS_INLINE void SlotVisitor::append(JSValue* slot, size_t count) -{ - for (size_t i = 0; i < count; ++i) { - JSValue& value = slot[i]; - internalAppend(value); - } -} - -template -inline void SlotVisitor::appendUnbarrieredPointer(T** slot) -{ - ASSERT(slot); - JSCell* cell = *slot; - internalAppend(cell); -} - -ALWAYS_INLINE void SlotVisitor::append(JSValue* slot) -{ - ASSERT(slot); - internalAppend(*slot); -} - -ALWAYS_INLINE void SlotVisitor::appendUnbarrieredValue(JSValue* slot) -{ - ASSERT(slot); - internalAppend(*slot); -} - -ALWAYS_INLINE void SlotVisitor::append(JSCell** slot) -{ - ASSERT(slot); - internalAppend(*slot); -} - -ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue value) -{ - if (!value || !value.isCell()) - return; - internalAppend(value.asCell()); -} - -inline void SlotVisitor::addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester) -{ - m_shared.m_weakReferenceHarvesters.addThreadSafe(weakReferenceHarvester); -} - -inline void SlotVisitor::addUnconditionalFinalizer(UnconditionalFinalizer* unconditionalFinalizer) -{ - m_shared.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer); -} - -inline void SlotVisitor::addOpaqueRoot(void* root) -{ -#if ENABLE(PARALLEL_GC) - if (Options::numberOfGCMarkers() == 1) { - // Put directly into the shared HashSet. - m_shared.m_opaqueRoots.add(root); - return; - } - // Put into the local set, but merge with the shared one every once in - // a while to make sure that the local sets don't grow too large. - mergeOpaqueRootsIfProfitable(); - m_opaqueRoots.add(root); -#else - m_opaqueRoots.add(root); -#endif -} - -inline bool SlotVisitor::containsOpaqueRoot(void* root) -{ - ASSERT(!m_isInParallelMode); -#if ENABLE(PARALLEL_GC) - ASSERT(m_opaqueRoots.isEmpty()); - return m_shared.m_opaqueRoots.contains(root); -#else - return m_opaqueRoots.contains(root); -#endif -} - -inline int SlotVisitor::opaqueRootCount() -{ - ASSERT(!m_isInParallelMode); -#if ENABLE(PARALLEL_GC) - ASSERT(m_opaqueRoots.isEmpty()); - return m_shared.m_opaqueRoots.size(); -#else - return m_opaqueRoots.size(); -#endif -} - -inline void SlotVisitor::mergeOpaqueRootsIfNecessary() -{ - if (m_opaqueRoots.isEmpty()) - return; - mergeOpaqueRoots(); -} - -inline void SlotVisitor::mergeOpaqueRootsIfProfitable() -{ - if (static_cast(m_opaqueRoots.size()) < Options::opaqueRootMergeThreshold()) - return; - mergeOpaqueRoots(); -} - -inline void SlotVisitor::donate() -{ - ASSERT(m_isInParallelMode); - if (Options::numberOfGCMarkers() == 1) - return; - - donateKnownParallel(); -} - -inline void SlotVisitor::donateAndDrain() -{ - donate(); - drain(); -} - -inline void SlotVisitor::copyLater(void* ptr, size_t bytes) -{ - if (CopiedSpace::isOversize(bytes)) { - m_shared.m_copiedSpace->pin(CopiedSpace::oversizeBlockFor(ptr)); - return; - } - - CopiedBlock* block = CopiedSpace::blockFor(ptr); - if (block->isPinned()) - return; - - block->reportLiveBytes(bytes); - - if (!block->shouldEvacuate()) - m_shared.m_copiedSpace->pin(block); -} - -} // namespace JSC - -#endif // SlotVisitorInlineMethods_h - diff --git a/Source/JavaScriptCore/heap/SlotVisitorInlines.h b/Source/JavaScriptCore/heap/SlotVisitorInlines.h new file mode 100644 index 000000000..ea8126f87 --- /dev/null +++ b/Source/JavaScriptCore/heap/SlotVisitorInlines.h @@ -0,0 +1,183 @@ +/* + * 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. + */ + +#ifndef SlotVisitorInlines_h +#define SlotVisitorInlines_h + +#include "CopiedSpaceInlines.h" +#include "Options.h" +#include "SlotVisitor.h" +#include "Weak.h" + +namespace JSC { + +ALWAYS_INLINE void SlotVisitor::append(JSValue* slot, size_t count) +{ + for (size_t i = 0; i < count; ++i) { + JSValue& value = slot[i]; + internalAppend(value); + } +} + +template +inline void SlotVisitor::appendUnbarrieredPointer(T** slot) +{ + ASSERT(slot); + JSCell* cell = *slot; + internalAppend(cell); +} + +ALWAYS_INLINE void SlotVisitor::append(JSValue* slot) +{ + ASSERT(slot); + internalAppend(*slot); +} + +ALWAYS_INLINE void SlotVisitor::appendUnbarrieredValue(JSValue* slot) +{ + ASSERT(slot); + internalAppend(*slot); +} + +ALWAYS_INLINE void SlotVisitor::append(JSCell** slot) +{ + ASSERT(slot); + internalAppend(*slot); +} + +template +ALWAYS_INLINE void SlotVisitor::appendUnbarrieredWeak(Weak* weak) +{ + ASSERT(weak); + if (weak->get()) + internalAppend(weak->get()); +} + +ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue value) +{ + if (!value || !value.isCell()) + return; + internalAppend(value.asCell()); +} + +inline void SlotVisitor::addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester) +{ + m_shared.m_weakReferenceHarvesters.addThreadSafe(weakReferenceHarvester); +} + +inline void SlotVisitor::addUnconditionalFinalizer(UnconditionalFinalizer* unconditionalFinalizer) +{ + m_shared.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer); +} + +inline void SlotVisitor::addOpaqueRoot(void* root) +{ +#if ENABLE(PARALLEL_GC) + if (Options::numberOfGCMarkers() == 1) { + // Put directly into the shared HashSet. + m_shared.m_opaqueRoots.add(root); + return; + } + // Put into the local set, but merge with the shared one every once in + // a while to make sure that the local sets don't grow too large. + mergeOpaqueRootsIfProfitable(); + m_opaqueRoots.add(root); +#else + m_opaqueRoots.add(root); +#endif +} + +inline bool SlotVisitor::containsOpaqueRoot(void* root) +{ + ASSERT(!m_isInParallelMode); +#if ENABLE(PARALLEL_GC) + ASSERT(m_opaqueRoots.isEmpty()); + return m_shared.m_opaqueRoots.contains(root); +#else + return m_opaqueRoots.contains(root); +#endif +} + +inline int SlotVisitor::opaqueRootCount() +{ + ASSERT(!m_isInParallelMode); +#if ENABLE(PARALLEL_GC) + ASSERT(m_opaqueRoots.isEmpty()); + return m_shared.m_opaqueRoots.size(); +#else + return m_opaqueRoots.size(); +#endif +} + +inline void SlotVisitor::mergeOpaqueRootsIfNecessary() +{ + if (m_opaqueRoots.isEmpty()) + return; + mergeOpaqueRoots(); +} + +inline void SlotVisitor::mergeOpaqueRootsIfProfitable() +{ + if (static_cast(m_opaqueRoots.size()) < Options::opaqueRootMergeThreshold()) + return; + mergeOpaqueRoots(); +} + +inline void SlotVisitor::donate() +{ + ASSERT(m_isInParallelMode); + if (Options::numberOfGCMarkers() == 1) + return; + + donateKnownParallel(); +} + +inline void SlotVisitor::donateAndDrain() +{ + donate(); + drain(); +} + +inline void SlotVisitor::copyLater(void* ptr, size_t bytes) +{ + if (CopiedSpace::isOversize(bytes)) { + m_shared.m_copiedSpace->pin(CopiedSpace::oversizeBlockFor(ptr)); + return; + } + + CopiedBlock* block = CopiedSpace::blockFor(ptr); + if (block->isPinned()) + return; + + block->reportLiveBytes(bytes); + + if (!block->shouldEvacuate()) + m_shared.m_copiedSpace->pin(block); +} + +} // namespace JSC + +#endif // SlotVisitorInlines_h + diff --git a/Source/JavaScriptCore/heap/Weak.h b/Source/JavaScriptCore/heap/Weak.h index 3c3d1d0ce..efb2a9a56 100644 --- a/Source/JavaScriptCore/heap/Weak.h +++ b/Source/JavaScriptCore/heap/Weak.h @@ -151,6 +151,11 @@ template inline WeakImpl* Weak::hashTableDeletedValue() return reinterpret_cast(-1); } +template inline bool operator==(const Weak& lhs, const Weak& rhs) +{ + return lhs.get() == rhs.get(); +} + // This function helps avoid modifying a weak table while holding an iterator into it. (Object allocation // can run a finalizer that modifies the table. We avoid that by requiring a pre-constructed object as our value.) template inline void weakAdd(Map& map, const Key& key, Value value) -- cgit v1.2.1