/* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef MarkedSpace_h #define MarkedSpace_h #include "MachineStackMarker.h" #include "MarkedBlock.h" #include "PageAllocationAligned.h" #include #include #include #include #include #include #define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) < MarkedSpace::maxCellSize, class_fits_in_cell) namespace JSC { class Heap; class JSCell; class JSGlobalData; class LiveObjectIterator; class MarkStack; class WeakGCHandle; class MarkedSpace { WTF_MAKE_NONCOPYABLE(MarkedSpace); public: // Currently public for use in assertions. static const size_t maxCellSize = 1024; static Heap* heap(JSCell*); static bool isMarked(const JSCell*); static bool testAndSetMarked(const JSCell*); static void setMarked(const JSCell*); MarkedSpace(JSGlobalData*); void destroy(); JSGlobalData* globalData() { return m_globalData; } size_t highWaterMark() { return m_highWaterMark; } void setHighWaterMark(size_t highWaterMark) { m_highWaterMark = highWaterMark; } void* allocate(size_t); void clearMarks(); void markRoots(); void reset(); void sweep(); void shrink(); size_t size() const; size_t capacity() const; size_t objectCount() const; bool contains(const void*); template void forEach(Functor&); private: // [ 8, 16... 128 ) static const size_t preciseStep = MarkedBlock::atomSize; static const size_t preciseCutoff = 128; static const size_t preciseCount = preciseCutoff / preciseStep - 1; // [ 128, 256... 1024 ) static const size_t impreciseStep = preciseCutoff; static const size_t impreciseCutoff = maxCellSize; static const size_t impreciseCount = impreciseCutoff / impreciseStep - 1; typedef HashSet::iterator BlockIterator; struct SizeClass { SizeClass(); void reset(); MarkedBlock* nextBlock; DoublyLinkedList blockList; size_t cellSize; }; MarkedBlock* allocateBlock(SizeClass&); void freeBlocks(DoublyLinkedList&); SizeClass& sizeClassFor(size_t); void* allocateFromSizeClass(SizeClass&); void clearMarks(MarkedBlock*); SizeClass m_preciseSizeClasses[preciseCount]; SizeClass m_impreciseSizeClasses[impreciseCount]; HashSet m_blocks; size_t m_waterMark; size_t m_highWaterMark; JSGlobalData* m_globalData; }; inline Heap* MarkedSpace::heap(JSCell* cell) { return MarkedBlock::blockFor(cell)->heap(); } inline bool MarkedSpace::isMarked(const JSCell* cell) { return MarkedBlock::blockFor(cell)->isMarked(cell); } inline bool MarkedSpace::testAndSetMarked(const JSCell* cell) { return MarkedBlock::blockFor(cell)->testAndSetMarked(cell); } inline void MarkedSpace::setMarked(const JSCell* cell) { MarkedBlock::blockFor(cell)->setMarked(cell); } inline bool MarkedSpace::contains(const void* x) { if (!MarkedBlock::isAtomAligned(x)) return false; MarkedBlock* block = MarkedBlock::blockFor(x); if (!block || !m_blocks.contains(block)) return false; return block->contains(x); } template inline void MarkedSpace::forEach(Functor& functor) { BlockIterator end = m_blocks.end(); for (BlockIterator it = m_blocks.begin(); it != end; ++it) (*it)->forEach(functor); } inline MarkedSpace::SizeClass::SizeClass() : nextBlock(0) , cellSize(0) { } inline void MarkedSpace::SizeClass::reset() { nextBlock = blockList.head(); } } // namespace JSC #endif // MarkedSpace_h