Add WIN32 define for MSVC builds.
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 *);
34 // Every object gets two successive mark bits. These bits represent various
35 // states during garbage collection:
37 // WHITE (00): The object is dead or unmarked.
38 // GREY (11): The object is live but its children have not been marked.
39 // BLACK (10): The object and all its children have been marked.
41 // These colors assist in maintaining the "tri-color invariant", explained
42 // in Heap.h. The bits are organized such that transitioning an object from
43 // White to Black requires one bit change, and Black to Grey requires another.
50 MarkBit(uint32 *word, uint32 bit)
54 assert(bit_ < sizeof(*word_) * 8);
58 return !!(*word_ & (1 << bit_));
61 *word_ |= (1 << bit_);
64 *word_ &= ~(1 << bit_);
69 MarkBit next() const {
70 if (bit_ == (sizeof(*word_) * 8) - 1)
71 return MarkBit(word_ + 1, 0);
72 return MarkBit(word_, bit_ + 1);
80 // Base address, from OS::AlignableMapping.
83 // End of the allocated region.
90 HAS_OVERFLOWED_OBJECT = (1 << 0),
95 static const size_t kDefaultSize = 1 * kMB;
96 static const size_t kAlignment = 1 * kMB;
98 // Maximum size of an object that will fit in a page. We limit this
99 // specifically to help JITs: the computation of a[i] has a special
100 // instruction form on most CPUs, but the index might not be sign-
101 // extended on 64-bit architectures. We limit the size such that:
103 // index * sizeof(Object *)
105 // Is guaranteed to not overflow a signed 32-bit integer.
106 static const size_t kMaxObjectSize = INT_MAX / sizeof(Object *);
108 // Size of a HeapChunk header.
109 static const size_t kHeaderSize =
110 sizeof(HeapChunk *) +
115 // All objects must be allocated in the first kAlignment bytes of the
116 // chunk. We need two mark bits for every allocatable object, since there
117 // are three possible states: White (00), Black (11), and Grey (10). These
118 // bits are stored immediately after the HeapChunk header, and before the
119 // first allocatable object.
121 // Although object alignment is only at word boundaries, we guarantee that
122 // every object is at least two words. This means we don't need to reserve
123 // two mark bits for every object, just one mark bit for every allocatable
124 // address. That also means a pair of mark bits can cross a byte boundary.
128 // The number of mark bits needed is:
130 // MaxObjectsPerChunk = (kAlignment / kObjectAlignment)
131 // -> 256KB (128KB on 64-bit)
133 // The number of bytes needed for these mark bits is:
135 // NumMarkBytes = MaxObjectsPerChunk / 8
136 // = 32KB (16KB on 64-bit)
138 // The number of uint32s needed to store these bytes is:
140 // NumMarkWords = NumMarkBytes / sizeof(uint32)
141 // = 8KB (4KB on 64-bit)
143 static const size_t kMaxObjectsPerChunk = kAlignment / kObjectAlignment;
144 static const size_t kMarkBits = kMaxObjectsPerChunk;
145 static const size_t kMarkBytes = kMarkBits / 8;
146 static const size_t kMarkWords = kMarkBytes / sizeof(uint32);
147 static const size_t kMarkBitsPerWord = sizeof(uint32) * 8;
149 static const size_t kMarkBitsOffset = kHeaderSize;
150 static const size_t kFirstObject = kMarkBitsOffset + kMarkBytes;
152 // Threshold for allocating an object in the large object space.
153 static const size_t kLargeObjectThreshold = kAlignment - kFirstObject;
155 static inline void StaticAsserts() {
156 STATIC_ASSERT(kHeaderSize == sizeof(HeapChunk));
157 STATIC_ASSERT(IS_ALIGNED(kHeaderSize, kObjectAlignment));
158 STATIC_ASSERT(IS_ALIGNED(kFirstObject, kObjectAlignment));
162 static HeapChunk *New(HeapChunk *prev, size_t size);
163 static void Destroy(HeapChunk *chunk);
173 return reinterpret_cast<Address>(this);
179 return end() - base();
182 return reinterpret_cast<Address>(this) + kFirstObject;
184 HeapChunk **nextp() {
188 return reinterpret_cast<uint32 *>(reinterpret_cast<Address>(this) + kMarkBitsOffset);
190 void resetMarkBits();
192 // Marking functions.
193 static inline MarkBit GetMarkBit(Object *obj) {
194 uintptr_t address = reinterpret_cast<uintptr_t>(obj);
196 HeapChunk *chunk = reinterpret_cast<HeapChunk *>(address & ~(kAlignment - 1));
197 assert(Address(obj) >= chunk->first() && Address(obj) < chunk->end());
199 size_t index = (address & (kAlignment - 1)) / kObjectAlignment;
200 assert(index < kMaxObjectsPerChunk);
202 uint32 *word = chunk->markBits() + (index / kMarkBitsPerWord);
203 uint32 bit = index & (kMarkBitsPerWord - 1);
204 return MarkBit(word, bit);
206 static inline Address FromMarkBit(HeapChunk *chunk, uint32 *word, uint32 bit) {
207 // word = bits + (index / kMarkBitsPerWord)
208 // word - bits = index / kMarkBitsPerWord
209 // (word - bits) * kMarkBitsPerWord = index
210 assert(word >= chunk->markBits() && word < chunk->markBits() + kMarkWords);
211 size_t index = ((word - chunk->markBits()) * kMarkBitsPerWord) + bit;
212 return chunk->address() + (index * kObjectAlignment);
214 static inline bool IsWhite(const MarkBit &bit) {
215 assert(bit.isSet() || !bit.next().isSet());
218 static inline bool IsBlack(const MarkBit &bit) {
219 return bit.isSet() && !bit.next().isSet();
221 static inline bool IsGrey(const MarkBit &bit) {
222 return bit.isSet() && bit.next().isSet();
224 static inline bool IsBlackOrGrey(const MarkBit &bit) {
227 static inline void WhiteToBlack(MarkBit &bit) {
228 assert(IsWhite(bit));
231 static inline void BlackToGrey(MarkBit &bit) {
232 assert(IsBlack(bit));
235 static inline void GreyToBlack(MarkBit &bit) {
239 static inline void Clear(MarkBit &bit) {
244 bool hasOverflowedObject() {
245 return !!(flags_ & HAS_OVERFLOWED_OBJECT);
247 void setHasOverflowedObject() {
248 flags_ |= HAS_OVERFLOWED_OBJECT;
251 return !!(flags_ & EMPTY);
258 template <typename SizeEvaluator>
259 class ChunkObjectIteratorBase
263 SizeEvaluator evaluator_;
267 ChunkObjectIteratorBase(HeapChunk *start, Address top, const SizeEvaluator &evaluator)
270 evaluator_(evaluator),
271 current_(start ? start->first() : NULL)
285 FreedObject(Map *map, size_t bytes)
289 assert(bytes_ >= sizeof(Map *) + sizeof(size_t));
290 if (bytes_ >= sizeof(FreedObject))
294 void setNext(FreedObject *obj) {
295 assert(bytes_ >= sizeof(FreedObject));
298 FreedObject *next() {
299 assert(bytes_ >= sizeof(FreedObject));
307 // Free-region list used in old spaces. Based on V8's. Each object pool
308 // is used to allocate objects of the previous pool's size. For example,
309 // the medium object pool is used to allocate small objects.
313 static const size_t kMinObjectSize = 32;
314 static const size_t kMaxSmallObject = 255;
315 static const size_t kMaxMediumObject = (2 * kKB) - 1;
316 static const size_t kMaxLargeObject = (16 * kKB) - 1;
322 void add(FreedObject *obj);
323 FreedObject *pick(size_t size);
327 FreedObject *small_objects_;
328 FreedObject *medium_objects_;
329 FreedObject *large_objects_;
330 FreedObject *huge_objects_;
333 // The heap stack is designed for structures which are known to not escape the
334 // program stack, and can thus be quickly allocated in a LIFO manner.
338 OS::AlignableMapping map_;
344 static const size_t kStackSize = 1024 * 1024;
352 Address position() const {
355 inline Address allocate(size_t nbytes);
356 inline void unwind(Address to);
358 inline bool contains(Object *obj) {
359 return (reinterpret_cast<uintptr_t>(obj) & mask_) == reinterpret_cast<uintptr_t>(chunk_);
362 template <typename Evaluator>
363 ChunkObjectIteratorBase<Evaluator> begin(const Evaluator &evaluator) {
364 return ChunkObjectIteratorBase<Evaluator>(chunk_, cursor_, evaluator);
377 OldSpace(Zone *zone);
383 inline Address allocate(size_t nbytes);
384 Address allocateSlow(size_t nbytes);
385 void markRegionFree(Address start, size_t size);
386 void freeUnusedPages();
388 template <typename Evaluator>
389 ChunkObjectIteratorBase<Evaluator> begin(const Evaluator &evaluator) {
390 return ChunkObjectIteratorBase<Evaluator>(first_, cursor_, evaluator);
396 void resetFreeList();
399 class LargeObjectSpace
411 Address allocate(size_t nbytes);
421 #endif // _include_jitcraft_spaces_h_