blob: bf839011d2068bf7b7e0da098dfd02cc676fbf2c [file] [log] [blame]
/*
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
*
* 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
*
*/
#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_waterMark(0)
, m_nurseryWaterMark(0)
, 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()
{
m_waterMark = 0;
m_nurseryWaterMark = 0;
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();
}
}
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();
MutexLocker locker(m_heap->m_freeBlockLock);
m_heap->m_freeBlocks.append(block);
m_heap->m_numberOfFreeBlocks++;
}
}
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()
{
// We record a temporary list of empties to avoid modifying m_blocks while iterating it.
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
} // namespace JSC