jitcraft/Spaces.cpp
changeset 53 13bd3a8df334
parent 51 fb324242a675
child 59 b7d61ddb3c8d
     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 +}