Added a product.version file.
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/.
21 #include "Spaces-inl.h"
22 #include "VirtualObjectVisitor.h"
23 #include "ObjectVisitor.h"
25 #include "StringPool.h"
29 static const size_t kMarkStackSize = 256 * kKB;
31 Heap::Heap(Zone *zone)
42 if (!lifoSpace_.initialize())
44 if (!oldSpace_.initialize())
46 if (!mapSpace_.initialize())
48 if (!largeSpace_.initialize())
51 markStack_ = malloc(kMarkStackSize);
55 if ((metaMap_ = allocateMap(MapKind_Meta, sizeof(Map))) == NULL)
57 metaMap_->init(metaMap_);
68 Heap::allocateMap(MapKind kind, size_t bytes)
70 size_t actualBytes = Align(bytes, kObjectAlignment);
72 Address addr = mapSpace_.allocate(actualBytes);
78 // Note that we use a NULL type initially, and reinterpret-cast to get
79 // the Type pointer, so we can allocate the self-referencing meta type.
80 Object *obj = InitAddressIntoObject(addr, NULL);
81 Map *map = reinterpret_cast<Map *>(obj);
86 // To avoid marking recursively, we use a worklist to manage the marking
87 // process. Algorithm:
89 // (1) While the mark stack is not empty:
90 // (a) Remove object |o| from the mark stack.
91 // (b) For each reference |p| in object |o|,
92 // (i) Mark |p| as Black.
93 // (ii) Push |p| onto the mark stack.
94 // (iv) If the mark stack overflowde, mark |p| as Grey.
96 // We run this algorithm after pushing every root object onto the mark stack.
97 // After all roots have been processed, it may be that the mark stack
98 // overflowed. In this case, we use the following algorithm:
100 // (1) while the mark stack has overflowed:
101 // (a) Search the heap for grey objects, adding as many as possible to the
103 // (b) Run the mark-stack-emptying algorithm above.
105 // This algorithm is guaranteed to terminate, because even if there are more
106 // grey objects than mark stack capacity, we eventually all objects will
107 // become grey, and grey objects are not re-pushed onto the mark stack. Thus,
108 // eventually, all objects will become black.
119 MarkStack(Object **base, Object **end)
127 void pushBlack(Object *ptr) {
128 assert(HeapChunk::IsBlack(HeapChunk::GetMarkBit(ptr)));
130 MarkBit bit = HeapChunk::GetMarkBit(ptr);
131 HeapChunk::BlackToGrey(bit);
142 bool overflowed() const {
146 return base_ == top_;
155 // Iterates over an object's body, pushing its referenced objects onto the
157 class MarkingVisitor : public ObjectVisitor<VirtualObjectVisitor>
162 MarkingVisitor(MarkStack &stack)
167 void visit(Object **ptr) {
173 // If the object is grey, we'll find it later when searching the heap.
174 // If the object is black, it's already been scsanned.
175 MarkBit bit = HeapChunk::GetMarkBit(obj);
176 if (HeapChunk::IsBlackOrGrey(bit))
179 // Place the object in the stack and optimistically mark it black. If
180 // the stack overflows, it'll become grey instead.
181 HeapChunk::WhiteToBlack(bit);
182 stack_.pushBlack(obj);
187 ProcessMarkStack(MarkStack &stack)
189 MarkingVisitor visitor(stack);
191 while (!stack.empty()) {
192 Object *obj = stack.pop();
193 assert(HeapChunk::IsBlack(HeapChunk::GetMarkBit(obj)));
195 visitor.iterate(obj);
199 class RootMarkingVisitor : public VirtualObjectVisitor
202 MarkingVisitor visitor_;
205 RootMarkingVisitor(MarkStack &stack)
211 void visit(Object **ptr) {
212 // Flush the stack after every new root. Note that the root gets pushed
213 // as black; that's okay. If the mark stack overflows, its children are
214 // guaranteed to be at least grey.
216 ProcessMarkStack(stack_);
220 typedef ChunkObjectIteratorBase<ObjectSizeEvaluator> ChunkObjectIterator;
223 EnqueueGreyObject(MarkStack &stack, Object *obj)
225 assert(!stack.overflowed());
226 MarkBit bit = HeapChunk::GetMarkBit(obj);
227 if (HeapChunk::IsGrey(bit)) {
228 HeapChunk::GreyToBlack(bit);
229 stack.pushBlack(obj);
230 return !stack.overflowed();
236 EnqueueGreyObjectsInChunks(MarkStack &stack, ChunkObjectIterator iter)
238 for (Object *obj = iter.next(); obj; obj = iter.next()) {
239 if (!EnqueueGreyObject(stack, obj))
245 EnqueueGreyObjectsInLargeChunks(MarkStack &stack, HeapChunk *first)
247 for (HeapChunk *chunk = first; chunk; chunk = chunk->next()) {
248 Object *obj = reinterpret_cast<Object *>(chunk->first());
249 if (!EnqueueGreyObject(stack, obj))
255 Heap::findGreyObjects(MarkStack &stack)
257 EnqueueGreyObjectsInChunks(stack, lifoSpace_.begin(ObjectSizeEvaluator()));
258 if (stack.overflowed())
261 EnqueueGreyObjectsInChunks(stack, mapSpace_.begin(ObjectSizeEvaluator()));
262 if (stack.overflowed())
265 EnqueueGreyObjectsInChunks(stack, oldSpace_.begin(ObjectSizeEvaluator()));
266 if (stack.overflowed())
269 EnqueueGreyObjectsInLargeChunks(stack, largeSpace_.first());
270 if (stack.overflowed())
277 Object **qbase = reinterpret_cast<Object **>(markStack_);
278 Object **qend = qbase + (kMarkStackSize / sizeof(Object *));
279 MarkStack stack(qbase, qend);
280 RootMarkingVisitor visitor(stack);
282 // Attempt to mark all objects reachable from the root set.
283 zone_->accept(&visitor);
284 assert(stack.empty());
286 // If the stack overflowed, we need to look through the entire heap for
287 // grey objects to rescan. We keep doing this until there are no grey
289 while (stack.overflowed()) {
291 findGreyObjects(stack);
292 ProcessMarkStack(stack);
296 // Use the mark bits to scan for live objects, and mark the regions in
297 // between them as free.
299 SweepOldSpaceChunk(OldSpace *space, HeapChunk *chunk)
301 uint32 *markbits = chunk->markBits();
302 uint32 *markbitsEnd = markbits + HeapChunk::kMarkWords;
303 Address freeStart = chunk->first();
305 // Scoot up to the first usable markword. Since memory is reserved for
306 // mark bits, not all addresses are allocatable, so quite a few of the
307 // initial mark bits are wasted. (1KB of mark bytes on x86.)
308 markbits = HeapChunk::GetMarkBit(reinterpret_cast<Object *>(chunk->first())).word();
310 uint32 bits = *markbits;
313 uint32 bit = FindRightmostBit(bits);
314 Address object = HeapChunk::FromMarkBit(chunk, markbits, bit);
316 assert(object >= freeStart);
317 if (freeStart != object)
318 space->markRegionFree(freeStart, object - freeStart);
320 Object *obj = reinterpret_cast<Object *>(object);
321 freeStart = object + SizeOfObject(obj, obj->map());
323 // Since black is 10, we never need to clear the next bit.
328 if (markbits >= markbitsEnd)
332 if (freeStart == chunk->base())
334 else if (freeStart != chunk->end())
335 space->markRegionFree(freeStart, chunk->end() - freeStart);
339 SweepOldSpace(OldSpace *space)
341 space->resetFreeList();
342 for (HeapChunk *chunk = space->first(); chunk; chunk = chunk->next()) {
343 SweepOldSpaceChunk(space, chunk);
344 chunk->resetMarkBits();
346 space->freeUnusedPages();
352 // Before destroying mark bits, sweep weak roots.
353 zone_->symbols()->sweep();
355 // Note: we don't bother sweeping the LIFO space.
356 SweepOldSpace(&mapSpace_);
357 SweepOldSpace(&oldSpace_);
369 Heap::reportOutOfMemory()
371 zone_->reportOutOfMemory();