Home | History | Annotate | Download | only in heap
      1 /*
      2  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      3  *  Copyright (C) 2007 Eric Seidel <eric (at) webkit.org>
      4  *
      5  *  This library is free software; you can redistribute it and/or
      6  *  modify it under the terms of the GNU Lesser General Public
      7  *  License as published by the Free Software Foundation; either
      8  *  version 2 of the License, or (at your option) any later version.
      9  *
     10  *  This library is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  *  Lesser General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU Lesser General Public
     16  *  License along with this library; if not, write to the Free Software
     17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     18  *
     19  */
     20 
     21 #include "config.h"
     22 #include "MarkedSpace.h"
     23 
     24 #include "JSCell.h"
     25 #include "JSGlobalData.h"
     26 #include "JSLock.h"
     27 #include "JSObject.h"
     28 #include "ScopeChain.h"
     29 
     30 namespace JSC {
     31 
     32 class Structure;
     33 
     34 MarkedSpace::MarkedSpace(JSGlobalData* globalData)
     35     : m_waterMark(0)
     36     , m_highWaterMark(0)
     37     , m_globalData(globalData)
     38 {
     39     for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep)
     40         sizeClassFor(cellSize).cellSize = cellSize;
     41 
     42     for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep)
     43         sizeClassFor(cellSize).cellSize = cellSize;
     44 }
     45 
     46 void MarkedSpace::destroy()
     47 {
     48     clearMarks();
     49     shrink();
     50     ASSERT(!size());
     51 }
     52 
     53 MarkedBlock* MarkedSpace::allocateBlock(SizeClass& sizeClass)
     54 {
     55     MarkedBlock* block = MarkedBlock::create(globalData(), sizeClass.cellSize);
     56     sizeClass.blockList.append(block);
     57     sizeClass.nextBlock = block;
     58     m_blocks.add(block);
     59 
     60     return block;
     61 }
     62 
     63 void MarkedSpace::freeBlocks(DoublyLinkedList<MarkedBlock>& blocks)
     64 {
     65     MarkedBlock* next;
     66     for (MarkedBlock* block = blocks.head(); block; block = next) {
     67         next = block->next();
     68 
     69         blocks.remove(block);
     70         m_blocks.remove(block);
     71         MarkedBlock::destroy(block);
     72     }
     73 }
     74 
     75 void* MarkedSpace::allocateFromSizeClass(SizeClass& sizeClass)
     76 {
     77     for (MarkedBlock*& block = sizeClass.nextBlock ; block; block = block->next()) {
     78         if (void* result = block->allocate())
     79             return result;
     80 
     81         m_waterMark += block->capacity();
     82     }
     83 
     84     if (m_waterMark < m_highWaterMark)
     85         return allocateBlock(sizeClass)->allocate();
     86 
     87     return 0;
     88 }
     89 
     90 void MarkedSpace::shrink()
     91 {
     92     // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
     93     DoublyLinkedList<MarkedBlock> empties;
     94 
     95     BlockIterator end = m_blocks.end();
     96     for (BlockIterator it = m_blocks.begin(); it != end; ++it) {
     97         MarkedBlock* block = *it;
     98         if (block->isEmpty()) {
     99             SizeClass& sizeClass = sizeClassFor(block->cellSize());
    100             sizeClass.blockList.remove(block);
    101             sizeClass.nextBlock = sizeClass.blockList.head();
    102             empties.append(block);
    103         }
    104     }
    105 
    106     freeBlocks(empties);
    107     ASSERT(empties.isEmpty());
    108 }
    109 
    110 void MarkedSpace::clearMarks()
    111 {
    112     BlockIterator end = m_blocks.end();
    113     for (BlockIterator it = m_blocks.begin(); it != end; ++it)
    114         (*it)->clearMarks();
    115 }
    116 
    117 void MarkedSpace::sweep()
    118 {
    119     BlockIterator end = m_blocks.end();
    120     for (BlockIterator it = m_blocks.begin(); it != end; ++it)
    121         (*it)->sweep();
    122 }
    123 
    124 size_t MarkedSpace::objectCount() const
    125 {
    126     size_t result = 0;
    127     BlockIterator end = m_blocks.end();
    128     for (BlockIterator it = m_blocks.begin(); it != end; ++it)
    129         result += (*it)->markCount();
    130     return result;
    131 }
    132 
    133 size_t MarkedSpace::size() const
    134 {
    135     size_t result = 0;
    136     BlockIterator end = m_blocks.end();
    137     for (BlockIterator it = m_blocks.begin(); it != end; ++it)
    138         result += (*it)->size();
    139     return result;
    140 }
    141 
    142 size_t MarkedSpace::capacity() const
    143 {
    144     size_t result = 0;
    145     BlockIterator end = m_blocks.end();
    146     for (BlockIterator it = m_blocks.begin(); it != end; ++it)
    147         result += (*it)->capacity();
    148     return result;
    149 }
    150 
    151 void MarkedSpace::reset()
    152 {
    153     m_waterMark = 0;
    154 
    155     for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep)
    156         sizeClassFor(cellSize).reset();
    157 
    158     for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep)
    159         sizeClassFor(cellSize).reset();
    160 
    161     BlockIterator end = m_blocks.end();
    162     for (BlockIterator it = m_blocks.begin(); it != end; ++it)
    163         (*it)->reset();
    164 }
    165 
    166 } // namespace JSC
    167