| /* |
| * 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 <wtf/CheckedBoolean.h> |
| |
| namespace JSC { |
| |
| inline bool CopiedSpace::contains(CopiedBlock* block) |
| { |
| return !m_blockFilter.ruleOut(reinterpret_cast<Bits>(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->pin(); |
| } |
| |
| 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<EncodedJSValue*>(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<CopiedBlock>()); |
| |
| { |
| 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<CopiedBlock>()); |
| |
| m_toSpace->push(block); |
| m_blockFilter.add(reinterpret_cast<Bits>(block)); |
| m_blockSet.add(block); |
| m_allocator.setCurrentBlock(block); |
| } |
| |
| inline CheckedBoolean CopiedSpace::tryAllocate(size_t bytes, void** outPtr) |
| { |
| #if ENABLE(GC_VALIDATION) |
| ASSERT(!m_heap->globalData()->isInitializingObject()); |
| #endif |
| |
| 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<CopiedBlock*>(reinterpret_cast<size_t>(ptr) & WTF::pageMask()); |
| } |
| |
| inline CopiedBlock* CopiedSpace::blockFor(void* ptr) |
| { |
| return reinterpret_cast<CopiedBlock*>(reinterpret_cast<size_t>(ptr) & s_blockMask); |
| } |
| |
| } // namespace JSC |
| |
| #endif // CopiedSpaceInlines_h |
| |