/* * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Eric Seidel * * 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_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(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 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