1.1 --- a/jitcraft/Spaces.cpp Sat Jul 07 01:45:33 2012 -0400
1.2 +++ b/jitcraft/Spaces.cpp Sat Jul 07 17:11:31 2012 -0700
1.3 @@ -16,6 +16,7 @@
1.4 * You should have received a copy of the GNU General Public License along with
1.5 * JITCraft. If not, see http://www.gnu.org/licenses/.
1.6 */
1.7 +#include "Zone.h"
1.8 #include "Spaces.h"
1.9 #include "Platform.h"
1.10 #include "Spaces-inl.h"
1.11 @@ -66,8 +67,79 @@
1.12 OS::UnmapAlignedMemory(chunk->base(), chunk->size());
1.13 }
1.14
1.15 -OldSpace::OldSpace()
1.16 - : first_(NULL),
1.17 +void
1.18 +HeapChunk::resetMarkBits()
1.19 +{
1.20 + memset(markBits(), 0, kMarkBytes);
1.21 +}
1.22 +
1.23 +FreeList::FreeList()
1.24 + : small_objects_(NULL),
1.25 + medium_objects_(NULL),
1.26 + large_objects_(NULL),
1.27 + huge_objects_(NULL)
1.28 +{
1.29 +}
1.30 +
1.31 +void
1.32 +FreeList::add(FreedObject *obj)
1.33 +{
1.34 + if (obj->size() < kMinObjectSize)
1.35 + return;
1.36 +
1.37 + FreedObject **list;
1.38 + if (obj->size() < kMaxSmallObject)
1.39 + list = &small_objects_;
1.40 + else if (obj->size() < kMaxMediumObject)
1.41 + list = &medium_objects_;
1.42 + else if (obj->size() < kMaxLargeObject)
1.43 + list = &large_objects_;
1.44 + else
1.45 + list = &huge_objects_;
1.46 +
1.47 + if (*list)
1.48 + (*list)->setNext(obj);
1.49 + *list = obj;
1.50 +}
1.51 +
1.52 +FreedObject *
1.53 +FreeList::pick(size_t size)
1.54 +{
1.55 + if (size < kMinObjectSize && small_objects_) {
1.56 + FreedObject *obj = small_objects_;
1.57 + small_objects_ = small_objects_->next();
1.58 + return obj;
1.59 + }
1.60 + if (size < kMaxSmallObject && medium_objects_) {
1.61 + FreedObject *obj = medium_objects_;
1.62 + medium_objects_ = medium_objects_->next();
1.63 + return obj;
1.64 + }
1.65 + if (size < kMaxMediumObject && large_objects_) {
1.66 + FreedObject *obj = large_objects_;
1.67 + large_objects_ = large_objects_->next();
1.68 + return obj;
1.69 + }
1.70 + if (huge_objects_) {
1.71 + FreedObject *obj = huge_objects_;
1.72 + huge_objects_ = huge_objects_->next();
1.73 + return obj;
1.74 + }
1.75 + return NULL;
1.76 +}
1.77 +
1.78 +void
1.79 +FreeList::reset()
1.80 +{
1.81 + small_objects_ = NULL;
1.82 + medium_objects_ = NULL;
1.83 + large_objects_ = NULL;
1.84 + huge_objects_ = NULL;
1.85 +}
1.86 +
1.87 +OldSpace::OldSpace(Zone *zone)
1.88 + : zone_(zone),
1.89 + first_(NULL),
1.90 last_(NULL)
1.91 {
1.92 }
1.93 @@ -82,12 +154,41 @@
1.94 return !!first_;
1.95 }
1.96
1.97 +OldSpace::~OldSpace()
1.98 +{
1.99 + while (first_) {
1.100 + HeapChunk *temp = first_->next();
1.101 + HeapChunk::Destroy(first_);
1.102 + first_ = temp;
1.103 + }
1.104 +}
1.105 +
1.106 Address
1.107 OldSpace::allocateSlow(size_t nbytes)
1.108 {
1.109 - HeapChunk *chunk = HeapChunk::New(last_, HeapChunk::kDefaultSize);
1.110 - if (!chunk)
1.111 - return NULL;
1.112 + if (FreedObject *obj = freelist_.pick(nbytes)) {
1.113 + Address address = reinterpret_cast<Address>(obj);
1.114 + size_t actual = obj->size();
1.115 + assert(actual >= nbytes);
1.116 + if (actual != nbytes)
1.117 + markRegionFree(address + nbytes, actual - nbytes);
1.118 +
1.119 + return address;
1.120 + }
1.121 +
1.122 + // Free unused stuff at the end of the current chunk.
1.123 + if (cursor_ != last_->end())
1.124 + markRegionFree(cursor_, last_->end() - cursor_);
1.125 +
1.126 + HeapChunk *chunk;
1.127 + if (last_->next()) {
1.128 + // The next chunk is guaranteed to be empty.
1.129 + chunk = last_->next();
1.130 + } else {
1.131 + chunk = HeapChunk::New(last_, HeapChunk::kDefaultSize);
1.132 + if (!chunk)
1.133 + return NULL;
1.134 + }
1.135
1.136 last_ = chunk;
1.137 cursor_ = chunk->first();
1.138 @@ -99,13 +200,49 @@
1.139 return address;
1.140 }
1.141
1.142 -OldSpace::~OldSpace()
1.143 +void
1.144 +OldSpace::markRegionFree(Address start, size_t length)
1.145 +{
1.146 + FreedObject *obj = reinterpret_cast<FreedObject *>(start);
1.147 + new (obj) FreedObject(zone_->getMap(MapKind_FreeRegion), length);
1.148 +
1.149 + if (length < sizeof(FreedObject)) {
1.150 + // Can't encode a list in this object, but it's marked free, so we're done.
1.151 + return;
1.152 + }
1.153 +
1.154 + freelist_.add(obj);
1.155 +}
1.156 +
1.157 +void
1.158 +OldSpace::freeUnusedPages()
1.159 {
1.160 - while (first_) {
1.161 - HeapChunk *temp = first_->next();
1.162 - HeapChunk::Destroy(first_);
1.163 - first_ = temp;
1.164 + HeapChunk **prev = &first_;
1.165 + HeapChunk *empty = NULL;
1.166 + while (*prev) {
1.167 + HeapChunk *chunk = *prev;
1.168 + if (chunk->isEmpty()) {
1.169 + *prev = chunk->next();
1.170 + if (empty) {
1.171 + // Remove this chunk.
1.172 + HeapChunk::Destroy(chunk);
1.173 + continue;
1.174 + }
1.175 + empty = chunk;
1.176 + }
1.177 + prev = chunk->nextp();
1.178 }
1.179 +
1.180 + if (empty) {
1.181 + *empty->nextp() = NULL;
1.182 + *last_->nextp() = empty;
1.183 + }
1.184 +}
1.185 +
1.186 +void
1.187 +OldSpace::resetFreeList()
1.188 +{
1.189 + freelist_.reset();
1.190 }
1.191
1.192 LargeObjectSpace::LargeObjectSpace()
1.193 @@ -146,3 +283,25 @@
1.194 return chunk->first();
1.195 }
1.196
1.197 +void
1.198 +LargeObjectSpace::sweep()
1.199 +{
1.200 + if (!first_)
1.201 + return;
1.202 +
1.203 + HeapChunk **pprev = &first_;
1.204 + do {
1.205 + HeapChunk *chunk = *pprev;
1.206 + Object *obj = reinterpret_cast<Object *>(chunk->first());
1.207 + MarkBit bit = HeapChunk::GetMarkBit(obj);
1.208 + if (HeapChunk::IsWhite(bit)) {
1.209 + *pprev = chunk->next();
1.210 + HeapChunk::Destroy(chunk);
1.211 + } else {
1.212 + assert(HeapChunk::IsBlack(bit));
1.213 + HeapChunk::Clear(bit);
1.214 + pprev = chunk->nextp();
1.215 + last_ = chunk;
1.216 + }
1.217 + } while (*pprev);
1.218 +}