Fix warnings when building with clang.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
7 * JITCraft is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation, either version 3 of the License, or (at your option)
12 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * JITCraft. If not, see http://www.gnu.org/licenses/.
19 #ifndef _include_jitcraft_spaces_h_
20 #define _include_jitcraft_spaces_h_
32 static const size_t kObjectAlignment = sizeof(Object *);
33 static const size_t kMinObjectSize = sizeof(Object *) * 2;
35 // Every object gets two successive mark bits. These bits represent various
36 // states during garbage collection:
38 // WHITE (00): The object is dead or unmarked.
39 // GREY (11): The object is live but its children have not been marked.
40 // BLACK (10): The object and all its children have been marked.
42 // These colors assist in maintaining the "tri-color invariant", explained
43 // in Heap.h. The bits are organized such that transitioning an object from
44 // White to Black requires one bit change, and Black to Grey requires another.
51 MarkBit(uint32 *word, uint32 bit)
55 assert(bit_ < sizeof(*word_) * 8);
59 return !!(*word_ & (1 << bit_));
62 *word_ |= (1 << bit_);
65 *word_ &= ~(1 << bit_);
70 MarkBit next() const {
71 if (bit_ == (sizeof(*word_) * 8) - 1)
72 return MarkBit(word_ + 1, 0);
73 return MarkBit(word_, bit_ + 1);
81 // Base address, from OS::AlignableMapping.
84 // End of the allocated region.
91 HAS_OVERFLOWED_OBJECT = (1 << 0),
96 static const size_t kDefaultSize = 1 * kMB;
97 static const size_t kAlignment = 1 * kMB;
99 // Maximum size of an object that will fit in a page. We limit this
100 // specifically to help JITs: the computation of a[i] has a special
101 // instruction form on most CPUs, but the index might not be sign-
102 // extended on 64-bit architectures. We limit the size such that:
104 // index * sizeof(Object *)
106 // Is guaranteed to not overflow a signed 32-bit integer.
107 static const size_t kMaxObjectSize = INT_MAX / sizeof(Object *);
109 // Size of a HeapChunk header.
110 static const size_t kHeaderSize =
111 sizeof(HeapChunk *) +
116 // All objects must be allocated in the first kAlignment bytes of the
117 // chunk. We need two mark bits for every allocatable object, since there
118 // are three possible states: White (00), Black (11), and Grey (10). These
119 // bits are stored immediately after the HeapChunk header, and before the
120 // first allocatable object.
122 // Although object alignment is only at word boundaries, we guarantee that
123 // every object is at least two words. This means we don't need to reserve
124 // two mark bits for every object, just one mark bit for every allocatable
125 // address. That also means a pair of mark bits can cross a byte boundary.
129 // The number of mark bits needed is:
131 // MaxObjectsPerChunk = (kAlignment / kObjectAlignment)
132 // -> 256KB (128KB on 64-bit)
134 // The number of bytes needed for these mark bits is:
136 // NumMarkBytes = MaxObjectsPerChunk / 8
137 // = 32KB (16KB on 64-bit)
139 // The number of uint32s needed to store these bytes is:
141 // NumMarkWords = NumMarkBytes / sizeof(uint32)
142 // = 8KB (4KB on 64-bit)
144 static const size_t kMaxObjectsPerChunk = kAlignment / kObjectAlignment;
145 static const size_t kMarkBits = kMaxObjectsPerChunk;
146 static const size_t kMarkBytes = kMarkBits / 8;
147 static const size_t kMarkWords = kMarkBytes / sizeof(uint32);
148 static const size_t kMarkBitsPerWord = sizeof(uint32) * 8;
150 static const size_t kMarkBitsOffset = kHeaderSize;
151 static const size_t kFirstObject = kMarkBitsOffset + kMarkBytes;
153 // Threshold for allocating an object in the large object space.
154 static const size_t kLargeObjectThreshold = kAlignment - kFirstObject;
156 static inline void StaticAsserts() {
157 STATIC_ASSERT(kHeaderSize == sizeof(HeapChunk));
158 STATIC_ASSERT(IS_ALIGNED(kHeaderSize, kObjectAlignment));
159 STATIC_ASSERT(IS_ALIGNED(kFirstObject, kObjectAlignment));
163 static HeapChunk *New(HeapChunk *prev, size_t size);
164 static void Destroy(HeapChunk *chunk);
174 return reinterpret_cast<Address>(this);
180 return end() - base();
183 return reinterpret_cast<Address>(this) + kFirstObject;
185 HeapChunk **nextp() {
189 return reinterpret_cast<uint32 *>(reinterpret_cast<Address>(this) + kMarkBitsOffset);
191 void resetMarkBits();
193 // Marking functions.
194 static inline MarkBit GetMarkBit(Object *obj) {
195 uintptr_t address = reinterpret_cast<uintptr_t>(obj);
197 HeapChunk *chunk = reinterpret_cast<HeapChunk *>(address & ~(kAlignment - 1));
198 assert(Address(obj) >= chunk->first() && Address(obj) < chunk->end());
200 size_t index = (address & (kAlignment - 1)) / kObjectAlignment;
201 assert(index < kMaxObjectsPerChunk);
203 uint32 *word = chunk->markBits() + (index / kMarkBitsPerWord);
204 uint32 bit = index & (kMarkBitsPerWord - 1);
205 return MarkBit(word, bit);
207 static inline Address FromMarkBit(HeapChunk *chunk, uint32 *word, uint32 bit) {
208 // word = bits + (index / kMarkBitsPerWord)
209 // word - bits = index / kMarkBitsPerWord
210 // (word - bits) * kMarkBitsPerWord = index
211 assert(word >= chunk->markBits() && word < chunk->markBits() + kMarkWords);
212 size_t index = ((word - chunk->markBits()) * kMarkBitsPerWord) + bit;
213 return chunk->address() + (index * kObjectAlignment);
215 static inline bool IsWhite(const MarkBit &bit) {
216 assert(bit.isSet() || !bit.next().isSet());
219 static inline bool IsBlack(const MarkBit &bit) {
220 return bit.isSet() && !bit.next().isSet();
222 static inline bool IsGrey(const MarkBit &bit) {
223 return bit.isSet() && bit.next().isSet();
225 static inline bool IsBlackOrGrey(const MarkBit &bit) {
228 static inline void WhiteToBlack(MarkBit &bit) {
229 assert(IsWhite(bit));
232 static inline void BlackToGrey(MarkBit &bit) {
233 assert(IsBlack(bit));
236 static inline void GreyToBlack(MarkBit &bit) {
240 static inline void Clear(MarkBit &bit) {
245 bool hasOverflowedObject() {
246 return !!(flags_ & HAS_OVERFLOWED_OBJECT);
248 void setHasOverflowedObject() {
249 flags_ |= HAS_OVERFLOWED_OBJECT;
252 return !!(flags_ & EMPTY);
259 template <typename SizeEvaluator>
260 class ChunkObjectIteratorBase
264 SizeEvaluator evaluator_;
268 ChunkObjectIteratorBase(HeapChunk *start, Address top, const SizeEvaluator &evaluator)
271 evaluator_(evaluator),
272 current_(start ? start->first() : NULL)
287 FreedObject(Map *map, size_t bytes)
291 assert(bytes_ >= sizeof(Map *) + sizeof(size_t));
292 if (bytes_ >= sizeof(FreedObject))
296 void setNext(FreedObject *obj) {
297 assert(bytes_ >= sizeof(FreedObject));
300 FreedObject *next() {
301 assert(bytes_ >= sizeof(FreedObject));
309 // Free-region list used in old spaces. Based on V8's. Each object pool
310 // is used to allocate objects of the previous pool's size. For example,
311 // the medium object pool is used to allocate small objects.
315 static const size_t kMinObjectSize = 32;
316 static const size_t kMaxSmallObject = 255;
317 static const size_t kMaxMediumObject = (2 * kKB) - 1;
318 static const size_t kMaxLargeObject = (16 * kKB) - 1;
324 void add(FreedObject *obj);
325 FreedObject *pick(size_t size);
329 FreedObject *small_objects_;
330 FreedObject *medium_objects_;
331 FreedObject *large_objects_;
332 FreedObject *huge_objects_;
335 // The heap stack is designed for structures which are known to not escape the
336 // program stack, and can thus be quickly allocated in a LIFO manner.
340 OS::AlignableMapping map_;
346 static const size_t kStackSize = 1024 * 1024;
354 Address position() const {
357 inline Address allocate(size_t nbytes);
358 inline void unwind(Address to);
360 inline bool contains(Object *obj) {
361 return (reinterpret_cast<uintptr_t>(obj) & mask_) == reinterpret_cast<uintptr_t>(chunk_);
364 template <typename Evaluator>
365 ChunkObjectIteratorBase<Evaluator> begin(const Evaluator &evaluator) {
366 return ChunkObjectIteratorBase<Evaluator>(chunk_, cursor_, evaluator);
379 OldSpace(Zone *zone);
385 inline Address allocate(size_t nbytes);
386 Address allocateSlow(size_t nbytes);
387 void markRegionFree(Address start, size_t size);
388 void freeUnusedPages();
390 template <typename Evaluator>
391 ChunkObjectIteratorBase<Evaluator> begin(const Evaluator &evaluator) {
392 return ChunkObjectIteratorBase<Evaluator>(first_, cursor_, evaluator);
398 void resetFreeList();
401 class LargeObjectSpace
413 Address allocate(size_t nbytes);
423 #endif // _include_jitcraft_spaces_h_