36bca9556d4922302341e13f6e23c80f0e77dc6e
[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 namespace JSC {
30
31     class Heap;
32     class JSGlobalData;
33
34 #if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP)
35     const size_t BLOCK_SIZE = 64 * 1024; // 64k
36 #else
37     const size_t BLOCK_SIZE = 256 * 1024; // 256k
38 #endif
39
40     const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
41     const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK;
42     const size_t MINIMUM_CELL_SIZE = 64;
43     const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
44     const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double);
45     const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
46     const size_t CELL_MASK = CELL_SIZE - 1;
47     const size_t CELL_ALIGN_MASK = ~CELL_MASK;
48     const size_t BITS_PER_BLOCK = BLOCK_SIZE / CELL_SIZE;
49     const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*) - sizeof(WTF::Bitmap<BITS_PER_BLOCK>)) / CELL_SIZE; // Division rounds down intentionally.
50     
51     struct CollectorCell {
52         FixedArray<double, CELL_ARRAY_LENGTH> memory;
53     };
54
55     // Cell size needs to be a power of two for CELL_MASK to be valid.
56     COMPILE_ASSERT(!(sizeof(CollectorCell) % 2), Collector_cell_size_is_power_of_two);
57
58     class MarkedBlock {
59         friend class CollectorHeapIterator;
60
61     public:
62         static MarkedBlock* create(JSGlobalData*);
63         static void destroy(MarkedBlock*);
64
65         static bool isCellAligned(const void*);
66         static MarkedBlock* blockFor(const void*);
67         
68         Heap* heap() const;
69         
70         void* allocate(size_t& nextCell);
71         void sweep();
72         
73         bool isEmpty();
74
75         void clearMarks();
76         size_t markCount();
77
78         size_t cellNumber(const void*);
79         bool isMarked(const void*);
80         bool testAndSetMarked(const void*);
81         void setMarked(const void*);
82
83         FixedArray<CollectorCell, CELLS_PER_BLOCK> cells;
84
85     private:
86         MarkedBlock(const PageAllocationAligned&, JSGlobalData*);
87
88         WTF::Bitmap<BITS_PER_BLOCK> marked;
89         PageAllocationAligned m_allocation;
90         Heap* m_heap;
91     };
92
93     struct HeapConstants {
94         static const size_t cellSize = CELL_SIZE;
95         static const size_t cellsPerBlock = CELLS_PER_BLOCK;
96         typedef CollectorCell Cell;
97         typedef MarkedBlock Block;
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(HeapConstants::cellsPerBlock - 1); // Clear the always-set last bit to avoid confusing isEmpty().
118         bool result = marked.isEmpty();
119         marked.set(HeapConstants::cellsPerBlock - 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(HeapConstants::cellsPerBlock - 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::cellNumber(const void* cell)
136     {
137         return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
138     }
139
140     inline bool MarkedBlock::isMarked(const void* cell)
141     {
142         return marked.get(cellNumber(cell));
143     }
144
145     inline bool MarkedBlock::testAndSetMarked(const void* cell)
146     {
147         return marked.testAndSet(cellNumber(cell));
148     }
149
150     inline void MarkedBlock::setMarked(const void* cell)
151     {
152         marked.set(cellNumber(cell));
153     }
154
155 } // namespace JSC
156
157 #endif // MarkedSpace_h