#include "MarkedSpace.h"
#include "JSGlobalObject.h"
-#include "JSCell.h"
-#include "JSGlobalData.h"
#include "JSLock.h"
#include "JSObject.h"
#include "ScopeChain.h"
class Structure;
-MarkedSpace::MarkedSpace(JSGlobalData* globalData)
- : m_waterMark(0)
- , m_highWaterMark(0)
- , m_globalData(globalData)
+MarkedSpace::MarkedSpace(Heap* heap)
+ : m_heap(heap)
{
- for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep)
- sizeClassFor(cellSize).cellSize = cellSize;
+ for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
+ allocatorFor(cellSize).init(heap, this, cellSize, false);
+ destructorAllocatorFor(cellSize).init(heap, this, cellSize, true);
+ }
- for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep)
- sizeClassFor(cellSize).cellSize = cellSize;
+ for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
+ allocatorFor(cellSize).init(heap, this, cellSize, false);
+ destructorAllocatorFor(cellSize).init(heap, this, cellSize, true);
+ }
}
-void MarkedSpace::destroy()
+void MarkedSpace::resetAllocators()
{
- clearMarks();
- shrink();
- ASSERT(!size());
+ for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
+ allocatorFor(cellSize).reset();
+ destructorAllocatorFor(cellSize).reset();
+ }
+
+ for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
+ allocatorFor(cellSize).reset();
+ destructorAllocatorFor(cellSize).reset();
+ }
}
-MarkedBlock* MarkedSpace::allocateBlock(SizeClass& sizeClass)
+void MarkedSpace::canonicalizeCellLivenessData()
{
- MarkedBlock* block = MarkedBlock::create(globalData(), sizeClass.cellSize);
- sizeClass.blockList.append(block);
- sizeClass.nextBlock = block;
- m_blocks.add(block);
+ for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
+ allocatorFor(cellSize).zapFreeList();
+ destructorAllocatorFor(cellSize).zapFreeList();
+ }
- return block;
+ for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
+ allocatorFor(cellSize).zapFreeList();
+ destructorAllocatorFor(cellSize).zapFreeList();
+ }
}
-void MarkedSpace::freeBlocks(DoublyLinkedList<MarkedBlock>& blocks)
+bool MarkedSpace::isPagedOut(double deadline)
{
- MarkedBlock* next;
- for (MarkedBlock* block = blocks.head(); block; block = next) {
- next = block->next();
+ for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
+ if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
+ return true;
+ }
- blocks.remove(block);
- m_blocks.remove(block);
- MarkedBlock::destroy(block);
+ for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
+ if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
+ return true;
}
+
+ return false;
}
-void* MarkedSpace::allocateFromSizeClass(SizeClass& sizeClass)
+void MarkedSpace::freeBlocks(MarkedBlock* head)
{
- for (MarkedBlock*& block = sizeClass.nextBlock ; block; block = block->next()) {
- if (void* result = block->allocate())
- return result;
+ MarkedBlock* next;
+ for (MarkedBlock* block = head; block; block = next) {
+ next = static_cast<MarkedBlock*>(block->next());
+
+ m_blocks.remove(block);
+ block->sweep();
- m_waterMark += block->capacity();
+ m_heap->blockAllocator().deallocate(block);
}
+}
- if (m_waterMark < m_highWaterMark)
- return allocateBlock(sizeClass)->allocate();
+class TakeIfUnmarked {
+public:
+ typedef MarkedBlock* ReturnType;
+
+ TakeIfUnmarked(MarkedSpace*);
+ void operator()(MarkedBlock*);
+ ReturnType returnValue();
+
+private:
+ MarkedSpace* m_markedSpace;
+ DoublyLinkedList<MarkedBlock> m_empties;
+};
- return 0;
+inline TakeIfUnmarked::TakeIfUnmarked(MarkedSpace* newSpace)
+ : m_markedSpace(newSpace)
+{
}
-void MarkedSpace::shrink()
+inline void TakeIfUnmarked::operator()(MarkedBlock* block)
{
- // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
- DoublyLinkedList<MarkedBlock> empties;
-
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it) {
- MarkedBlock* block = *it;
- if (block->isEmpty()) {
- SizeClass& sizeClass = sizeClassFor(block->cellSize());
- sizeClass.blockList.remove(block);
- sizeClass.nextBlock = sizeClass.blockList.head();
- empties.append(block);
- }
- }
+ if (!block->markCountIsZero())
+ return;
- freeBlocks(empties);
- ASSERT(empties.isEmpty());
+ m_markedSpace->allocatorFor(block).removeBlock(block);
+ m_empties.append(block);
}
-void MarkedSpace::clearMarks()
+inline TakeIfUnmarked::ReturnType TakeIfUnmarked::returnValue()
{
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- (*it)->clearMarks();
+ return m_empties.head();
}
-void MarkedSpace::sweep()
+void MarkedSpace::shrink()
{
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- (*it)->sweep();
+ // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
+ TakeIfUnmarked takeIfUnmarked(this);
+ freeBlocks(forEachBlock(takeIfUnmarked));
}
-size_t MarkedSpace::objectCount() const
-{
- size_t result = 0;
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- result += (*it)->markCount();
- return result;
-}
+#if ENABLE(GGC)
+class GatherDirtyCells {
+ WTF_MAKE_NONCOPYABLE(GatherDirtyCells);
+public:
+ typedef void* ReturnType;
+
+ explicit GatherDirtyCells(MarkedBlock::DirtyCellVector*);
+ void operator()(MarkedBlock*);
+ ReturnType returnValue() { return 0; }
+
+private:
+ MarkedBlock::DirtyCellVector* m_dirtyCells;
+};
-size_t MarkedSpace::size() const
+inline GatherDirtyCells::GatherDirtyCells(MarkedBlock::DirtyCellVector* dirtyCells)
+ : m_dirtyCells(dirtyCells)
{
- size_t result = 0;
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- result += (*it)->size();
- return result;
}
-size_t MarkedSpace::capacity() const
+inline void GatherDirtyCells::operator()(MarkedBlock* block)
{
- size_t result = 0;
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- result += (*it)->capacity();
- return result;
+ block->gatherDirtyCells(*m_dirtyCells);
}
-void MarkedSpace::reset()
+void MarkedSpace::gatherDirtyCells(MarkedBlock::DirtyCellVector& dirtyCells)
{
- m_waterMark = 0;
-
- for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep)
- sizeClassFor(cellSize).reset();
-
- for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep)
- sizeClassFor(cellSize).reset();
-
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- (*it)->reset();
+ GatherDirtyCells gatherDirtyCells(&dirtyCells);
+ forEachBlock(gatherDirtyCells);
}
+#endif
} // namespace JSC