Added clang support. A lot of the motion here is introducing a new offsetof because clang's seems broken?
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/.
23 #include "Spaces-inl.h"
27 HeapStack::HeapStack()
33 HeapStack::~HeapStack()
36 HeapChunk::Destroy(chunk_);
40 HeapStack::initialize()
42 chunk_ = HeapChunk::New(NULL, kStackSize);
43 cursor_ = chunk_->first();
48 HeapChunk::New(HeapChunk *prev, size_t size)
50 OS::AlignableMapping map =
51 OS::MapAlignedMemory(size, HeapChunk::kAlignment, OS::Map_Commit);
56 HeapChunk *chunk = reinterpret_cast<HeapChunk *>(map.aligned());
57 chunk->base_ = map.base();
58 chunk->end_ = map.base() + map.size();
66 HeapChunk::Destroy(HeapChunk *chunk)
68 OS::UnmapAlignedMemory(chunk->base(), chunk->size());
72 HeapChunk::resetMarkBits()
74 memset(markBits(), 0, kMarkBytes);
78 : small_objects_(NULL),
79 medium_objects_(NULL),
86 FreeList::add(FreedObject *obj)
88 if (obj->size() < kMinObjectSize)
92 if (obj->size() < kMaxSmallObject)
93 list = &small_objects_;
94 else if (obj->size() < kMaxMediumObject)
95 list = &medium_objects_;
96 else if (obj->size() < kMaxLargeObject)
97 list = &large_objects_;
99 list = &huge_objects_;
102 (*list)->setNext(obj);
107 FreeList::pick(size_t size)
109 if (size < kMinObjectSize && small_objects_) {
110 FreedObject *obj = small_objects_;
111 small_objects_ = small_objects_->next();
114 if (size < kMaxSmallObject && medium_objects_) {
115 FreedObject *obj = medium_objects_;
116 medium_objects_ = medium_objects_->next();
119 if (size < kMaxMediumObject && large_objects_) {
120 FreedObject *obj = large_objects_;
121 large_objects_ = large_objects_->next();
125 FreedObject *obj = huge_objects_;
126 huge_objects_ = huge_objects_->next();
135 small_objects_ = NULL;
136 medium_objects_ = NULL;
137 large_objects_ = NULL;
138 huge_objects_ = NULL;
141 OldSpace::OldSpace(Zone *zone)
149 OldSpace::initialize()
151 first_ = HeapChunk::New(first_, HeapChunk::kDefaultSize);
153 cursor_ = first_->first();
158 OldSpace::~OldSpace()
161 HeapChunk *temp = first_->next();
162 HeapChunk::Destroy(first_);
168 OldSpace::allocateSlow(size_t nbytes)
170 if (FreedObject *obj = freelist_.pick(nbytes)) {
171 Address address = reinterpret_cast<Address>(obj);
172 size_t actual = obj->size();
173 assert(actual >= nbytes);
174 if (actual != nbytes)
175 markRegionFree(address + nbytes, actual - nbytes);
180 // Free unused stuff at the end of the current chunk.
181 if (cursor_ != last_->end())
182 markRegionFree(cursor_, last_->end() - cursor_);
186 // The next chunk is guaranteed to be empty.
187 chunk = last_->next();
189 chunk = HeapChunk::New(last_, HeapChunk::kDefaultSize);
195 cursor_ = chunk->first();
197 assert(cursor_ + nbytes <= chunk->end());
199 Address address = cursor_;
205 OldSpace::markRegionFree(Address start, size_t length)
207 FreedObject *obj = reinterpret_cast<FreedObject *>(start);
208 new (obj) FreedObject(zone_->getMap(MapKind_FreeRegion), length);
210 if (length < sizeof(FreedObject)) {
211 // Can't encode a list in this object, but it's marked free, so we're done.
219 OldSpace::freeUnusedPages()
221 HeapChunk **prev = &first_;
222 HeapChunk *empty = NULL;
224 HeapChunk *chunk = *prev;
225 if (chunk->isEmpty()) {
226 *prev = chunk->next();
228 // Remove this chunk.
229 HeapChunk::Destroy(chunk);
234 prev = chunk->nextp();
238 *empty->nextp() = NULL;
239 *last_->nextp() = empty;
244 OldSpace::resetFreeList()
249 LargeObjectSpace::LargeObjectSpace()
255 LargeObjectSpace::~LargeObjectSpace()
258 HeapChunk *temp = first_->next();
259 HeapChunk::Destroy(first_);
265 LargeObjectSpace::initialize()
271 LargeObjectSpace::allocate(size_t nbytes)
273 assert(IsAligned(nbytes, kObjectAlignment));
275 // Always allocate a new chunk for large objects.
276 HeapChunk *chunk = HeapChunk::New(last_, nbytes);
284 return chunk->first();
288 LargeObjectSpace::sweep()
293 HeapChunk **pprev = &first_;
295 HeapChunk *chunk = *pprev;
296 Object *obj = reinterpret_cast<Object *>(chunk->first());
297 MarkBit bit = HeapChunk::GetMarkBit(obj);
298 if (HeapChunk::IsWhite(bit)) {
299 *pprev = chunk->next();
300 HeapChunk::Destroy(chunk);
302 assert(HeapChunk::IsBlack(bit));
303 HeapChunk::Clear(bit);
304 pprev = chunk->nextp();