]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/MarkedSpace.cpp
405ed571a08bfa4e52d43e63fdb4911226e9eb82
[apple/javascriptcore.git] / heap / 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 "JSGlobalObject.h"
25 #include "JSLock.h"
26 #include "JSObject.h"
27 #include "ScopeChain.h"
28
29 namespace JSC {
30
31 class Structure;
32
33 MarkedSpace::MarkedSpace(Heap* heap)
34 : m_heap(heap)
35 {
36 for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
37 allocatorFor(cellSize).init(heap, this, cellSize, false);
38 destructorAllocatorFor(cellSize).init(heap, this, cellSize, true);
39 }
40
41 for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
42 allocatorFor(cellSize).init(heap, this, cellSize, false);
43 destructorAllocatorFor(cellSize).init(heap, this, cellSize, true);
44 }
45 }
46
47 void MarkedSpace::resetAllocators()
48 {
49 for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
50 allocatorFor(cellSize).reset();
51 destructorAllocatorFor(cellSize).reset();
52 }
53
54 for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
55 allocatorFor(cellSize).reset();
56 destructorAllocatorFor(cellSize).reset();
57 }
58 }
59
60 void MarkedSpace::canonicalizeCellLivenessData()
61 {
62 for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
63 allocatorFor(cellSize).zapFreeList();
64 destructorAllocatorFor(cellSize).zapFreeList();
65 }
66
67 for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
68 allocatorFor(cellSize).zapFreeList();
69 destructorAllocatorFor(cellSize).zapFreeList();
70 }
71 }
72
73 bool MarkedSpace::isPagedOut(double deadline)
74 {
75 for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
76 if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
77 return true;
78 }
79
80 for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
81 if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
82 return true;
83 }
84
85 return false;
86 }
87
88 void MarkedSpace::freeBlocks(MarkedBlock* head)
89 {
90 MarkedBlock* next;
91 for (MarkedBlock* block = head; block; block = next) {
92 next = static_cast<MarkedBlock*>(block->next());
93
94 m_blocks.remove(block);
95 block->sweep();
96
97 m_heap->blockAllocator().deallocate(block);
98 }
99 }
100
101 class TakeIfUnmarked {
102 public:
103 typedef MarkedBlock* ReturnType;
104
105 TakeIfUnmarked(MarkedSpace*);
106 void operator()(MarkedBlock*);
107 ReturnType returnValue();
108
109 private:
110 MarkedSpace* m_markedSpace;
111 DoublyLinkedList<MarkedBlock> m_empties;
112 };
113
114 inline TakeIfUnmarked::TakeIfUnmarked(MarkedSpace* newSpace)
115 : m_markedSpace(newSpace)
116 {
117 }
118
119 inline void TakeIfUnmarked::operator()(MarkedBlock* block)
120 {
121 if (!block->markCountIsZero())
122 return;
123
124 m_markedSpace->allocatorFor(block).removeBlock(block);
125 m_empties.append(block);
126 }
127
128 inline TakeIfUnmarked::ReturnType TakeIfUnmarked::returnValue()
129 {
130 return m_empties.head();
131 }
132
133 void MarkedSpace::shrink()
134 {
135 // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
136 TakeIfUnmarked takeIfUnmarked(this);
137 freeBlocks(forEachBlock(takeIfUnmarked));
138 }
139
140 #if ENABLE(GGC)
141 class GatherDirtyCells {
142 WTF_MAKE_NONCOPYABLE(GatherDirtyCells);
143 public:
144 typedef void* ReturnType;
145
146 explicit GatherDirtyCells(MarkedBlock::DirtyCellVector*);
147 void operator()(MarkedBlock*);
148 ReturnType returnValue() { return 0; }
149
150 private:
151 MarkedBlock::DirtyCellVector* m_dirtyCells;
152 };
153
154 inline GatherDirtyCells::GatherDirtyCells(MarkedBlock::DirtyCellVector* dirtyCells)
155 : m_dirtyCells(dirtyCells)
156 {
157 }
158
159 inline void GatherDirtyCells::operator()(MarkedBlock* block)
160 {
161 block->gatherDirtyCells(*m_dirtyCells);
162 }
163
164 void MarkedSpace::gatherDirtyCells(MarkedBlock::DirtyCellVector& dirtyCells)
165 {
166 GatherDirtyCells gatherDirtyCells(&dirtyCells);
167 forEachBlock(gatherDirtyCells);
168 }
169 #endif
170
171 } // namespace JSC