1/* 2 * Copyright (C) 2012 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef WeakBlock_h 27#define WeakBlock_h 28 29#include "HeapBlock.h" 30#include "WeakHandleOwner.h" 31#include "WeakImpl.h" 32#include <wtf/DoublyLinkedList.h> 33#include <wtf/StdLibExtras.h> 34 35namespace JSC { 36 37class DeadBlock; 38class HeapRootVisitor; 39class JSValue; 40class WeakHandleOwner; 41 42class WeakBlock : public HeapBlock<WeakBlock> { 43public: 44 friend class WTF::DoublyLinkedListNode<WeakBlock>; 45 static const size_t blockSize = 4 * KB; // 5% of MarkedBlock size 46 47 struct FreeCell { 48 FreeCell* next; 49 }; 50 51 struct SweepResult { 52 SweepResult(); 53 bool isNull() const; 54 55 bool blockIsFree; 56 FreeCell* freeList; 57 }; 58 59 static WeakBlock* create(DeadBlock*); 60 61 static WeakImpl* asWeakImpl(FreeCell*); 62 63 bool isEmpty(); 64 65 void sweep(); 66 SweepResult takeSweepResult(); 67 68 void visit(HeapRootVisitor&); 69 void reap(); 70 71 void lastChanceToFinalize(); 72 73private: 74 static FreeCell* asFreeCell(WeakImpl*); 75 76 WeakBlock(Region*); 77 WeakImpl* firstWeakImpl(); 78 void finalize(WeakImpl*); 79 WeakImpl* weakImpls(); 80 size_t weakImplCount(); 81 void addToFreeList(FreeCell**, WeakImpl*); 82 83 SweepResult m_sweepResult; 84}; 85 86inline WeakBlock::SweepResult::SweepResult() 87 : blockIsFree(true) 88 , freeList(0) 89{ 90 ASSERT(isNull()); 91} 92 93inline bool WeakBlock::SweepResult::isNull() const 94{ 95 return blockIsFree && !freeList; // This state is impossible, so we can use it to mean null. 96} 97 98inline WeakImpl* WeakBlock::asWeakImpl(FreeCell* freeCell) 99{ 100 return reinterpret_cast_ptr<WeakImpl*>(freeCell); 101} 102 103inline WeakBlock::SweepResult WeakBlock::takeSweepResult() 104{ 105 SweepResult tmp; 106 std::swap(tmp, m_sweepResult); 107 ASSERT(m_sweepResult.isNull()); 108 return tmp; 109} 110 111inline WeakBlock::FreeCell* WeakBlock::asFreeCell(WeakImpl* weakImpl) 112{ 113 return reinterpret_cast_ptr<FreeCell*>(weakImpl); 114} 115 116inline WeakImpl* WeakBlock::weakImpls() 117{ 118 return reinterpret_cast_ptr<WeakImpl*>(this) + ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl)); 119} 120 121inline size_t WeakBlock::weakImplCount() 122{ 123 return (blockSize / sizeof(WeakImpl)) - ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl)); 124} 125 126inline void WeakBlock::addToFreeList(FreeCell** freeList, WeakImpl* weakImpl) 127{ 128 ASSERT(weakImpl->state() == WeakImpl::Deallocated); 129 FreeCell* freeCell = asFreeCell(weakImpl); 130 ASSERT(!*freeList || ((char*)*freeList > (char*)this && (char*)*freeList < (char*)this + blockSize)); 131 ASSERT((char*)freeCell > (char*)this && (char*)freeCell < (char*)this + blockSize); 132 freeCell->next = *freeList; 133 *freeList = freeCell; 134} 135 136inline bool WeakBlock::isEmpty() 137{ 138 return !m_sweepResult.isNull() && m_sweepResult.blockIsFree; 139} 140 141} // namespace JSC 142 143#endif // WeakBlock_h 144