29e332d6de8ad44e6e91940bf541c7158ca16b63
[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_heap.nextCell = 0;
75         m_waterMark += BLOCK_SIZE;
76     } while (++m_heap.nextBlock != m_heap.blocks.size());
77
78     if (m_waterMark < m_highWaterMark)
79         return allocateBlock()->allocate(m_heap.nextCell);
80
81     return 0;
82 }
83
84 void MarkedSpace::shrink()
85 {
86     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.
87         if (m_heap.collectorBlock(i)->isEmpty()) {
88             freeBlock(i);
89         } else
90             ++i;
91     }
92 }
93
94 void MarkedSpace::clearMarks()
95 {
96     for (size_t i = 0; i < m_heap.blocks.size(); ++i)
97         m_heap.collectorBlock(i)->clearMarks();
98 }
99
100 size_t MarkedSpace::markCount() const
101 {
102     size_t result = 0;
103     for (size_t i = 0; i < m_heap.blocks.size(); ++i)
104         result += m_heap.collectorBlock(i)->markCount();
105     return result;
106 }
107
108 void MarkedSpace::sweep()
109 {
110     for (size_t i = 0; i < m_heap.blocks.size(); ++i)
111         m_heap.collectorBlock(i)->sweep();
112 }
113
114 size_t MarkedSpace::objectCount() const
115 {
116     return markCount();
117 }
118
119 size_t MarkedSpace::size() const
120 {
121     return objectCount() * HeapConstants::cellSize;
122 }
123
124 size_t MarkedSpace::capacity() const
125 {
126     return m_heap.blocks.size() * BLOCK_SIZE;
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