|
dvander@49
|
1 |
/* vim: set ts=4 sw=4 tw=99 et: |
|
dvander@49
|
2 |
* |
|
dvander@49
|
3 |
* Copyright (C) 2012 David Anderson |
|
dvander@49
|
4 |
* |
|
dvander@49
|
5 |
* This file is part of JITCraft. |
|
dvander@49
|
6 |
* |
|
dvander@49
|
7 |
* JITCraft is free software: you can redistribute it and/or modify it under |
|
dvander@49
|
8 |
* the terms of the GNU General Public License as published by the Free |
|
dvander@49
|
9 |
* Software Foundation, either version 3 of the License, or (at your option) |
|
dvander@49
|
10 |
* any later version. |
|
dvander@49
|
11 |
* |
|
dvander@49
|
12 |
* Foobar is distributed in the hope that it will be useful, but WITHOUT ANY |
|
dvander@49
|
13 |
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
dvander@49
|
14 |
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
|
dvander@49
|
15 |
* |
|
dvander@49
|
16 |
* You should have received a copy of the GNU General Public License along with |
|
dvander@49
|
17 |
* JITCraft. If not, see http://www.gnu.org/licenses/. |
|
dvander@49
|
18 |
*/ |
|
dvander@49
|
19 |
#ifndef _include_jitcraft_spaces_h_ |
|
dvander@49
|
20 |
#define _include_jitcraft_spaces_h_ |
|
dvander@49
|
21 |
|
|
dvander@49
|
22 |
#include <limits.h> |
|
dvander@49
|
23 |
#include "Utility.h" |
|
dvander@49
|
24 |
#include "Platform.h" |
|
dvander@49
|
25 |
|
|
dvander@59
|
26 |
namespace ke { |
|
dvander@49
|
27 |
|
|
dvander@53
|
28 |
class Zone; |
|
dvander@49
|
29 |
class Object; |
|
dvander@53
|
30 |
class Map; |
|
dvander@49
|
31 |
|
|
dvander@52
|
32 |
static const size_t kObjectAlignment = sizeof(Object *); |
|
dvander@52
|
33 |
|
|
dvander@52
|
34 |
// Every object gets two successive mark bits. These bits represent various |
|
dvander@52
|
35 |
// states during garbage collection: |
|
dvander@52
|
36 |
// |
|
dvander@52
|
37 |
// WHITE (00): The object is dead or unmarked. |
|
dvander@52
|
38 |
// GREY (11): The object is live but its children have not been marked. |
|
dvander@52
|
39 |
// BLACK (10): The object and all its children have been marked. |
|
dvander@52
|
40 |
// |
|
dvander@52
|
41 |
// These colors assist in maintaining the "tri-color invariant", explained |
|
dvander@52
|
42 |
// in Heap.h. The bits are organized such that transitioning an object from |
|
dvander@52
|
43 |
// White to Black requires one bit change, and Black to Grey requires another. |
|
dvander@52
|
44 |
class MarkBit |
|
dvander@52
|
45 |
{ |
|
dvander@52
|
46 |
uint32 *word_; |
|
dvander@52
|
47 |
uint32 bit_; |
|
dvander@52
|
48 |
|
|
dvander@52
|
49 |
public: |
|
dvander@52
|
50 |
MarkBit(uint32 *word, uint32 bit) |
|
dvander@52
|
51 |
: word_(word), |
|
dvander@52
|
52 |
bit_(bit) |
|
dvander@52
|
53 |
{ |
|
dvander@52
|
54 |
assert(bit_ < sizeof(*word_) * 8); |
|
dvander@52
|
55 |
} |
|
dvander@52
|
56 |
|
|
dvander@52
|
57 |
bool isSet() const { |
|
dvander@52
|
58 |
return !!(*word_ & (1 << bit_)); |
|
dvander@52
|
59 |
} |
|
dvander@52
|
60 |
void set() { |
|
dvander@52
|
61 |
*word_ |= (1 << bit_); |
|
dvander@52
|
62 |
} |
|
dvander@53
|
63 |
void unset() { |
|
dvander@53
|
64 |
*word_ &= ~(1 << bit_); |
|
dvander@53
|
65 |
} |
|
dvander@53
|
66 |
uint32 *word() { |
|
dvander@53
|
67 |
return word_; |
|
dvander@53
|
68 |
} |
|
dvander@52
|
69 |
MarkBit next() const { |
|
dvander@52
|
70 |
if (bit_ == (sizeof(*word_) * 8) - 1) |
|
dvander@52
|
71 |
return MarkBit(word_ + 1, 0); |
|
dvander@52
|
72 |
return MarkBit(word_, bit_ + 1); |
|
dvander@52
|
73 |
} |
|
dvander@52
|
74 |
}; |
|
dvander@49
|
75 |
|
|
dvander@11
|
76 |
class HeapChunk |
|
dvander@11
|
77 |
{ |
|
dvander@11
|
78 |
HeapChunk *next_; |
|
dvander@11
|
79 |
|
|
dvander@11
|
80 |
// Base address, from OS::AlignableMapping. |
|
dvander@11
|
81 |
Address base_; |
|
dvander@11
|
82 |
|
|
dvander@11
|
83 |
// End of the allocated region. |
|
dvander@11
|
84 |
Address end_; |
|
dvander@11
|
85 |
|
|
dvander@51
|
86 |
uintptr_t flags_; |
|
dvander@51
|
87 |
|
|
dvander@51
|
88 |
public: |
|
dvander@51
|
89 |
enum Flag { |
|
dvander@53
|
90 |
HAS_OVERFLOWED_OBJECT = (1 << 0), |
|
dvander@53
|
91 |
EMPTY = (1 << 1) |
|
dvander@51
|
92 |
}; |
|
dvander@11
|
93 |
|
|
dvander@11
|
94 |
public: |
|
dvander@49
|
95 |
static const size_t kDefaultSize = 1 * kMB; |
|
dvander@49
|
96 |
static const size_t kAlignment = 1 * kMB; |
|
dvander@49
|
97 |
|
|
dvander@49
|
98 |
// Maximum size of an object that will fit in a page. We limit this |
|
dvander@49
|
99 |
// specifically to help JITs: the computation of a[i] has a special |
|
dvander@49
|
100 |
// instruction form on most CPUs, but the index might not be sign- |
|
dvander@49
|
101 |
// extended on 64-bit architectures. We limit the size such that: |
|
dvander@49
|
102 |
// |
|
dvander@49
|
103 |
// index * sizeof(Object *) |
|
dvander@49
|
104 |
// |
|
dvander@49
|
105 |
// Is guaranteed to not overflow a signed 32-bit integer. |
|
dvander@49
|
106 |
static const size_t kMaxObjectSize = INT_MAX / sizeof(Object *); |
|
dvander@49
|
107 |
|
|
dvander@49
|
108 |
// Size of a HeapChunk header. |
|
dvander@49
|
109 |
static const size_t kHeaderSize = |
|
dvander@49
|
110 |
sizeof(HeapChunk *) + |
|
dvander@49
|
111 |
sizeof(Address) + |
|
dvander@49
|
112 |
sizeof(Address) + |
|
dvander@49
|
113 |
sizeof(Address); |
|
dvander@11
|
114 |
|
|
dvander@11
|
115 |
// All objects must be allocated in the first kAlignment bytes of the |
|
dvander@52
|
116 |
// chunk. We need two mark bits for every allocatable object, since there |
|
dvander@52
|
117 |
// are three possible states: White (00), Black (11), and Grey (10). These |
|
dvander@52
|
118 |
// bits are stored immediately after the HeapChunk header, and before the |
|
dvander@52
|
119 |
// first allocatable object. |
|
dvander@52
|
120 |
// |
|
dvander@52
|
121 |
// Although object alignment is only at word boundaries, we guarantee that |
|
dvander@52
|
122 |
// every object is at least two words. This means we don't need to reserve |
|
dvander@52
|
123 |
// two mark bits for every object, just one mark bit for every allocatable |
|
dvander@52
|
124 |
// address. That also means a pair of mark bits can cross a byte boundary. |
|
dvander@52
|
125 |
// |
|
dvander@52
|
126 |
// --- Math --- |
|
dvander@11
|
127 |
// |
|
dvander@11
|
128 |
// The number of mark bits needed is: |
|
dvander@11
|
129 |
// |
|
dvander@52
|
130 |
// MaxObjectsPerChunk = (kAlignment / kObjectAlignment) |
|
dvander@52
|
131 |
// -> 256KB (128KB on 64-bit) |
|
dvander@11
|
132 |
// |
|
dvander@11
|
133 |
// The number of bytes needed for these mark bits is: |
|
dvander@11
|
134 |
// |
|
dvander@11
|
135 |
// NumMarkBytes = MaxObjectsPerChunk / 8 |
|
dvander@52
|
136 |
// = 32KB (16KB on 64-bit) |
|
dvander@11
|
137 |
// |
|
dvander@11
|
138 |
// The number of uint32s needed to store these bytes is: |
|
dvander@11
|
139 |
// |
|
dvander@11
|
140 |
// NumMarkWords = NumMarkBytes / sizeof(uint32) |
|
dvander@52
|
141 |
// = 8KB (4KB on 64-bit) |
|
dvander@52
|
142 |
// |
|
dvander@11
|
143 |
static const size_t kMaxObjectsPerChunk = kAlignment / kObjectAlignment; |
|
dvander@11
|
144 |
static const size_t kMarkBits = kMaxObjectsPerChunk; |
|
dvander@11
|
145 |
static const size_t kMarkBytes = kMarkBits / 8; |
|
dvander@11
|
146 |
static const size_t kMarkWords = kMarkBytes / sizeof(uint32); |
|
dvander@52
|
147 |
static const size_t kMarkBitsPerWord = sizeof(uint32) * 8; |
|
dvander@11
|
148 |
|
|
dvander@49
|
149 |
static const size_t kMarkBitsOffset = kHeaderSize; |
|
dvander@49
|
150 |
static const size_t kFirstObject = kMarkBitsOffset + kMarkBytes; |
|
dvander@11
|
151 |
|
|
dvander@49
|
152 |
// Threshold for allocating an object in the large object space. |
|
dvander@49
|
153 |
static const size_t kLargeObjectThreshold = kAlignment - kFirstObject; |
|
dvander@49
|
154 |
|
|
dvander@49
|
155 |
static inline void StaticAsserts() { |
|
dvander@49
|
156 |
STATIC_ASSERT(kHeaderSize == sizeof(HeapChunk)); |
|
dvander@49
|
157 |
STATIC_ASSERT(IS_ALIGNED(kHeaderSize, kObjectAlignment)); |
|
dvander@49
|
158 |
STATIC_ASSERT(IS_ALIGNED(kFirstObject, kObjectAlignment)); |
|
dvander@11
|
159 |
} |
|
dvander@11
|
160 |
|
|
dvander@11
|
161 |
public: |
|
dvander@11
|
162 |
static HeapChunk *New(HeapChunk *prev, size_t size); |
|
dvander@11
|
163 |
static void Destroy(HeapChunk *chunk); |
|
dvander@11
|
164 |
|
|
dvander@11
|
165 |
public: |
|
dvander@11
|
166 |
HeapChunk *next() { |
|
dvander@11
|
167 |
return next_; |
|
dvander@11
|
168 |
} |
|
dvander@11
|
169 |
Address base() { |
|
dvander@11
|
170 |
return base_; |
|
dvander@11
|
171 |
} |
|
dvander@53
|
172 |
Address address() { |
|
dvander@53
|
173 |
return reinterpret_cast<Address>(this); |
|
dvander@53
|
174 |
} |
|
dvander@11
|
175 |
Address end() { |
|
dvander@11
|
176 |
return end_; |
|
dvander@11
|
177 |
} |
|
dvander@11
|
178 |
size_t size() { |
|
dvander@11
|
179 |
return end() - base(); |
|
dvander@11
|
180 |
} |
|
dvander@11
|
181 |
Address first() { |
|
dvander@49
|
182 |
return reinterpret_cast<Address>(this) + kFirstObject; |
|
dvander@11
|
183 |
} |
|
dvander@53
|
184 |
HeapChunk **nextp() { |
|
dvander@53
|
185 |
return &next_; |
|
dvander@53
|
186 |
} |
|
dvander@53
|
187 |
uint32 *markBits() { |
|
dvander@53
|
188 |
return reinterpret_cast<uint32 *>(reinterpret_cast<Address>(this) + kMarkBitsOffset); |
|
dvander@53
|
189 |
} |
|
dvander@53
|
190 |
void resetMarkBits(); |
|
dvander@52
|
191 |
|
|
dvander@52
|
192 |
// Marking functions. |
|
dvander@52
|
193 |
static inline MarkBit GetMarkBit(Object *obj) { |
|
dvander@52
|
194 |
uintptr_t address = reinterpret_cast<uintptr_t>(obj); |
|
dvander@52
|
195 |
|
|
dvander@52
|
196 |
HeapChunk *chunk = reinterpret_cast<HeapChunk *>(address & ~(kAlignment - 1)); |
|
dvander@52
|
197 |
assert(Address(obj) >= chunk->first() && Address(obj) < chunk->end()); |
|
dvander@52
|
198 |
|
|
dvander@52
|
199 |
size_t index = (address & (kAlignment - 1)) / kObjectAlignment; |
|
dvander@52
|
200 |
assert(index < kMaxObjectsPerChunk); |
|
dvander@52
|
201 |
|
|
dvander@52
|
202 |
uint32 *word = chunk->markBits() + (index / kMarkBitsPerWord); |
|
dvander@52
|
203 |
uint32 bit = index & (kMarkBitsPerWord - 1); |
|
dvander@52
|
204 |
return MarkBit(word, bit); |
|
dvander@52
|
205 |
} |
|
dvander@53
|
206 |
static inline Address FromMarkBit(HeapChunk *chunk, uint32 *word, uint32 bit) { |
|
dvander@53
|
207 |
// word = bits + (index / kMarkBitsPerWord) |
|
dvander@53
|
208 |
// word - bits = index / kMarkBitsPerWord |
|
dvander@53
|
209 |
// (word - bits) * kMarkBitsPerWord = index |
|
dvander@53
|
210 |
assert(word >= chunk->markBits() && word < chunk->markBits() + kMarkWords); |
|
dvander@86
|
211 |
size_t index = ((word - chunk->markBits()) * kMarkBitsPerWord) + bit; |
|
dvander@53
|
212 |
return chunk->address() + (index * kObjectAlignment); |
|
dvander@53
|
213 |
} |
|
dvander@52
|
214 |
static inline bool IsWhite(const MarkBit &bit) { |
|
dvander@52
|
215 |
assert(bit.isSet() || !bit.next().isSet()); |
|
dvander@52
|
216 |
return !bit.isSet(); |
|
dvander@52
|
217 |
} |
|
dvander@52
|
218 |
static inline bool IsBlack(const MarkBit &bit) { |
|
dvander@52
|
219 |
return bit.isSet() && !bit.next().isSet(); |
|
dvander@52
|
220 |
} |
|
dvander@52
|
221 |
static inline bool IsGrey(const MarkBit &bit) { |
|
dvander@52
|
222 |
return bit.isSet() && bit.next().isSet(); |
|
dvander@52
|
223 |
} |
|
dvander@52
|
224 |
static inline bool IsBlackOrGrey(const MarkBit &bit) { |
|
dvander@52
|
225 |
return bit.isSet(); |
|
dvander@52
|
226 |
} |
|
dvander@52
|
227 |
static inline void WhiteToBlack(MarkBit &bit) { |
|
dvander@52
|
228 |
assert(IsWhite(bit)); |
|
dvander@52
|
229 |
bit.set(); |
|
dvander@52
|
230 |
} |
|
dvander@52
|
231 |
static inline void BlackToGrey(MarkBit &bit) { |
|
dvander@53
|
232 |
assert(IsBlack(bit)); |
|
dvander@53
|
233 |
bit.next().set(); |
|
dvander@53
|
234 |
} |
|
dvander@53
|
235 |
static inline void GreyToBlack(MarkBit &bit) { |
|
dvander@52
|
236 |
assert(IsGrey(bit)); |
|
dvander@53
|
237 |
bit.next().unset(); |
|
dvander@53
|
238 |
} |
|
dvander@53
|
239 |
static inline void Clear(MarkBit &bit) { |
|
dvander@53
|
240 |
bit.unset(); |
|
dvander@53
|
241 |
bit.next().unset(); |
|
dvander@11
|
242 |
} |
|
dvander@51
|
243 |
|
|
dvander@51
|
244 |
bool hasOverflowedObject() { |
|
dvander@51
|
245 |
return !!(flags_ & HAS_OVERFLOWED_OBJECT); |
|
dvander@51
|
246 |
} |
|
dvander@51
|
247 |
void setHasOverflowedObject() { |
|
dvander@51
|
248 |
flags_ |= HAS_OVERFLOWED_OBJECT; |
|
dvander@51
|
249 |
} |
|
dvander@53
|
250 |
bool isEmpty() { |
|
dvander@53
|
251 |
return !!(flags_ & EMPTY); |
|
dvander@53
|
252 |
} |
|
dvander@53
|
253 |
void setEmpty() { |
|
dvander@53
|
254 |
flags_ |= EMPTY; |
|
dvander@53
|
255 |
} |
|
dvander@53
|
256 |
}; |
|
dvander@53
|
257 |
|
|
dvander@53
|
258 |
template <typename SizeEvaluator> |
|
dvander@53
|
259 |
class ChunkObjectIteratorBase |
|
dvander@53
|
260 |
{ |
|
dvander@53
|
261 |
HeapChunk *chunk_; |
|
dvander@53
|
262 |
Address top_; |
|
dvander@53
|
263 |
SizeEvaluator evaluator_; |
|
dvander@53
|
264 |
Address current_; |
|
dvander@53
|
265 |
|
|
dvander@53
|
266 |
public: |
|
dvander@53
|
267 |
ChunkObjectIteratorBase(HeapChunk *start, Address top, const SizeEvaluator &evaluator) |
|
dvander@53
|
268 |
: chunk_(start), |
|
dvander@53
|
269 |
top_(top), |
|
dvander@53
|
270 |
evaluator_(evaluator), |
|
dvander@53
|
271 |
current_(start ? start->first() : NULL) |
|
dvander@53
|
272 |
{ |
|
dvander@53
|
273 |
} |
|
dvander@53
|
274 |
|
|
dvander@53
|
275 |
Object *next() { |
|
dvander@53
|
276 |
while (current_ && current_ != top_) { |
|
dvander@53
|
277 |
Object *obj = reinterpret_cast<Object *>(current_); |
|
dvander@53
|
278 |
size_t size = evaluator_(obj, obj->map()); |
|
dvander@53
|
279 |
current_ += size; |
|
dvander@53
|
280 |
if (current_ == chunk_->end()) { |
|
dvander@53
|
281 |
chunk_ = chunk_->next(); |
|
dvander@53
|
282 |
current_ = chunk_ ? chunk_->first() : NULL; |
|
dvander@53
|
283 |
} |
|
dvander@53
|
284 |
if (obj->is(MapKind_FreeRegion)) |
|
dvander@53
|
285 |
continue; |
|
dvander@53
|
286 |
} |
|
dvander@53
|
287 |
return NULL; |
|
dvander@53
|
288 |
} |
|
dvander@11
|
289 |
}; |
|
dvander@11
|
290 |
|
|
dvander@53
|
291 |
class FreedObject |
|
dvander@52
|
292 |
{ |
|
dvander@53
|
293 |
Map *map_; |
|
dvander@53
|
294 |
size_t bytes_; |
|
dvander@53
|
295 |
FreedObject *next_; |
|
dvander@53
|
296 |
|
|
dvander@53
|
297 |
public: |
|
dvander@53
|
298 |
FreedObject(Map *map, size_t bytes) |
|
dvander@53
|
299 |
: map_(map), |
|
dvander@53
|
300 |
bytes_(bytes) |
|
dvander@53
|
301 |
{ |
|
dvander@53
|
302 |
assert(bytes_ >= sizeof(Map *) + sizeof(size_t)); |
|
dvander@53
|
303 |
if (bytes_ >= sizeof(FreedObject)) |
|
dvander@53
|
304 |
next_ = NULL; |
|
dvander@53
|
305 |
} |
|
dvander@53
|
306 |
|
|
dvander@53
|
307 |
void setNext(FreedObject *obj) { |
|
dvander@53
|
308 |
assert(bytes_ >= sizeof(FreedObject)); |
|
dvander@53
|
309 |
next_ = obj; |
|
dvander@53
|
310 |
} |
|
dvander@53
|
311 |
FreedObject *next() { |
|
dvander@53
|
312 |
assert(bytes_ >= sizeof(FreedObject)); |
|
dvander@53
|
313 |
return next_; |
|
dvander@53
|
314 |
} |
|
dvander@53
|
315 |
size_t size() { |
|
dvander@53
|
316 |
return bytes_; |
|
dvander@53
|
317 |
} |
|
dvander@53
|
318 |
}; |
|
dvander@53
|
319 |
|
|
dvander@53
|
320 |
// Free-region list used in old spaces. Based on V8's. Each object pool |
|
dvander@53
|
321 |
// is used to allocate objects of the previous pool's size. For example, |
|
dvander@53
|
322 |
// the medium object pool is used to allocate small objects. |
|
dvander@53
|
323 |
class FreeList |
|
dvander@53
|
324 |
{ |
|
dvander@53
|
325 |
private: |
|
dvander@53
|
326 |
static const size_t kMinObjectSize = 32; |
|
dvander@53
|
327 |
static const size_t kMaxSmallObject = 255; |
|
dvander@53
|
328 |
static const size_t kMaxMediumObject = (2 * kKB) - 1; |
|
dvander@53
|
329 |
static const size_t kMaxLargeObject = (16 * kKB) - 1; |
|
dvander@53
|
330 |
|
|
dvander@53
|
331 |
public: |
|
dvander@53
|
332 |
FreeList(); |
|
dvander@53
|
333 |
|
|
dvander@53
|
334 |
public: |
|
dvander@53
|
335 |
void add(FreedObject *obj); |
|
dvander@53
|
336 |
FreedObject *pick(size_t size); |
|
dvander@53
|
337 |
void reset(); |
|
dvander@53
|
338 |
|
|
dvander@53
|
339 |
private: |
|
dvander@53
|
340 |
FreedObject *small_objects_; |
|
dvander@53
|
341 |
FreedObject *medium_objects_; |
|
dvander@53
|
342 |
FreedObject *large_objects_; |
|
dvander@53
|
343 |
FreedObject *huge_objects_; |
|
dvander@52
|
344 |
}; |
|
dvander@52
|
345 |
|
|
dvander@51
|
346 |
// The heap stack is designed for structures which are known to not escape the |
|
dvander@51
|
347 |
// program stack, and can thus be quickly allocated in a LIFO manner. |
|
dvander@51
|
348 |
// |
|
dvander@51
|
349 |
class HeapStack |
|
dvander@51
|
350 |
{ |
|
dvander@51
|
351 |
OS::AlignableMapping map_; |
|
dvander@51
|
352 |
HeapChunk *chunk_; |
|
dvander@51
|
353 |
Address cursor_; |
|
dvander@51
|
354 |
uintptr_t mask_; |
|
dvander@51
|
355 |
|
|
dvander@51
|
356 |
private: |
|
dvander@51
|
357 |
static const size_t kStackSize = 1024 * 1024; |
|
dvander@51
|
358 |
|
|
dvander@51
|
359 |
public: |
|
dvander@51
|
360 |
HeapStack(); |
|
dvander@51
|
361 |
~HeapStack(); |
|
dvander@51
|
362 |
bool initialize(); |
|
dvander@51
|
363 |
|
|
dvander@51
|
364 |
public: |
|
dvander@51
|
365 |
Address position() const { |
|
dvander@51
|
366 |
return cursor_; |
|
dvander@51
|
367 |
} |
|
dvander@51
|
368 |
inline Address allocate(size_t nbytes); |
|
dvander@51
|
369 |
inline void unwind(Address to); |
|
dvander@51
|
370 |
|
|
dvander@51
|
371 |
inline bool contains(Object *obj) { |
|
dvander@51
|
372 |
return (reinterpret_cast<uintptr_t>(obj) & mask_) == reinterpret_cast<uintptr_t>(chunk_); |
|
dvander@51
|
373 |
} |
|
dvander@53
|
374 |
|
|
dvander@53
|
375 |
template <typename Evaluator> |
|
dvander@53
|
376 |
ChunkObjectIteratorBase<Evaluator> begin(const Evaluator &evaluator) { |
|
dvander@53
|
377 |
return ChunkObjectIteratorBase<Evaluator>(chunk_, cursor_, evaluator); |
|
dvander@53
|
378 |
} |
|
dvander@51
|
379 |
}; |
|
dvander@51
|
380 |
|
|
dvander@11
|
381 |
class OldSpace |
|
dvander@11
|
382 |
{ |
|
dvander@53
|
383 |
Zone *zone_; |
|
dvander@11
|
384 |
HeapChunk *first_; |
|
dvander@11
|
385 |
HeapChunk *last_; |
|
dvander@51
|
386 |
Address cursor_; |
|
dvander@53
|
387 |
FreeList freelist_; |
|
dvander@11
|
388 |
|
|
dvander@11
|
389 |
public: |
|
dvander@53
|
390 |
OldSpace(Zone *zone); |
|
dvander@11
|
391 |
~OldSpace(); |
|
dvander@11
|
392 |
|
|
dvander@11
|
393 |
bool initialize(); |
|
dvander@11
|
394 |
|
|
dvander@11
|
395 |
public: |
|
dvander@11
|
396 |
inline Address allocate(size_t nbytes); |
|
dvander@11
|
397 |
Address allocateSlow(size_t nbytes); |
|
dvander@53
|
398 |
void markRegionFree(Address start, size_t size); |
|
dvander@53
|
399 |
void freeUnusedPages(); |
|
dvander@53
|
400 |
|
|
dvander@53
|
401 |
template <typename Evaluator> |
|
dvander@53
|
402 |
ChunkObjectIteratorBase<Evaluator> begin(const Evaluator &evaluator) { |
|
dvander@53
|
403 |
return ChunkObjectIteratorBase<Evaluator>(first_, cursor_, evaluator); |
|
dvander@53
|
404 |
} |
|
dvander@53
|
405 |
|
|
dvander@53
|
406 |
HeapChunk *first() { |
|
dvander@53
|
407 |
return first_; |
|
dvander@53
|
408 |
} |
|
dvander@53
|
409 |
void resetFreeList(); |
|
dvander@49
|
410 |
}; |
|
dvander@49
|
411 |
|
|
dvander@49
|
412 |
class LargeObjectSpace |
|
dvander@49
|
413 |
{ |
|
dvander@49
|
414 |
HeapChunk *first_; |
|
dvander@49
|
415 |
HeapChunk *last_; |
|
dvander@49
|
416 |
|
|
dvander@49
|
417 |
public: |
|
dvander@49
|
418 |
LargeObjectSpace(); |
|
dvander@49
|
419 |
~LargeObjectSpace(); |
|
dvander@49
|
420 |
|
|
dvander@49
|
421 |
bool initialize(); |
|
dvander@49
|
422 |
|
|
dvander@49
|
423 |
public: |
|
dvander@49
|
424 |
Address allocate(size_t nbytes); |
|
dvander@53
|
425 |
|
|
dvander@53
|
426 |
HeapChunk *first() { |
|
dvander@53
|
427 |
return first_; |
|
dvander@53
|
428 |
} |
|
dvander@53
|
429 |
void sweep(); |
|
dvander@49
|
430 |
}; |
|
dvander@49
|
431 |
|
|
dvander@49
|
432 |
} |
|
dvander@49
|
433 |
|
|
dvander@49
|
434 |
#endif // _include_jitcraft_spaces_h_ |