diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/MarkedSpace.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/MarkedSpace.h | 206 |
1 files changed, 70 insertions, 136 deletions
diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.h b/Source/JavaScriptCore/runtime/MarkedSpace.h index af312b5..fcb93b7 100644 --- a/Source/JavaScriptCore/runtime/MarkedSpace.h +++ b/Source/JavaScriptCore/runtime/MarkedSpace.h @@ -23,7 +23,9 @@ #define MarkedSpace_h #include "MachineStackMarker.h" +#include "MarkedBlock.h" #include "PageAllocationAligned.h" +#include <wtf/Bitmap.h> #include <wtf/FixedArray.h> #include <wtf/HashCountedSet.h> #include <wtf/Noncopyable.h> @@ -31,7 +33,6 @@ namespace JSC { - class CollectorBlock; class Heap; class JSCell; class JSGlobalData; @@ -39,182 +40,115 @@ namespace JSC { class MarkStack; class WeakGCHandle; -#if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP) - const size_t BLOCK_SIZE = 64 * 1024; // 64k -#else - const size_t BLOCK_SIZE = 256 * 1024; // 256k -#endif - - typedef HashCountedSet<JSCell*> ProtectCountSet; - struct CollectorHeap { - size_t nextBlock; - size_t nextCell; - PageAllocationAligned* blocks; + CollectorHeap() + : nextBlock(0) + , nextCell(0) + { + } - size_t numBlocks; - size_t usedBlocks; - - CollectorBlock* collectorBlock(size_t index) const + MarkedBlock* collectorBlock(size_t index) const { - return static_cast<CollectorBlock*>(blocks[index].base()); + return blocks[index]; } + + size_t nextBlock; + size_t nextCell; + Vector<MarkedBlock*> blocks; }; class MarkedSpace { WTF_MAKE_NONCOPYABLE(MarkedSpace); public: - MarkedSpace(JSGlobalData*); - void destroy(ProtectCountSet&); - - void* allocate(size_t); - - size_t objectCount() const; - struct Statistics { - size_t size; - size_t free; - }; - Statistics statistics() const; - size_t size() const; - static Heap* heap(JSCell*); - static bool isCellMarked(const JSCell*); - static bool checkMarkCell(const JSCell*); - static void markCell(JSCell*); - - WeakGCHandle* addWeakGCHandle(JSCell*); - - void markConservatively(ConservativeSet&, void* start, void* end); + static bool isMarked(const JSCell*); + static bool testAndSetMarked(const JSCell*); + static void setMarked(const JSCell*); - static bool isNumber(JSCell*); - - LiveObjectIterator primaryHeapBegin(); - LiveObjectIterator primaryHeapEnd(); + MarkedSpace(JSGlobalData*); + void destroy(); JSGlobalData* globalData() { return m_globalData; } - static CollectorBlock* cellBlock(const JSCell*); - static size_t cellOffset(const JSCell*); + 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(); - NEVER_INLINE CollectorBlock* allocateBlock(); - NEVER_INLINE void freeBlock(size_t); - void resizeBlocks(); - void growBlocks(size_t neededBlocks); - void shrinkBlocks(size_t neededBlocks); - void clearMarkBits(); - void clearMarkBits(CollectorBlock*); - size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const; + size_t size() const; + size_t capacity() const; + size_t objectCount() const; - void addToStatistics(Statistics&) const; + bool contains(const void*); - void markRoots(); + template<typename Functor> void forEach(Functor&); private: - CollectorHeap m_heap; - JSGlobalData* m_globalData; - }; + NEVER_INLINE MarkedBlock* allocateBlock(); + NEVER_INLINE void freeBlock(size_t); - // tunable parameters - // derived constants - const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1; - const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK; - const size_t MINIMUM_CELL_SIZE = 64; - const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0); - const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double); - const size_t SMALL_CELL_SIZE = CELL_SIZE / 2; - const size_t CELL_MASK = CELL_SIZE - 1; - const size_t CELL_ALIGN_MASK = ~CELL_MASK; - const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(MarkedSpace*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells. - - const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8; - const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t); - - struct CollectorBitmap { - FixedArray<uint32_t, BITMAP_WORDS> bits; - bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } - void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } - bool getset(size_t n) - { - unsigned i = (1 << (n & 0x1F)); - uint32_t& b = bits[n >> 5]; - bool r = !!(b & i); - b |= i; - return r; - } - void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } - void clearAll() { memset(bits.data(), 0, sizeof(bits)); } - ALWAYS_INLINE void advanceToNextPossibleFreeCell(size_t& startCell) - { - if (!~bits[startCell >> 5]) - startCell = (startCell & (~0x1F)) + 32; - else - ++startCell; - } - size_t count(size_t startCell = 0) - { - size_t result = 0; - for ( ; (startCell & 0x1F) != 0; ++startCell) { - if (get(startCell)) - ++result; - } - for (size_t i = startCell >> 5; i < BITMAP_WORDS; ++i) - result += WTF::bitCount(bits[i]); - return result; - } - size_t isEmpty() // Much more efficient than testing count() == 0. - { - for (size_t i = 0; i < BITMAP_WORDS; ++i) - if (bits[i] != 0) - return false; - return true; - } - }; - - struct CollectorCell { - FixedArray<double, CELL_ARRAY_LENGTH> memory; - }; + void clearMarks(MarkedBlock*); - class CollectorBlock { - public: - FixedArray<CollectorCell, CELLS_PER_BLOCK> cells; - CollectorBitmap marked; - Heap* heap; + CollectorHeap m_heap; + size_t m_waterMark; + size_t m_highWaterMark; + JSGlobalData* m_globalData; }; - struct HeapConstants { - static const size_t cellSize = CELL_SIZE; - static const size_t cellsPerBlock = CELLS_PER_BLOCK; - typedef CollectorCell Cell; - typedef CollectorBlock Block; - }; + inline Heap* MarkedSpace::heap(JSCell* cell) + { + return MarkedBlock::blockFor(cell)->heap(); + } - inline CollectorBlock* MarkedSpace::cellBlock(const JSCell* cell) + inline bool MarkedSpace::isMarked(const JSCell* cell) { - return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK); + return MarkedBlock::blockFor(cell)->isMarked(cell); } - inline size_t MarkedSpace::cellOffset(const JSCell* cell) + inline bool MarkedSpace::testAndSetMarked(const JSCell* cell) { - return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE; + return MarkedBlock::blockFor(cell)->testAndSetMarked(cell); } - inline bool MarkedSpace::isCellMarked(const JSCell* cell) + inline void MarkedSpace::setMarked(const JSCell* cell) { - return cellBlock(cell)->marked.get(cellOffset(cell)); + MarkedBlock::blockFor(cell)->setMarked(cell); } - inline bool MarkedSpace::checkMarkCell(const JSCell* cell) + inline bool MarkedSpace::contains(const void* x) { - return cellBlock(cell)->marked.getset(cellOffset(cell)); + if (!MarkedBlock::isCellAligned(x)) + return false; + + MarkedBlock* block = MarkedBlock::blockFor(x); + if (!block) + return false; + + size_t size = m_heap.blocks.size(); + for (size_t i = 0; i < size; i++) { + if (block != m_heap.collectorBlock(i)) + continue; + + // x is a pointer into the heap. Now, verify that the cell it + // points to is live. (If the cell is dead, we must not mark it, + // since that would revive it in a zombie state.) + return block->isMarked(x); + } + + return false; } - inline void MarkedSpace::markCell(JSCell* cell) + template <typename Functor> inline void MarkedSpace::forEach(Functor& functor) { - cellBlock(cell)->marked.set(cellOffset(cell)); + for (size_t i = 0; i < m_heap.blocks.size(); ++i) + m_heap.collectorBlock(i)->forEach(functor); } } // namespace JSC |