#include "config.h"
#include "MarkedSpace.h"
#include "JSGlobalObject.h"
#include "JSLock.h"
#include "JSObject.h"
#include "ScopeChain.h"
namespace JSC {
class Structure;
MarkedSpace::MarkedSpace(Heap* heap)
: m_heap(heap)
{
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) {
allocatorFor(cellSize).init(heap, this, cellSize, false);
destructorAllocatorFor(cellSize).init(heap, this, cellSize, true);
}
}
void MarkedSpace::resetAllocators()
{
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();
}
}
void MarkedSpace::canonicalizeCellLivenessData()
{
for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
allocatorFor(cellSize).zapFreeList();
destructorAllocatorFor(cellSize).zapFreeList();
}
for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
allocatorFor(cellSize).zapFreeList();
destructorAllocatorFor(cellSize).zapFreeList();
}
}
bool MarkedSpace::isPagedOut(double deadline)
{
for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
return true;
}
for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
return true;
}
return false;
}
void MarkedSpace::freeBlocks(MarkedBlock* head)
{
MarkedBlock* next;
for (MarkedBlock* block = head; block; block = next) {
next = static_cast<MarkedBlock*>(block->next());
m_blocks.remove(block);
block->sweep();
m_heap->blockAllocator().deallocate(block);
}
}
class TakeIfUnmarked {
public:
typedef MarkedBlock* ReturnType;
TakeIfUnmarked(MarkedSpace*);
void operator()(MarkedBlock*);
ReturnType returnValue();
private:
MarkedSpace* m_markedSpace;
DoublyLinkedList<MarkedBlock> m_empties;
};
inline TakeIfUnmarked::TakeIfUnmarked(MarkedSpace* newSpace)
: m_markedSpace(newSpace)
{
}
inline void TakeIfUnmarked::operator()(MarkedBlock* block)
{
if (!block->markCountIsZero())
return;
m_markedSpace->allocatorFor(block).removeBlock(block);
m_empties.append(block);
}
inline TakeIfUnmarked::ReturnType TakeIfUnmarked::returnValue()
{
return m_empties.head();
}
void MarkedSpace::shrink()
{
TakeIfUnmarked takeIfUnmarked(this);
freeBlocks(forEachBlock(takeIfUnmarked));
}
#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;
};
inline GatherDirtyCells::GatherDirtyCells(MarkedBlock::DirtyCellVector* dirtyCells)
: m_dirtyCells(dirtyCells)
{
}
inline void GatherDirtyCells::operator()(MarkedBlock* block)
{
block->gatherDirtyCells(*m_dirtyCells);
}
void MarkedSpace::gatherDirtyCells(MarkedBlock::DirtyCellVector& dirtyCells)
{
GatherDirtyCells gatherDirtyCells(&dirtyCells);
forEachBlock(gatherDirtyCells);
}
#endif
}