2011-02-10 Geoffrey Garen <ggaren@apple.com>
[WebKit-https.git] / Source / JavaScriptCore / runtime / MarkedBlock.h
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifndef MarkedBlock_h
23 #define MarkedBlock_h
24
25 #include <wtf/Bitmap.h>
26 #include <wtf/FixedArray.h>
27 #include <wtf/PageAllocationAligned.h>
28
29 #define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedBlock::CELL_SIZE, class_fits_in_cell)
30
31 namespace JSC {
32
33     class Heap;
34     class JSGlobalData;
35
36     class MarkedBlock {
37 #if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP)
38         static const size_t BLOCK_SIZE = 64 * 1024; // 64k
39 #else
40         static const size_t BLOCK_SIZE = 256 * 1024; // 256k
41 #endif
42
43         static const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
44         static const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK;
45         static const size_t MINIMUM_CELL_SIZE = 64;
46         static const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
47     public:
48         // This is still public for now, for use in assertions.
49         static const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double);
50     private:
51         static const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
52         static const size_t CELL_MASK = CELL_SIZE - 1;
53         static const size_t CELL_ALIGN_MASK = ~CELL_MASK;
54         static const size_t BITS_PER_BLOCK = BLOCK_SIZE / CELL_SIZE;
55         static const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*) - sizeof(WTF::Bitmap<BITS_PER_BLOCK>)) / CELL_SIZE; // Division rounds down intentionally.
56         
57         struct CollectorCell {
58             FixedArray<double, CELL_ARRAY_LENGTH> memory;
59         };
60
61         // Cell size needs to be a power of two for CELL_MASK to be valid.
62         COMPILE_ASSERT(!(sizeof(CollectorCell) % 2), Collector_cell_size_is_power_of_two);
63
64         friend class CollectorHeapIterator;
65
66     public:
67         static MarkedBlock* create(JSGlobalData*);
68         static void destroy(MarkedBlock*);
69
70         static bool isCellAligned(const void*);
71         static MarkedBlock* blockFor(const void*);
72         
73         Heap* heap() const;
74         
75         void* allocate(size_t& nextCell);
76         void sweep();
77         
78         bool isEmpty();
79
80         void clearMarks();
81         size_t markCount();
82         size_t size();
83         size_t capacity();
84
85         size_t cellNumber(const void*);
86         bool isMarked(const void*);
87         bool testAndSetMarked(const void*);
88         void setMarked(const void*);
89
90         FixedArray<CollectorCell, CELLS_PER_BLOCK> cells;
91
92     private:
93         MarkedBlock(const PageAllocationAligned&, JSGlobalData*);
94
95         WTF::Bitmap<BITS_PER_BLOCK> marked;
96         PageAllocationAligned m_allocation;
97         Heap* m_heap;
98     };
99
100     inline bool MarkedBlock::isCellAligned(const void* p)
101     {
102         return !((intptr_t)(p) & CELL_MASK);
103     }
104
105     inline MarkedBlock* MarkedBlock::blockFor(const void* p)
106     {
107         return reinterpret_cast<MarkedBlock*>(reinterpret_cast<uintptr_t>(p) & BLOCK_MASK);
108     }
109
110     inline Heap* MarkedBlock::heap() const
111     {
112         return m_heap;
113     }
114
115     inline bool MarkedBlock::isEmpty()
116     {
117         marked.clear(CELLS_PER_BLOCK - 1); // Clear the always-set last bit to avoid confusing isEmpty().
118         bool result = marked.isEmpty();
119         marked.set(CELLS_PER_BLOCK - 1);
120         return result;
121     }
122
123     inline void MarkedBlock::clearMarks()
124     {
125         // allocate() assumes that the last mark bit is always set.
126         marked.clearAll();
127         marked.set(CELLS_PER_BLOCK - 1);
128     }
129     
130     inline size_t MarkedBlock::markCount()
131     {
132         return marked.count() - 1; // The last mark bit is always set.
133     }
134
135     inline size_t MarkedBlock::size()
136     {
137         return markCount() * CELL_SIZE;
138     }
139
140     inline size_t MarkedBlock::capacity()
141     {
142         return BLOCK_SIZE;
143     }
144
145     inline size_t MarkedBlock::cellNumber(const void* cell)
146     {
147         return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
148     }
149
150     inline bool MarkedBlock::isMarked(const void* cell)
151     {
152         return marked.get(cellNumber(cell));
153     }
154
155     inline bool MarkedBlock::testAndSetMarked(const void* cell)
156     {
157         return marked.testAndSet(cellNumber(cell));
158     }
159
160     inline void MarkedBlock::setMarked(const void* cell)
161     {
162         marked.set(cellNumber(cell));
163     }
164
165 } // namespace JSC
166
167 #endif // MarkedSpace_h