diff --git a/src/heap.cpp b/src/heap.cpp index 383aaed499..f0b52308f1 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -36,8 +36,8 @@ class Segment { // printf("iterating from %p (index %d) to %p (index %d) " // "(%d of %d bytes) (scale: %d)\n", -// start, index, end, limit, (end - start) * sizeof(void*), -// map->segment->position * sizeof(void*), map->scale); +// start, index, end, limit, (end - start) * BytesPerWord, +// map->segment->position * BytesPerWord, map->scale); } bool hasMore() { @@ -51,12 +51,12 @@ class Segment { for (; word <= wordLimit and (word < wordLimit or bit < bitLimit); ++word) { - uintptr_t* p = map->data + word; + uintptr_t* p = map->data() + word; if (*p) { for (; bit < BitsPerWord and (word < wordLimit or bit < bitLimit); ++bit) { - if (map->data[word] & (static_cast(1) << bit)) { + if (map->data()[word] & (static_cast(1) << bit)) { index = ::indexOf(word, bit); // printf("hit at index %d\n", index); return true; @@ -74,8 +74,8 @@ class Segment { } void** next() { - assert(hasMore()); - assert(map->segment); + assert(map->segment->context, hasMore()); + assert(map->segment->context, map->segment); return reinterpret_cast(map->segment->data) + ((index++) * map->scale); @@ -83,83 +83,66 @@ class Segment { }; Segment* segment; + unsigned offset; unsigned bitsPerRecord; unsigned scale; - uintptr_t* data; Map* next; Map* child; void init() { init(0); - data = 0; } - void init(Segment* segment, unsigned bitsPerRecord = 1, unsigned scale = 1, - Map* next = 0, Map* child = 0) + void init(Segment* segment, unsigned offset, unsigned bitsPerRecord = 1, + unsigned scale = 1, Map* next = 0, Map* child = 0) { assert(bitsPerRecord); assert(scale); assert(powerOfTwo(scale)); this->segment = segment; + this->offset = offset; this->bitsPerRecord = bitsPerRecord; this->scale = scale; this->next = next; this->child = child; } - void replaceWith(Map* m) { - assert(m); - assert(bitsPerRecord == m->bitsPerRecord); - assert(scale == m->scale); - - free(data); - - data = m->data; - m->data = 0; - - if (next) next->replaceWith(m->next); - if (child) child->replaceWith(m->child); + uintptr_t* data() { + return segment->data + offset; } unsigned size(unsigned capacity) { unsigned result = pad (divide(divide(capacity, scale) * bitsPerRecord, 8)); - assert(result); + assert(segment->context, result); return result; } unsigned size() { - assert(segment); + assert(segment->context, segment); return size(max(segment->capacity, 1)); } unsigned indexOf(void* p) { - assert(segment); - assert(segment->position + assert(segment->context, segment); + assert(segment->context, + segment->position and p >= segment->data and p <= segment->data + segment->position); - assert(segment->data); - return ((static_cast(p) - reinterpret_cast(segment->data)) + assert(segment->context, segment->data); + + return ((static_cast(p) + - reinterpret_cast(segment->data)) / scale) * bitsPerRecord; } - void update() { - data = static_cast(realloc(data, size())); - assert(data); + void update(uintptr_t* segmentData) { + uintptr_t* p = segmentData + offset; + memcpy(p, data(), size(segment->position)); - if (next) next->update(); - if (child) child->update(); - } - - void reset(bool clear = true) { - free(data); - data = static_cast(malloc(size())); - assert(data); - if (clear) memset(data, 0, size()); - - if (next) next->reset(); - if (child) child->reset(); + if (next) next->update(segmentData); + if (child) child->update(segmentData); } void clear() { @@ -219,8 +202,7 @@ class Segment { } void dispose() { - free(data); - data = 0; + offset = 0; segment = 0; next = 0; @@ -237,7 +219,7 @@ class Segment { return n; } - void setSegment(Segment* s) { + void setSegment(Segment* s, bool clear = true) { segment = s; if (next) next->setSegment(s); if (child) child->setSegment(s); @@ -259,27 +241,46 @@ class Segment { return footprint(capacity); } - void init(unsigned capacityInBytes, Map* map = 0, bool clearMap = true) { - this->capacity = divide(capacityInBytes, BytesPerWord); + void init(Context* context, unsigned capacity, Map* map = 0, + bool clearMap = true) + { + this->context = context; + this->capacity = capacity; this->data = 0; this->position = 0; this->map = map; if (capacity) { - if (map) map->reset(clearMap); - this->data = static_cast(malloc(capacity * BytesPerWord)); - assert(this->data); + unsigned count = footprint(capacity); + this->data = static_cast(system(context)->allocate(&count)); + + if (count != footprint(capacity)) { + abort(context); + } + + if (map) { + map->setSegment(this, clearMap); + } } } - void* add(System* sys, void* p, unsigned size) { + void* allocate(unsigned size) { + assert(c, size); + assert(c, position + size <= capacity); + void* p = reinterpret_cast(data) + position; + position += size; + + return p; + } + + void* add(void* p, unsigned size) { void* target = allocate(size); - memcpy(target, p, size); + memcpy(target, p, size * BytesPerWord); return target; } unsigned remaining() { - return (capacity - position) * BytesPerWord; + return capacity - position; } void replaceWith(Segment* s) { @@ -307,28 +308,30 @@ class Segment { } } - void grow(System* sys, unsigned extra) { - if (remainingBytes() < extra) { - unsigned minimumNeeded = s->usedBytes() + (extra * bytesPerWord); + void grow(unsigned extra) { + if (remaining() < extra) { + unsigned minimumNeeded = position + extra; unsigned count = minimumNeeded * 2; + + minimumNeeded = footprint(minimumNeeded); + count = footprint(count); - void* p = sys->allocate(&count); + uintptr_t* p = static_cast + (system(context)->allocate(&count)); if (count >= minimumNeeded) { - memcpy(p, s->data, s->usedBytes()); - s->data = p; - sys->free(s->data); + memcpy(p, data, position * BytesPerWord); + + if (map) { + map->update(p); + } + + data = p; + system(context)->free(data); } else { - abort(sys); + abort(context); } } - - unsigned newCapacity = divide(newCapacityInBytes, BytesPerWord); - assert(newCapacity > capacity); - capacity = newCapacity; - data = static_cast(realloc(data, capacity * BytesPerWord)); - assert(data); - if (map) map->update(); } bool contains(void* p) { @@ -354,7 +357,7 @@ void initGen1(Context* c) { c->ageMap.init(&(c->gen1), log(Arena::TenureThreshold)); - c->gen1.init(c->minimumGen1Size, &(c->ageMap), false); + c->gen1.init(c->minimumGen1Size / BytesPerWord, &(c->ageMap), false); } void @@ -364,14 +367,14 @@ initGen2(Context* c) c->pageMap.init(&(c->gen2), 1, LikelyPageSize / BytesPerWord, 0, &(c->pointerMap)); c->heapMap.init(&(c->gen2), 1, c->pageMap.scale * 1024, 0, &(c->pageMap)); - c->gen2.init(c->minimumGen2Size, &(c->heapMap)); + c->gen2.init(c->minimumGen2Size / BytesPerWord, &(c->heapMap)); } void initNextGen1(Context* c) { - unsigned size = max(c->minimumGen1Size, - nextPowerOfTwo(c->gen1.position() * BytesPerWord)); + unsigned size = max(c->minimumGen1Size / BytesPerWord, + nextPowerOfTwo(c->gen1.position())); c->nextAgeMap.init(&(c->nextGen1), log(Arena::TenureThreshold)); c->nextGen1.init(size, &(c->nextAgeMap), false); } @@ -379,8 +382,8 @@ initNextGen1(Context* c) void initNextGen2(Context* c) { - unsigned size = max(c->minimumGen2Size, - nextPowerOfTwo(c->gen2.position() * BytesPerWord)); + unsigned size = max(c->minimumGen2Size / BytesPerWord, + nextPowerOfTwo(c->gen2.position())); c->pointerMap.init(&(c->nextGen2)); c->pageMap.init(&(c->nextGen2), 1, LikelyPageSize / BytesPerWord, 0, &(c->pointerMap)); @@ -411,11 +414,8 @@ bitset(object o) object copyTo(Context* c, Segment* s, object o, unsigned size) { - assert(c, size >= BytesPerWord); - assert(c, size % BytesPerWord == 0); - - if (s->remainingBytes() < size) { - s->grow(c->sys, size * bytesPerWord); + if (s->remaining() < size) { + s->grow(c->sys, size); } return static_cast(s->add(o, size)); @@ -424,7 +424,7 @@ copyTo(Context* c, Segment* s, object o, unsigned size) object copy2(Context* c, object o) { - unsigned size = c->client->sizeOf(o); + unsigned size = c->client->sizeInWords(o); if (c->gen2.contains(o)) { assert(c, c->mode == MajorCollection @@ -437,7 +437,7 @@ copy2(Context* c, object o) if (c->mode == MinorCollection) { if (c->gen2.front == 0) initGen2(a); - if (c->gen2.remainingBytes() >= size) { + if (c->gen2.remaining() >= size) { return copyTo(c, &(c->gen2), o, size); } else { c->mode = OverflowCollection; @@ -676,7 +676,7 @@ collect(Context* c, void** p) virtual bool visit(unsigned offset) { bool needsVisit; object childCopy = update - (c, &cast(copy, offset * sizeof(void*)), &needsVisit); + (c, &cast(copy, offset * BytesPerWord), &needsVisit); ++ total; @@ -698,7 +698,7 @@ collect(Context* c, void** p) bitsetSet(bitset, offset, true); } } else { - cast(copy, offset * sizeof(void*)) = childCopy; + cast(copy, offset * BytesPerWord) = childCopy; } return true; @@ -722,8 +722,8 @@ collect(Context* c, void** p) parent = original; } - original = cast(copy, walker.first * sizeof(void*)); - cast(copy, walker.first * sizeof(void*)) = follow(original); + original = cast(copy, walker.first * BytesPerWord); + cast(copy, walker.first * BytesPerWord) = follow(original); goto visit; } else { // ascend @@ -775,8 +775,8 @@ collect(Context* c, void** p) parent = ::parent(original); } - original = cast(copy, walker.next * sizeof(void*)); - cast(copy, walker.next * sizeof(void*)) = follow(original); + original = cast(copy, walker.next * BytesPerWord); + cast(copy, walker.next * BytesPerWord) = follow(original); goto visit; } else { return; @@ -843,7 +843,7 @@ class ObjectSegmentIterator { object next() { assert(c, hasNext()); object p = s->data + (index * BytesPerWord); - index += c->client->sizeOf(p) / BytesPerWord; + index += c->client->sizeInWords(p); return p; }