2011-02-10 Geoffrey Garen <ggaren@apple.com>
[WebKit-https.git] / Source / JavaScriptCore / runtime / MarkedSpace.cpp
1 /*
2  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3  *  Copyright (C) 2007 Eric Seidel <eric@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 "CollectorHeapIterator.h"
25 #include "JSCell.h"
26 #include "JSGlobalData.h"
27 #include "JSLock.h"
28
29 namespace JSC {
30
31 class Structure;
32
33 MarkedSpace::MarkedSpace(JSGlobalData* globalData)
34     : m_waterMark(0)
35     , m_highWaterMark(0)
36     , m_globalData(globalData)
37 {
38     allocateBlock();
39 }
40
41 void MarkedSpace::destroy()
42 {
43     clearMarks(); // Make sure weak pointers appear dead during destruction.
44
45     while (m_heap.blocks.size())
46         freeBlock(0);
47     m_heap.blocks.clear();
48 }
49
50 NEVER_INLINE MarkedBlock* MarkedSpace::allocateBlock()
51 {
52     MarkedBlock* block = MarkedBlock::create(globalData());
53     m_heap.blocks.append(block);
54     return block;
55 }
56
57 NEVER_INLINE void MarkedSpace::freeBlock(size_t block)
58 {
59     MarkedBlock::destroy(m_heap.blocks[block]);
60
61     // swap with the last block so we compact as we go
62     m_heap.blocks[block] = m_heap.blocks.last();
63     m_heap.blocks.removeLast();
64 }
65
66 void* MarkedSpace::allocate(size_t)
67 {
68     do {
69         ASSERT(m_heap.nextBlock < m_heap.blocks.size());
70         MarkedBlock* block = m_heap.collectorBlock(m_heap.nextBlock);
71         if (void* result = block->allocate(m_heap.nextCell))
72             return result;
73
74         m_waterMark += block->capacity();
75     } while (++m_heap.nextBlock != m_heap.blocks.size());
76
77     if (m_waterMark < m_highWaterMark)
78         return allocateBlock()->allocate(m_heap.nextCell);
79
80     return 0;
81 }
82
83 void MarkedSpace::shrink()
84 {
85     for (size_t i = 0; i != m_heap.blocks.size() && m_heap.blocks.size() > 1; ) { // We assume at least one block exists at all times.
86         if (m_heap.collectorBlock(i)->isEmpty()) {
87             freeBlock(i);
88         } else
89             ++i;
90     }
91 }
92
93 void MarkedSpace::clearMarks()
94 {
95     for (size_t i = 0; i < m_heap.blocks.size(); ++i)
96         m_heap.collectorBlock(i)->clearMarks();
97 }
98
99 void MarkedSpace::sweep()
100 {
101     for (size_t i = 0; i < m_heap.blocks.size(); ++i)
102         m_heap.collectorBlock(i)->sweep();
103 }
104
105 size_t MarkedSpace::objectCount() const
106 {
107     size_t result = 0;
108     for (size_t i = 0; i < m_heap.blocks.size(); ++i)
109         result += m_heap.collectorBlock(i)->markCount();
110     return result;
111 }
112
113 size_t MarkedSpace::size() const
114 {
115     size_t result = 0;
116     for (size_t i = 0; i < m_heap.blocks.size(); ++i)
117         result += m_heap.collectorBlock(i)->size();
118     return result;
119 }
120
121 size_t MarkedSpace::capacity() const
122 {
123     size_t result = 0;
124     for (size_t i = 0; i < m_heap.blocks.size(); ++i)
125         result += m_heap.collectorBlock(i)->capacity();
126     return result;
127 }
128
129 void MarkedSpace::reset()
130 {
131     m_heap.nextCell = 0;
132     m_heap.nextBlock = 0;
133     m_waterMark = 0;
134 #if ENABLE(JSC_ZOMBIES)
135     sweep();
136 #endif
137 }
138
139 LiveObjectIterator MarkedSpace::primaryHeapBegin()
140 {
141     return LiveObjectIterator(m_heap, 0, 0);
142 }
143
144 LiveObjectIterator MarkedSpace::primaryHeapEnd()
145 {
146     return LiveObjectIterator(m_heap, m_heap.blocks.size(), 0);
147 }
148
149 } // namespace JSC