mirror of
https://github.com/corda/corda.git
synced 2024-12-28 16:58:55 +00:00
switch to a linked heap implementation
This commit is contained in:
parent
3238b34723
commit
d5ce307a2a
12
makefile
12
makefile
@ -137,12 +137,6 @@ $(generated-code): %.cpp: $(src)/types.def $(generator-executable)
|
|||||||
@echo "generating $(@)"
|
@echo "generating $(@)"
|
||||||
$(generator-executable) $(call gen-arg,$(@)) < $(<) > $(@)
|
$(generator-executable) $(call gen-arg,$(@)) < $(<) > $(@)
|
||||||
|
|
||||||
$(bld)/vm.o \
|
|
||||||
$(bld)/test-vm.o \
|
|
||||||
$(bld)/stress-vm.o \
|
|
||||||
$(bld)/fast-vm.o: \
|
|
||||||
$(interpreter-depends)
|
|
||||||
|
|
||||||
$(bld)/type-generator.o: \
|
$(bld)/type-generator.o: \
|
||||||
$(generator-headers)
|
$(generator-headers)
|
||||||
|
|
||||||
@ -156,17 +150,17 @@ $(stdcpp-objects): $(bld)/%.o: $(src)/%.cpp
|
|||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(cxx) $(stdcpp-cflags) -c $(<) -o $(@)
|
$(cxx) $(stdcpp-cflags) -c $(<) -o $(@)
|
||||||
|
|
||||||
$(interpreter-objects): $(bld)/%.o: $(src)/%.cpp
|
$(interpreter-objects): $(bld)/%.o: $(src)/%.cpp $(interpreter-depends)
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(cxx) $(interpreter-cflags) -c $(<) -o $(@)
|
$(cxx) $(interpreter-cflags) -c $(<) -o $(@)
|
||||||
|
|
||||||
$(test-objects): $(bld)/test-%.o: $(src)/%.cpp
|
$(test-objects): $(bld)/test-%.o: $(src)/%.cpp $(interpreter-depends)
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(cxx) $(interpreter-cflags) $(test-cflags) -c $(<) -o $(@)
|
$(cxx) $(interpreter-cflags) $(test-cflags) -c $(<) -o $(@)
|
||||||
|
|
||||||
$(stress-objects): $(bld)/stress-%.o: $(src)/%.cpp
|
$(stress-objects): $(bld)/stress-%.o: $(src)/%.cpp $(interpreter-depends)
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(cxx) $(interpreter-cflags) $(stress-cflags) -c $(<) -o $(@)
|
$(cxx) $(interpreter-cflags) $(stress-cflags) -c $(<) -o $(@)
|
||||||
|
413
src/heap.cpp
413
src/heap.cpp
@ -2,6 +2,8 @@
|
|||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#define CHAIN_HEADER_SIZE divide(sizeof(Segment::Chain), BytesPerWord)
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -13,10 +15,10 @@ const unsigned TenureThreshold = 3;
|
|||||||
const unsigned MinimumGen1Size = 64 * 1024;
|
const unsigned MinimumGen1Size = 64 * 1024;
|
||||||
const unsigned MinimumGen2Size = 128 * 1024;
|
const unsigned MinimumGen2Size = 128 * 1024;
|
||||||
|
|
||||||
void* const Top = reinterpret_cast<void*>(~static_cast<uintptr_t>(0));
|
const unsigned Top = ~static_cast<unsigned>(0);
|
||||||
|
|
||||||
const bool Verbose = true;
|
const bool Verbose = true;
|
||||||
const bool Debug = false;
|
const bool Debug = true;
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
|
|
||||||
@ -28,6 +30,8 @@ class Segment {
|
|||||||
public:
|
public:
|
||||||
class Map {
|
class Map {
|
||||||
public:
|
public:
|
||||||
|
class Chain;
|
||||||
|
|
||||||
class Iterator {
|
class Iterator {
|
||||||
public:
|
public:
|
||||||
Map* map;
|
Map* map;
|
||||||
@ -40,19 +44,14 @@ class Segment {
|
|||||||
assert(map->segment->context, map);
|
assert(map->segment->context, map);
|
||||||
assert(map->segment->context, map->bitsPerRecord == 1);
|
assert(map->segment->context, map->bitsPerRecord == 1);
|
||||||
assert(map->segment->context, map->segment);
|
assert(map->segment->context, map->segment);
|
||||||
|
assert(map->segment->context, start <= map->segment->position());
|
||||||
|
|
||||||
|
if (end > map->segment->position()) end = map->segment->position();
|
||||||
|
|
||||||
index = map->indexOf(start);
|
index = map->indexOf(start);
|
||||||
assert(map->segment->context, index == 0 or start != 0);
|
|
||||||
|
|
||||||
if (end > map->segment->position) end = map->segment->position;
|
|
||||||
|
|
||||||
limit = map->indexOf(end);
|
limit = map->indexOf(end);
|
||||||
if (end - start % map->scale) ++ limit;
|
|
||||||
|
|
||||||
// printf("iterating from %p (index %d) to %p (index %d) "
|
if ((end - start) % map->scale) ++ limit;
|
||||||
// "(%d of %d bytes) (scale: %d)\n",
|
|
||||||
// start, index, end, limit, (end - start) * BytesPerWord,
|
|
||||||
// map->segment->position * BytesPerWord, map->scale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasMore() {
|
bool hasMore() {
|
||||||
@ -100,7 +99,7 @@ class Segment {
|
|||||||
unsigned bitsPerRecord;
|
unsigned bitsPerRecord;
|
||||||
unsigned scale;
|
unsigned scale;
|
||||||
Map* child;
|
Map* child;
|
||||||
|
|
||||||
Map(Segment* segment = 0, unsigned bitsPerRecord = 1,
|
Map(Segment* segment = 0, unsigned bitsPerRecord = 1,
|
||||||
unsigned scale = 1, Map* child = 0):
|
unsigned scale = 1, Map* child = 0):
|
||||||
segment(segment),
|
segment(segment),
|
||||||
@ -125,14 +124,18 @@ class Segment {
|
|||||||
if (child) child->replaceWith(m->child);
|
if (child) child->replaceWith(m->child);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned offset() {
|
unsigned offset(unsigned capacity) {
|
||||||
unsigned n = segment->capacity;
|
unsigned n = 0;
|
||||||
if (child) n += child->footprint(segment->capacity);
|
if (child) n += child->footprint(capacity);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned offset() {
|
||||||
|
return offset(segment->capacity());
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t* data() {
|
uintptr_t* data() {
|
||||||
return segment->data + offset();
|
return segment->rear->data() + segment->rear->capacity + offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned size(unsigned capacity) {
|
unsigned size(unsigned capacity) {
|
||||||
@ -143,7 +146,7 @@ class Segment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned size() {
|
unsigned size() {
|
||||||
return size(max(segment->capacity, 1));
|
return size(max(segment->capacity(), 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned indexOf(unsigned segmentIndex) {
|
unsigned indexOf(unsigned segmentIndex) {
|
||||||
@ -151,21 +154,21 @@ class Segment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned indexOf(void* p) {
|
unsigned indexOf(void* p) {
|
||||||
assert(segment->context,
|
assert(segment->context, segment);
|
||||||
segment->position
|
assert(segment->context, segment->almostContains(p));
|
||||||
and p >= segment->data
|
assert(segment->context, segment->capacity());
|
||||||
and p <= segment->data + segment->position);
|
return indexOf(segment->indexOf(p));
|
||||||
assert(segment->context, segment->data);
|
|
||||||
|
|
||||||
return indexOf(static_cast<void**>(p)
|
|
||||||
- reinterpret_cast<void**>(segment->data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(uintptr_t* segmentData) {
|
void update(uintptr_t* newData, unsigned capacity) {
|
||||||
uintptr_t* p = segmentData + offset();
|
assert(segment->context, capacity >= segment->capacity());
|
||||||
memcpy(p, data(), size(segment->position) * BytesPerWord);
|
|
||||||
|
|
||||||
if (child) child->update(segmentData);
|
uintptr_t* p = newData + offset(capacity);
|
||||||
|
memcpy(p, data(), size(segment->position()) * BytesPerWord);
|
||||||
|
|
||||||
|
if (child) {
|
||||||
|
child->update(newData, capacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
@ -174,17 +177,21 @@ class Segment {
|
|||||||
if (child) child->clear();
|
if (child) child->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear(unsigned i) {
|
void clearBit(unsigned i) {
|
||||||
|
assert(segment->context, wordOf(i) * BytesPerWord < size());
|
||||||
|
|
||||||
data()[wordOf(i)] &= ~(static_cast<uintptr_t>(1) << bitOf(i));
|
data()[wordOf(i)] &= ~(static_cast<uintptr_t>(1) << bitOf(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(unsigned i) {
|
void setBit(unsigned i) {
|
||||||
|
assert(segment->context, wordOf(i) * BytesPerWord < size());
|
||||||
|
|
||||||
data()[wordOf(i)] |= static_cast<uintptr_t>(1) << bitOf(i);
|
data()[wordOf(i)] |= static_cast<uintptr_t>(1) << bitOf(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearOnlyIndex(unsigned index) {
|
void clearOnlyIndex(unsigned index) {
|
||||||
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
||||||
clear(i);
|
clearBit(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +211,7 @@ class Segment {
|
|||||||
void setOnlyIndex(unsigned index, unsigned v = 1) {
|
void setOnlyIndex(unsigned index, unsigned v = 1) {
|
||||||
unsigned i = index + bitsPerRecord - 1;
|
unsigned i = index + bitsPerRecord - 1;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (v & 1) set(i); else clear(i);
|
if (v & 1) setBit(i); else clearBit(i);
|
||||||
v >>= 1;
|
v >>= 1;
|
||||||
if (i == index) break;
|
if (i == index) break;
|
||||||
--i;
|
--i;
|
||||||
@ -249,76 +256,133 @@ class Segment {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Chain {
|
||||||
|
public:
|
||||||
|
Segment* segment;
|
||||||
|
unsigned offset;
|
||||||
|
unsigned position;
|
||||||
|
unsigned capacity;
|
||||||
|
Chain* next;
|
||||||
|
Chain* previous;
|
||||||
|
|
||||||
|
Chain(Segment* segment, unsigned offset, unsigned capacity,
|
||||||
|
Chain* previous):
|
||||||
|
segment(segment),
|
||||||
|
offset(offset),
|
||||||
|
position(0),
|
||||||
|
capacity(capacity),
|
||||||
|
next(0),
|
||||||
|
previous(previous)
|
||||||
|
{
|
||||||
|
assert(segment->context, sizeof(Chain) % BytesPerWord == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dispose(Chain* c) {
|
||||||
|
if (c) {
|
||||||
|
if (c->next) dispose(c->next);
|
||||||
|
system(c->segment->context)->free(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t* data() {
|
||||||
|
return reinterpret_cast<uintptr_t*>(this) + CHAIN_HEADER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned footprint(unsigned capacity, Map* map) {
|
||||||
|
unsigned n = CHAIN_HEADER_SIZE + capacity;
|
||||||
|
if (map) {
|
||||||
|
n += map->footprint(capacity);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned footprint() {
|
||||||
|
return footprint(capacity, segment->map);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Context* context;
|
Context* context;
|
||||||
uintptr_t* data;
|
Chain* front;
|
||||||
unsigned position;
|
Chain* rear;
|
||||||
unsigned capacity;
|
|
||||||
Map* map;
|
Map* map;
|
||||||
|
|
||||||
Segment(Context* context, unsigned capacity, Map* map = 0,
|
Segment(Context* context, unsigned capacity, Map* map = 0,
|
||||||
bool clearMap = true):
|
bool clearMap = true):
|
||||||
context(context),
|
context(context),
|
||||||
data(0),
|
front(0),
|
||||||
position(0),
|
rear(0),
|
||||||
capacity(capacity),
|
|
||||||
map(map)
|
map(map)
|
||||||
{
|
{
|
||||||
|
front = rear = 0;
|
||||||
|
this->map = map;
|
||||||
|
|
||||||
if (capacity) {
|
if (capacity) {
|
||||||
data = static_cast<uintptr_t*>
|
front = rear = new
|
||||||
(system(context)->allocate(footprint(capacity) * BytesPerWord));
|
(system(context)->allocate
|
||||||
|
(Chain::footprint(capacity, map) * BytesPerWord))
|
||||||
|
Chain(this, 0, capacity, 0);
|
||||||
|
|
||||||
if (map) {
|
if (map) {
|
||||||
map->setSegment(this);
|
map->setSegment(this);
|
||||||
if (clearMap) map->clear();
|
if (clearMap) {
|
||||||
|
map->clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned footprint(unsigned capacity) {
|
unsigned capacity() {
|
||||||
unsigned n = capacity;
|
return (rear? rear->offset + rear->capacity : 0);
|
||||||
if (map) n += map->footprint(capacity);
|
}
|
||||||
return n;
|
|
||||||
|
unsigned position() {
|
||||||
|
return (rear? rear->offset + rear->position : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void truncate(unsigned offset) {
|
||||||
|
assert(context, offset <= position());
|
||||||
|
|
||||||
|
for (Chain* c = front; c; c = c->next) {
|
||||||
|
if (offset >= c->offset
|
||||||
|
and offset <= c->offset + c->position)
|
||||||
|
{
|
||||||
|
c->position = offset - c->offset;
|
||||||
|
Chain::dispose(c->next);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abort(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyTo(void* p) {
|
||||||
|
for (Chain* c = front; c; c = c->next) {
|
||||||
|
if (c->position) {
|
||||||
|
memcpy(static_cast<uintptr_t*>(p) + c->offset,
|
||||||
|
c->data(),
|
||||||
|
c->position * BytesPerWord);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned footprint() {
|
unsigned footprint() {
|
||||||
return footprint(capacity);
|
unsigned n = 0;
|
||||||
}
|
for (Chain* c = front; c; c = c->next) n += c->footprint();
|
||||||
|
return n;
|
||||||
void* allocate(unsigned size) {
|
|
||||||
assert(context, size);
|
|
||||||
assert(context, position + size <= capacity);
|
|
||||||
void* p = reinterpret_cast<void**>(data) + position;
|
|
||||||
position += size;
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* add(void* p, unsigned size) {
|
|
||||||
void* target = allocate(size);
|
|
||||||
memcpy(target, p, size * BytesPerWord);
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* get(unsigned offset) {
|
|
||||||
assert(context, offset < position);
|
|
||||||
return data + offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned remaining() {
|
unsigned remaining() {
|
||||||
return capacity - position;
|
return capacity() - position();
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceWith(Segment* s) {
|
void replaceWith(Segment* s) {
|
||||||
if (data) system(context)->free(data);
|
Chain::dispose(front);
|
||||||
|
|
||||||
data = s->data;
|
front = s->front;
|
||||||
s->data = 0;
|
rear = s->rear;
|
||||||
|
|
||||||
position = s->position;
|
s->front = s->rear = 0;
|
||||||
s->position = 0;
|
|
||||||
|
|
||||||
capacity = s->capacity;
|
|
||||||
s->capacity = 0;
|
|
||||||
|
|
||||||
if (s->map) {
|
if (s->map) {
|
||||||
if (map) {
|
if (map) {
|
||||||
@ -333,42 +397,104 @@ class Segment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void grow(unsigned extra) {
|
bool contains(void* p) {
|
||||||
if (remaining() < extra) {
|
for (Chain* c = front; c; c = c->next) {
|
||||||
unsigned minimumNeeded = position + extra;
|
if (c->position and p >= c->data() and p < c->data() + c->position) {
|
||||||
unsigned count = minimumNeeded * 2;
|
return true;
|
||||||
|
|
||||||
minimumNeeded = footprint(minimumNeeded) * BytesPerWord;
|
|
||||||
count = footprint(count) * BytesPerWord;
|
|
||||||
|
|
||||||
uintptr_t* p = static_cast<uintptr_t*>
|
|
||||||
(system(context)->allocate(&count));
|
|
||||||
|
|
||||||
if (count >= minimumNeeded) {
|
|
||||||
memcpy(p, data, position * BytesPerWord);
|
|
||||||
|
|
||||||
if (map) {
|
|
||||||
map->update(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
data = p;
|
|
||||||
system(context)->free(data);
|
|
||||||
} else {
|
|
||||||
abort(context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool almostContains(void* p) {
|
||||||
|
return contains(p) or p == rear->data() + rear->position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* get(unsigned offset) {
|
||||||
|
for (Chain* c = front; c; c = c->next) {
|
||||||
|
if (c->position
|
||||||
|
and offset >= c->offset
|
||||||
|
and offset < c->offset + c->position)
|
||||||
|
{
|
||||||
|
return c->data() + (offset - c->offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset == rear->offset + rear->position) {
|
||||||
|
return rear->data() + (offset - rear->offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned indexOf(void* p) {
|
||||||
|
for (Chain* c = front; c; c = c->next) {
|
||||||
|
if (c->position and p >= c->data() and p < c->data() + c->position) {
|
||||||
|
return (static_cast<uintptr_t*>(p) - c->data()) + c->offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == rear->data() + rear->position) {
|
||||||
|
return (static_cast<uintptr_t*>(p) - rear->data()) + rear->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* allocate(unsigned sizeInBytes) {
|
||||||
|
unsigned size = divide(sizeInBytes, BytesPerWord);
|
||||||
|
assert(context, size);
|
||||||
|
assert(context, rear->position + size <= rear->capacity);
|
||||||
|
void* p = reinterpret_cast<void**>(rear->data()) + rear->position;
|
||||||
|
rear->position += size;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* add(void* p, unsigned size) {
|
||||||
|
void* target = allocate(size);
|
||||||
|
memcpy(target, p, size * BytesPerWord);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensure(unsigned minimum) {
|
||||||
|
if (remaining() < minimum) {
|
||||||
|
if (Verbose) {
|
||||||
|
fprintf(stderr, "grow\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned desired = (position() + minimum) * 2;
|
||||||
|
|
||||||
|
void* p = 0;
|
||||||
|
unsigned newCapacity = desired;
|
||||||
|
while (p == 0) {
|
||||||
|
p = system(context)->tryAllocate
|
||||||
|
(Chain::footprint(newCapacity, map) * BytesPerWord);
|
||||||
|
|
||||||
|
if (p == 0) {
|
||||||
|
if (newCapacity > minimum) {
|
||||||
|
newCapacity = minimum + ((newCapacity - minimum) / 2);
|
||||||
|
} else {
|
||||||
|
abort(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Chain* c = new (p) Chain
|
||||||
|
(this, rear->offset + rear->position, newCapacity, rear);
|
||||||
|
|
||||||
|
if (map) {
|
||||||
|
map->update(c->data() + c->capacity, newCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
rear->previous = c;
|
||||||
|
rear = c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contains(void* p) {
|
|
||||||
return position and p >= data and p < data + position;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
system(context)->free(data);
|
Chain::dispose(front);
|
||||||
data = 0;
|
front = rear = 0;
|
||||||
position = 0;
|
|
||||||
capacity = 0;
|
|
||||||
|
|
||||||
map = 0;
|
map = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -406,7 +532,7 @@ class Context {
|
|||||||
Segment gen2;
|
Segment gen2;
|
||||||
Segment nextGen2;
|
Segment nextGen2;
|
||||||
|
|
||||||
void* gen2Base;
|
unsigned gen2Base;
|
||||||
|
|
||||||
Segment::Map ageMap;
|
Segment::Map ageMap;
|
||||||
Segment::Map nextAgeMap;
|
Segment::Map nextAgeMap;
|
||||||
@ -459,7 +585,7 @@ void
|
|||||||
initNextGen1(Context* c)
|
initNextGen1(Context* c)
|
||||||
{
|
{
|
||||||
unsigned size = max(MinimumGen1Size / BytesPerWord,
|
unsigned size = max(MinimumGen1Size / BytesPerWord,
|
||||||
nextPowerOfTwo(c->gen1.position));
|
nextPowerOfTwo(c->gen1.position()));
|
||||||
new (&(c->nextAgeMap)) Segment::Map(&(c->nextGen1), log(TenureThreshold));
|
new (&(c->nextAgeMap)) Segment::Map(&(c->nextGen1), log(TenureThreshold));
|
||||||
new (&(c->nextGen1)) Segment(c, size, &(c->nextAgeMap), false);
|
new (&(c->nextGen1)) Segment(c, size, &(c->nextAgeMap), false);
|
||||||
}
|
}
|
||||||
@ -468,7 +594,7 @@ void
|
|||||||
initNextGen2(Context* c)
|
initNextGen2(Context* c)
|
||||||
{
|
{
|
||||||
unsigned size = max(MinimumGen2Size / BytesPerWord,
|
unsigned size = max(MinimumGen2Size / BytesPerWord,
|
||||||
nextPowerOfTwo(c->gen2.position));
|
nextPowerOfTwo(c->gen2.position()));
|
||||||
new (&(c->pointerMap)) Segment::Map(&(c->nextGen2));
|
new (&(c->pointerMap)) Segment::Map(&(c->nextGen2));
|
||||||
new (&(c->pageMap)) Segment::Map
|
new (&(c->pageMap)) Segment::Map
|
||||||
(&(c->nextGen2), 1, LikelyPageSize / BytesPerWord, &(c->pointerMap));
|
(&(c->nextGen2), 1, LikelyPageSize / BytesPerWord, &(c->pointerMap));
|
||||||
@ -483,7 +609,7 @@ fresh(Context* c, object o)
|
|||||||
{
|
{
|
||||||
return c->nextGen1.contains(o)
|
return c->nextGen1.contains(o)
|
||||||
or c->nextGen2.contains(o)
|
or c->nextGen2.contains(o)
|
||||||
or (o >= c->gen2Base and c->gen2.contains(o));
|
or (c->gen2.contains(o) and c->gen2.indexOf(o) > c->gen2Base);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
@ -516,10 +642,7 @@ bitset(Context* c, object o)
|
|||||||
inline object
|
inline object
|
||||||
copyTo(Context*, Segment* s, object o, unsigned size)
|
copyTo(Context*, Segment* s, object o, unsigned size)
|
||||||
{
|
{
|
||||||
if (s->remaining() < size) {
|
s->ensure(size);
|
||||||
s->grow(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<object>(s->add(o, size));
|
return static_cast<object>(s->add(o, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,15 +660,19 @@ copy2(Context* c, object o)
|
|||||||
unsigned age = c->ageMap.get(o);
|
unsigned age = c->ageMap.get(o);
|
||||||
if (age == TenureThreshold) {
|
if (age == TenureThreshold) {
|
||||||
if (c->mode == MinorCollection) {
|
if (c->mode == MinorCollection) {
|
||||||
if (c->gen2.data == 0) initGen2(c);
|
if (c->gen2.front == 0) initGen2(c);
|
||||||
|
|
||||||
if (c->gen2.remaining() >= size) {
|
if (c->gen2.remaining() >= size) {
|
||||||
if (c->gen2Base == Top) {
|
if (c->gen2Base == Top) {
|
||||||
c->gen2Base = c->gen2.data + c->gen2.position;
|
c->gen2Base = c->gen2.position();
|
||||||
}
|
}
|
||||||
|
|
||||||
return copyTo(c, &(c->gen2), o, size);
|
return copyTo(c, &(c->gen2), o, size);
|
||||||
} else {
|
} else {
|
||||||
|
if (Verbose) {
|
||||||
|
fprintf(stderr, "overflow collection\n");
|
||||||
|
}
|
||||||
|
|
||||||
c->mode = OverflowCollection;
|
c->mode = OverflowCollection;
|
||||||
initNextGen2(c);
|
initNextGen2(c);
|
||||||
return copyTo(c, &(c->nextGen2), o, size);
|
return copyTo(c, &(c->nextGen2), o, size);
|
||||||
@ -586,7 +713,7 @@ copy(Context* c, object o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
update3(Context* c, object *p, bool* needsVisit)
|
update3(Context* c, object* p, bool* needsVisit)
|
||||||
{
|
{
|
||||||
if (wasCollected(c, *p)) {
|
if (wasCollected(c, *p)) {
|
||||||
*needsVisit = false;
|
*needsVisit = false;
|
||||||
@ -985,31 +1112,45 @@ collect(Context* c, Segment::Map* map, unsigned start, unsigned end,
|
|||||||
|
|
||||||
class ObjectSegmentIterator {
|
class ObjectSegmentIterator {
|
||||||
public:
|
public:
|
||||||
ObjectSegmentIterator(Context* c, Segment* s, unsigned end):
|
Context* context;
|
||||||
c(c), s(s), index(0), end(end)
|
Segment::Chain* chain;
|
||||||
|
unsigned index;
|
||||||
|
unsigned end;
|
||||||
|
bool dirty;
|
||||||
|
|
||||||
|
ObjectSegmentIterator(Segment* segment, unsigned end):
|
||||||
|
context(segment->context),
|
||||||
|
chain(segment->front),
|
||||||
|
index(0),
|
||||||
|
end(end),
|
||||||
|
dirty(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
bool hasNext() {
|
bool hasNext() {
|
||||||
return index < end;
|
if (dirty) {
|
||||||
|
dirty = false;
|
||||||
|
uintptr_t* p = chain->data() + index;
|
||||||
|
index += context->client->sizeInWords(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chain and index == chain->position) {
|
||||||
|
chain = chain->next;
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chain and index + chain->offset < end;
|
||||||
}
|
}
|
||||||
|
|
||||||
object next() {
|
object next() {
|
||||||
assert(c, hasNext());
|
dirty = true;
|
||||||
object p = s->data + (index * BytesPerWord);
|
return chain->data() + index;
|
||||||
index += c->client->sizeInWords(p);
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Context* c;
|
|
||||||
Segment* s;
|
|
||||||
unsigned index;
|
|
||||||
unsigned end;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
collect(Context* c, Segment* s, unsigned limit)
|
collect(Context* c, Segment* s, unsigned limit)
|
||||||
{
|
{
|
||||||
for (ObjectSegmentIterator it(c, s, limit); it.hasNext();) {
|
for (ObjectSegmentIterator it(s, limit); it.hasNext();) {
|
||||||
object p = it.next();
|
object p = it.next();
|
||||||
|
|
||||||
class Walker : public Heap::Walker {
|
class Walker : public Heap::Walker {
|
||||||
@ -1032,14 +1173,14 @@ collect(Context* c, Segment* s, unsigned limit)
|
|||||||
void
|
void
|
||||||
collect2(Context* c)
|
collect2(Context* c)
|
||||||
{
|
{
|
||||||
if (c->mode == MinorCollection and c->gen2.position) {
|
if (c->mode == MinorCollection and c->gen2.position()) {
|
||||||
unsigned start = 0;
|
unsigned start = 0;
|
||||||
unsigned end = start + c->gen2.position;
|
unsigned end = start + c->gen2.position();
|
||||||
bool dirty;
|
bool dirty;
|
||||||
collect(c, &(c->heapMap), start, end, &dirty, false);
|
collect(c, &(c->heapMap), start, end, &dirty, false);
|
||||||
} else if (c->mode == Gen2Collection) {
|
} else if (c->mode == Gen2Collection) {
|
||||||
unsigned ng2Position = c->nextGen2.position;
|
unsigned ng2Position = c->nextGen2.position();
|
||||||
collect(c, &(c->nextGen1), c->nextGen1.position);
|
collect(c, &(c->nextGen1), c->nextGen1.position());
|
||||||
collect(c, &(c->nextGen2), ng2Position);
|
collect(c, &(c->nextGen2), ng2Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1060,7 +1201,7 @@ collect2(Context* c)
|
|||||||
void
|
void
|
||||||
collect(Context* c)
|
collect(Context* c)
|
||||||
{
|
{
|
||||||
if (c->gen1.data == 0) initGen1(c);
|
if (c->gen1.front == 0) initGen1(c);
|
||||||
|
|
||||||
c->gen2Base = Top;
|
c->gen2Base = Top;
|
||||||
|
|
||||||
|
10
src/main.cpp
10
src/main.cpp
@ -33,15 +33,15 @@ class System: public vm::System {
|
|||||||
return s == 0;
|
return s == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* allocate(unsigned* size) {
|
virtual void* tryAllocate(unsigned size) {
|
||||||
if (count + *size > limit) {
|
if (count + size > limit) {
|
||||||
*size = limit - count;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t* up = static_cast<uintptr_t*>(malloc(*size + sizeof(uintptr_t)));
|
uintptr_t* up = static_cast<uintptr_t*>(malloc(size + sizeof(uintptr_t)));
|
||||||
if (up == 0) abort();
|
if (up == 0) abort();
|
||||||
|
|
||||||
*up = *size;
|
*up = size;
|
||||||
count += *up;
|
count += *up;
|
||||||
|
|
||||||
return up + 1;
|
return up + 1;
|
||||||
|
@ -30,16 +30,15 @@ class System {
|
|||||||
virtual ~System() { }
|
virtual ~System() { }
|
||||||
|
|
||||||
virtual bool success(Status) = 0;
|
virtual bool success(Status) = 0;
|
||||||
virtual void* allocate(unsigned* size) = 0;
|
virtual void* tryAllocate(unsigned size) = 0;
|
||||||
virtual void free(const void*) = 0;
|
virtual void free(const void*) = 0;
|
||||||
virtual Status start(Thread*) = 0;
|
virtual Status start(Thread*) = 0;
|
||||||
virtual Status make(Monitor**) = 0;
|
virtual Status make(Monitor**) = 0;
|
||||||
virtual void abort() = 0;
|
virtual void abort() = 0;
|
||||||
|
|
||||||
void* allocate(unsigned size) {
|
void* allocate(unsigned size) {
|
||||||
unsigned requested = size;
|
void* p = tryAllocate(size);
|
||||||
void* p = allocate(&size);
|
if (p == 0) {
|
||||||
if (size != requested) {
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
|
@ -1685,7 +1685,7 @@ run(Thread* t)
|
|||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
fprintf(stderr, "ip: %d; instruction: 0x%x\n", ip, codeBody(t, code, ip));
|
//fprintf(stderr, "ip: %d; instruction: 0x%x\n", ip, codeBody(t, code, ip));
|
||||||
|
|
||||||
switch (codeBody(t, code, ip++)) {
|
switch (codeBody(t, code, ip++)) {
|
||||||
case aaload: {
|
case aaload: {
|
||||||
|
Loading…
Reference in New Issue
Block a user