49
49
enum OperationInProgress { NoOperation, Allocation, Collection };
50
enum HeapType { PrimaryHeap, NumberHeap };
52
template <HeapType> class CollectorHeapIterator;
51
class LiveObjectIterator;
54
53
struct CollectorHeap {
55
56
CollectorBlock** blocks;
58
size_t firstBlockWithPossibleSpace;
60
size_t numLiveObjects;
61
size_t numLiveObjectsAtLastCollect;
64
66
OperationInProgress operationInProgress;
67
69
class Heap : public Noncopyable {
70
typedef CollectorHeapIterator<PrimaryHeap> iterator;
74
75
void* allocateNumber(size_t);
75
76
void* allocate(size_t);
78
78
bool isBusy(); // true if an allocation or collection is in progress
79
void collectAllGarbage();
80
static const size_t minExtraCostSize = 256;
81
static const size_t minExtraCost = 256;
82
static const size_t maxExtraCost = 1024 * 1024;
82
84
void reportExtraMemoryCost(size_t cost);
86
size_t objectCount() const;
85
87
struct Statistics {
111
113
JSGlobalData* globalData() const { return m_globalData; }
112
114
static bool isNumber(JSCell*);
114
// Iterators for the object heap.
115
iterator primaryHeapBegin();
116
iterator primaryHeapEnd();
116
LiveObjectIterator primaryHeapBegin();
117
LiveObjectIterator primaryHeapEnd();
119
template <HeapType heapType> void* heapAllocate(size_t);
120
template <HeapType heapType> size_t sweep();
121
122
static CollectorBlock* cellBlock(const JSCell*);
122
123
static size_t cellOffset(const JSCell*);
125
126
Heap(JSGlobalData*);
128
template <HeapType heapType> NEVER_INLINE CollectorBlock* allocateBlock();
129
template <HeapType heapType> NEVER_INLINE void freeBlock(size_t);
130
NEVER_INLINE void freeBlock(CollectorBlock*);
131
void freeBlocks(CollectorHeap*);
129
NEVER_INLINE CollectorBlock* allocateBlock();
130
NEVER_INLINE void freeBlock(size_t);
131
NEVER_INLINE void freeBlockPtr(CollectorBlock*);
134
void growBlocks(size_t neededBlocks);
135
void shrinkBlocks(size_t neededBlocks);
136
void clearMarkBits();
137
void clearMarkBits(CollectorBlock*);
138
size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const;
133
140
void recordExtraCost(size_t);
142
void addToStatistics(Statistics&) const;
134
145
void markProtectedObjects(MarkStack&);
135
146
void markCurrentThreadConservatively(MarkStack&);
136
147
void markCurrentThreadConservativelyInternal(MarkStack&);
186
196
const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
187
197
const size_t CELL_MASK = CELL_SIZE - 1;
188
198
const size_t CELL_ALIGN_MASK = ~CELL_MASK;
189
const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2);
190
const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK;
199
const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells.
191
201
const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
192
202
const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
194
204
struct CollectorBitmap {
195
205
uint32_t bits[BITMAP_WORDS];
196
206
bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); }
197
207
void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); }
198
208
void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); }
199
209
void clearAll() { memset(bits, 0, sizeof(bits)); }
210
size_t count(size_t startCell = 0)
213
for ( ; (startCell & 0x1F) != 0; ++startCell) {
217
for (size_t i = startCell >> 5; i < BITMAP_WORDS; ++i)
218
result += WTF::bitCount(bits[i]);
221
size_t isEmpty() // Much more efficient than testing count() == 0.
223
for (size_t i = 0; i < BITMAP_WORDS; ++i)
202
230
struct CollectorCell {
204
double memory[CELL_ARRAY_LENGTH];
212
struct SmallCollectorCell {
214
double memory[CELL_ARRAY_LENGTH / 2];
231
double memory[CELL_ARRAY_LENGTH];
222
234
class CollectorBlock {
224
236
CollectorCell cells[CELLS_PER_BLOCK];
226
CollectorCell* freeList;
227
CollectorBitmap marked;
232
class SmallCellCollectorBlock {
234
SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK];
236
SmallCollectorCell* freeList;
237
CollectorBitmap marked;
242
template <HeapType heapType> struct HeapConstants;
244
template <> struct HeapConstants<PrimaryHeap> {
237
CollectorBitmap marked;
241
struct HeapConstants {
245
242
static const size_t cellSize = CELL_SIZE;
246
243
static const size_t cellsPerBlock = CELLS_PER_BLOCK;
247
static const size_t bitmapShift = 0;
248
244
typedef CollectorCell Cell;
249
245
typedef CollectorBlock Block;
252
template <> struct HeapConstants<NumberHeap> {
253
static const size_t cellSize = SMALL_CELL_SIZE;
254
static const size_t cellsPerBlock = SMALL_CELLS_PER_BLOCK;
255
static const size_t bitmapShift = 1;
256
typedef SmallCollectorCell Cell;
257
typedef SmallCellCollectorBlock Block;
260
248
inline CollectorBlock* Heap::cellBlock(const JSCell* cell)
262
250
return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK);
265
inline bool Heap::isNumber(JSCell* cell)
267
return Heap::cellBlock(cell)->type == NumberHeap;
270
253
inline size_t Heap::cellOffset(const JSCell* cell)
272
255
return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
285
268
inline void Heap::reportExtraMemoryCost(size_t cost)
287
if (cost > minExtraCostSize)
288
recordExtraCost(cost / (CELL_SIZE * 2));
270
if (cost > minExtraCost)
271
recordExtraCost(cost);
274
inline void* Heap::allocateNumber(size_t s)
276
if (void* result = m_heap.nextNumber) {
277
m_heap.nextNumber = 0;
281
void* result = allocate(s);
282
m_heap.nextNumber = static_cast<char*>(result) + (CELL_SIZE / 2);
291
286
} // namespace JSC