mirror of
https://github.com/corda/corda.git
synced 2025-02-28 12:01:14 +00:00
snapshot
This commit is contained in:
parent
1a05eb2739
commit
d4d155c834
77
src/common.h
77
src/common.h
@ -15,6 +15,8 @@
|
|||||||
#define MACRO_MakeNameXY(FX, LINE) MACRO_XY(FX, LINE)
|
#define MACRO_MakeNameXY(FX, LINE) MACRO_XY(FX, LINE)
|
||||||
#define MAKE_NAME(FX) MACRO_MakeNameXY(FX, __LINE__)
|
#define MAKE_NAME(FX) MACRO_MakeNameXY(FX, __LINE__)
|
||||||
|
|
||||||
|
inline void* operator new(size_t, void* p) throw() { return p; }
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
typedef void* object;
|
typedef void* object;
|
||||||
@ -24,6 +26,81 @@ const unsigned BitsPerWord = BytesPerWord * 8;
|
|||||||
|
|
||||||
const unsigned LikelyPageSize = 4 * 1024;
|
const unsigned LikelyPageSize = 4 * 1024;
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
max(unsigned a, unsigned b)
|
||||||
|
{
|
||||||
|
return (a > b ? a : b);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
min(unsigned a, unsigned b)
|
||||||
|
{
|
||||||
|
return (a < b ? a : b);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
pad(unsigned n)
|
||||||
|
{
|
||||||
|
unsigned extra = n % BytesPerWord;
|
||||||
|
return (extra ? n + BytesPerWord - extra : n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
divide(unsigned n, unsigned d)
|
||||||
|
{
|
||||||
|
if (n and d > n) return 1;
|
||||||
|
return (n / d) + (n % d ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
powerOfTwo(unsigned n)
|
||||||
|
{
|
||||||
|
for (; n > 2; n >>= 1) if (n & 1) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
nextPowerOfTwo(unsigned n)
|
||||||
|
{
|
||||||
|
unsigned r = 1;
|
||||||
|
while (r < n) r <<= 1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
log(unsigned n)
|
||||||
|
{
|
||||||
|
if (n < 3) return 1;
|
||||||
|
unsigned r = 0;
|
||||||
|
for (unsigned i = 1; i < n; ++r) i <<= 1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
wordOf(unsigned i)
|
||||||
|
{
|
||||||
|
return i / BitsPerWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
bitOf(unsigned i)
|
||||||
|
{
|
||||||
|
return i % BitsPerWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
indexOf(unsigned word, unsigned bit)
|
||||||
|
{
|
||||||
|
return (word * BitsPerWord) + bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T&
|
||||||
|
cast(object p, unsigned offset)
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif//COMMON_H
|
#endif//COMMON_H
|
||||||
|
128
src/heap.cpp
128
src/heap.cpp
@ -29,24 +29,20 @@ class Segment {
|
|||||||
unsigned index;
|
unsigned index;
|
||||||
unsigned limit;
|
unsigned limit;
|
||||||
|
|
||||||
Iterator(Map* map, void** start, void** end):
|
Iterator(Map* map, unsigned start, unsigned end):
|
||||||
map(map)
|
map(map)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
||||||
index = map->indexOf(start);
|
index = map->indexOf(map->segment->data + start);
|
||||||
assert(map->segment->context,
|
assert(map->segment->context, index == 0 or start != 0);
|
||||||
index == 0 or
|
|
||||||
start != reinterpret_cast<void**>(map->segment->data));
|
|
||||||
|
|
||||||
void** p = reinterpret_cast<void**>(map->segment->data)
|
if (end > map->segment->position) end = map->segment->position;
|
||||||
+ map->segment->position;
|
|
||||||
if (end > p) end = p;
|
|
||||||
|
|
||||||
limit = map->indexOf(end);
|
limit = map->indexOf(map->segment->data + end);
|
||||||
if (static_cast<unsigned>(end - start) % map->scale) ++ limit;
|
if (end - start % map->scale) ++ limit;
|
||||||
|
|
||||||
// printf("iterating from %p (index %d) to %p (index %d) "
|
// printf("iterating from %p (index %d) to %p (index %d) "
|
||||||
// "(%d of %d bytes) (scale: %d)\n",
|
// "(%d of %d bytes) (scale: %d)\n",
|
||||||
@ -87,12 +83,11 @@ class Segment {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void** next() {
|
unsigned next() {
|
||||||
assert(map->segment->context, hasMore());
|
assert(map->segment->context, hasMore());
|
||||||
assert(map->segment->context, map->segment);
|
assert(map->segment->context, map->segment);
|
||||||
|
|
||||||
return reinterpret_cast<void**>(map->segment->data) +
|
return (index++) * map->scale;
|
||||||
((index++) * map->scale);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -101,8 +96,6 @@ class Segment {
|
|||||||
unsigned scale;
|
unsigned scale;
|
||||||
Map* child;
|
Map* child;
|
||||||
|
|
||||||
Map(): Map(0) { }
|
|
||||||
|
|
||||||
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),
|
||||||
@ -117,7 +110,7 @@ class Segment {
|
|||||||
|
|
||||||
unsigned offset() {
|
unsigned offset() {
|
||||||
unsigned n = segment->capacity;
|
unsigned n = segment->capacity;
|
||||||
if (child) n += child->footprint(capacity);
|
if (child) n += child->footprint(segment->capacity);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,20 +164,22 @@ class Segment {
|
|||||||
data()[wordOf(i)] |= static_cast<uintptr_t>(1) << bitOf(i);
|
data()[wordOf(i)] |= static_cast<uintptr_t>(1) << bitOf(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearOnly(void* p) {
|
void clearOnly(unsigned index) {
|
||||||
unsigned index = indexOf(p);
|
|
||||||
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) {
|
||||||
clear(i);
|
clear(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clearOnly(void* p) {
|
||||||
|
clearOnly(indexOf(p));
|
||||||
|
}
|
||||||
|
|
||||||
void clear(void* p) {
|
void clear(void* p) {
|
||||||
clearOnly(p);
|
clearOnly(p);
|
||||||
if (child) child->clear(p);
|
if (child) child->clear(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOnly(void* p, unsigned v = 1) {
|
void setOnly(unsigned index, unsigned v = 1) {
|
||||||
unsigned index = indexOf(p);
|
|
||||||
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) set(i); else clear(i);
|
||||||
@ -194,6 +189,10 @@ class Segment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setOnly(void* p, unsigned v = 1) {
|
||||||
|
setOnly(indexOf(p), v);
|
||||||
|
}
|
||||||
|
|
||||||
void set(void* p, unsigned v = 1) {
|
void set(void* p, unsigned v = 1) {
|
||||||
setOnly(p, v);
|
setOnly(p, v);
|
||||||
assert(segment->context, get(p) == v);
|
assert(segment->context, get(p) == v);
|
||||||
@ -224,6 +223,7 @@ class Segment {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Context* context;
|
||||||
uintptr_t* data;
|
uintptr_t* data;
|
||||||
unsigned position;
|
unsigned position;
|
||||||
unsigned capacity;
|
unsigned capacity;
|
||||||
@ -232,7 +232,6 @@ class Segment {
|
|||||||
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),
|
||||||
capacity(capacity),
|
|
||||||
data(0),
|
data(0),
|
||||||
position(0),
|
position(0),
|
||||||
capacity(capacity),
|
capacity(capacity),
|
||||||
@ -264,8 +263,8 @@ class Segment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* allocate(unsigned size) {
|
void* allocate(unsigned size) {
|
||||||
assert(c, size);
|
assert(context, size);
|
||||||
assert(c, position + size <= capacity);
|
assert(context, position + size <= capacity);
|
||||||
void* p = reinterpret_cast<void**>(data) + position;
|
void* p = reinterpret_cast<void**>(data) + position;
|
||||||
position += size;
|
position += size;
|
||||||
|
|
||||||
@ -278,6 +277,11 @@ class Segment {
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* get(unsigned offset) {
|
||||||
|
assert(context, offset < position);
|
||||||
|
return data + offset;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned remaining() {
|
unsigned remaining() {
|
||||||
return capacity - position;
|
return capacity - position;
|
||||||
}
|
}
|
||||||
@ -352,7 +356,14 @@ enum CollectionMode {
|
|||||||
|
|
||||||
class Context {
|
class Context {
|
||||||
public:
|
public:
|
||||||
Context(System* system, Client* client): system(system), client(client) { }
|
Context(System* system):
|
||||||
|
system(system),
|
||||||
|
client(0),
|
||||||
|
gen1(this, 0),
|
||||||
|
nextGen1(this, 0),
|
||||||
|
gen2(this, 0),
|
||||||
|
nextGen2(this, 0)
|
||||||
|
{ }
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
gen1.dispose();
|
gen1.dispose();
|
||||||
@ -362,7 +373,7 @@ class Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
System* system;
|
System* system;
|
||||||
Client* client;
|
Heap::Client* client;
|
||||||
|
|
||||||
Segment gen1;
|
Segment gen1;
|
||||||
Segment nextGen1;
|
Segment nextGen1;
|
||||||
@ -370,6 +381,7 @@ class Context {
|
|||||||
Segment nextGen2;
|
Segment nextGen2;
|
||||||
|
|
||||||
Segment::Map ageMap;
|
Segment::Map ageMap;
|
||||||
|
Segment::Map nextAgeMap;
|
||||||
Segment::Map pointerMap;
|
Segment::Map pointerMap;
|
||||||
Segment::Map pageMap;
|
Segment::Map pageMap;
|
||||||
Segment::Map heapMap;
|
Segment::Map heapMap;
|
||||||
@ -401,7 +413,7 @@ initGen1(Context* c)
|
|||||||
{
|
{
|
||||||
new (&(c->ageMap)) Segment::Map(&(c->gen1), log(TenureThreshold));
|
new (&(c->ageMap)) Segment::Map(&(c->gen1), log(TenureThreshold));
|
||||||
new (&(c->gen1)) Segment
|
new (&(c->gen1)) Segment
|
||||||
(MinimumGen1Size / BytesPerWord, &(c->ageMap), false);
|
(c, MinimumGen1Size / BytesPerWord, &(c->ageMap), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -412,29 +424,29 @@ initGen2(Context* c)
|
|||||||
(&(c->gen2), 1, LikelyPageSize / BytesPerWord, &(c->pointerMap));
|
(&(c->gen2), 1, LikelyPageSize / BytesPerWord, &(c->pointerMap));
|
||||||
new (&(c->heapMap)) Segment::Map
|
new (&(c->heapMap)) Segment::Map
|
||||||
(&(c->gen2), 1, c->pageMap.scale * 1024, &(c->pageMap));
|
(&(c->gen2), 1, c->pageMap.scale * 1024, &(c->pageMap));
|
||||||
new (&(c->gen2)) Segment(MinimumGen2Size / BytesPerWord, &(c->heapMap));
|
new (&(c->gen2)) Segment(c, MinimumGen2Size / BytesPerWord, &(c->heapMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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(size, &(c->nextAgeMap), false);
|
new (&(c->nextGen1)) Segment(c, size, &(c->nextAgeMap), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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));
|
||||||
new (&(c->heapMap)) Segment::Map
|
new (&(c->heapMap)) Segment::Map
|
||||||
(&(c->nextGen2), 1, c->pageMap.scale * 1024, &(c->pageMap));
|
(&(c->nextGen2), 1, c->pageMap.scale * 1024, &(c->pageMap));
|
||||||
new (&(c->nextGen2)) Segment(size, &(c->heapMap));
|
new (&(c->nextGen2)) Segment(c, size, &(c->heapMap));
|
||||||
c->gen2.map = 0;
|
c->gen2.map = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,11 +468,11 @@ bitset(object o)
|
|||||||
return &cast<uintptr_t>(o, BytesPerWord * 2);
|
return &cast<uintptr_t>(o, BytesPerWord * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
inline object
|
||||||
copyTo(Context* c, Segment* s, object o, unsigned size)
|
copyTo(Context*, Segment* s, object o, unsigned size)
|
||||||
{
|
{
|
||||||
if (s->remaining() < size) {
|
if (s->remaining() < size) {
|
||||||
s->grow(c->sys, size);
|
s->grow(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<object>(s->add(o, size));
|
return static_cast<object>(s->add(o, size));
|
||||||
@ -478,15 +490,15 @@ copy2(Context* c, object o)
|
|||||||
return copyTo(c, &(c->nextGen2), o, size);
|
return copyTo(c, &(c->nextGen2), o, size);
|
||||||
} else if (c->gen1.contains(o)) {
|
} else if (c->gen1.contains(o)) {
|
||||||
unsigned age = c->ageMap.get(o);
|
unsigned age = c->ageMap.get(o);
|
||||||
if (age == Arena::TenureThreshold) {
|
if (age == TenureThreshold) {
|
||||||
if (c->mode == MinorCollection) {
|
if (c->mode == MinorCollection) {
|
||||||
if (c->gen2.front == 0) initGen2(a);
|
if (c->gen2.data == 0) initGen2(c);
|
||||||
|
|
||||||
if (c->gen2.remaining() >= size) {
|
if (c->gen2.remaining() >= size) {
|
||||||
return copyTo(c, &(c->gen2), o, size);
|
return copyTo(c, &(c->gen2), o, size);
|
||||||
} else {
|
} else {
|
||||||
c->mode = OverflowCollection;
|
c->mode = OverflowCollection;
|
||||||
initNextGen2(a);
|
initNextGen2(c);
|
||||||
return copyTo(c, &(c->nextGen2), o, size);
|
return copyTo(c, &(c->nextGen2), o, size);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -810,7 +822,7 @@ collect(Context* c, void** p)
|
|||||||
uintptr_t* bitset;
|
uintptr_t* bitset;
|
||||||
unsigned next;
|
unsigned next;
|
||||||
unsigned total;
|
unsigned total;
|
||||||
} walker(c, copy, bitset(original));
|
} walker(c, bitset(original));
|
||||||
|
|
||||||
assert(c, walker.total > 1);
|
assert(c, walker.total > 1);
|
||||||
|
|
||||||
@ -830,7 +842,7 @@ collect(Context* c, void** p)
|
|||||||
|
|
||||||
void
|
void
|
||||||
collect(Context* c, Segment::Map* map, unsigned start, unsigned end,
|
collect(Context* c, Segment::Map* map, unsigned start, unsigned end,
|
||||||
bool* dirty, bool expectDirty UNUSED)
|
bool* dirty, bool expectDirty)
|
||||||
{
|
{
|
||||||
bool wasDirty = false;
|
bool wasDirty = false;
|
||||||
for (Segment::Map::Iterator it(map, start, end); it.hasMore();) {
|
for (Segment::Map::Iterator it(map, start, end); it.hasMore();) {
|
||||||
@ -843,7 +855,7 @@ collect(Context* c, Segment::Map* map, unsigned start, unsigned end,
|
|||||||
map->clearOnly(s);
|
map->clearOnly(s);
|
||||||
bool childDirty = false;
|
bool childDirty = false;
|
||||||
collect(c, map->child, s, e, &childDirty, true);
|
collect(c, map->child, s, e, &childDirty, true);
|
||||||
if (c->collectionMode == OverflowCollection) {
|
if (c->mode == OverflowCollection) {
|
||||||
return;
|
return;
|
||||||
} else if (childDirty) {
|
} else if (childDirty) {
|
||||||
map->setOnly(s);
|
map->setOnly(s);
|
||||||
@ -851,7 +863,7 @@ collect(Context* c, Segment::Map* map, unsigned start, unsigned end,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(c, map->scale == 1);
|
assert(c, map->scale == 1);
|
||||||
object* p = reinterpret_cast<object*>(map->heap->get(it.next()));
|
object* p = reinterpret_cast<object*>(map->segment->get(it.next()));
|
||||||
|
|
||||||
map->clearOnly(p);
|
map->clearOnly(p);
|
||||||
if (c->nextGen1.contains(*p)) {
|
if (c->nextGen1.contains(*p)) {
|
||||||
@ -860,7 +872,7 @@ collect(Context* c, Segment::Map* map, unsigned start, unsigned end,
|
|||||||
} else {
|
} else {
|
||||||
collect(c, p);
|
collect(c, p);
|
||||||
|
|
||||||
if (c->collectionMode == OverflowCollection) {
|
if (c->mode == OverflowCollection) {
|
||||||
return;
|
return;
|
||||||
} else if (c->gen2.contains(*p)) {
|
} else if (c->gen2.contains(*p)) {
|
||||||
// done
|
// done
|
||||||
@ -903,7 +915,6 @@ collect(Context* c, Segment* s, unsigned limit)
|
|||||||
{
|
{
|
||||||
for (ObjectSegmentIterator it(c, s, limit); it.hasNext();) {
|
for (ObjectSegmentIterator it(c, s, limit); it.hasNext();) {
|
||||||
object p = it.next();
|
object p = it.next();
|
||||||
collect(c, &objectClass(p));
|
|
||||||
|
|
||||||
class Walker : public Heap::Walker {
|
class Walker : public Heap::Walker {
|
||||||
public:
|
public:
|
||||||
@ -911,6 +922,7 @@ collect(Context* c, Segment* s, unsigned limit)
|
|||||||
|
|
||||||
virtual bool visit(unsigned offset) {
|
virtual bool visit(unsigned offset) {
|
||||||
collect(c, &cast<object>(p, offset * BytesPerWord));
|
collect(c, &cast<object>(p, offset * BytesPerWord));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context* c;
|
Context* c;
|
||||||
@ -924,14 +936,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -942,9 +954,11 @@ collect2(Context* c)
|
|||||||
virtual void visit(void** p) {
|
virtual void visit(void** p) {
|
||||||
collect(c, p);
|
collect(c, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Context* c;
|
||||||
} v(c);
|
} v(c);
|
||||||
|
|
||||||
c->iterator->iterate(&v);
|
c->client->visitRoots(&v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -977,6 +991,8 @@ collect(Context* c)
|
|||||||
c->gen1.replaceWith(&(c->nextGen1));
|
c->gen1.replaceWith(&(c->nextGen1));
|
||||||
c->gen2.replaceWith(&(c->nextGen2));
|
c->gen2.replaceWith(&(c->nextGen2));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
default: abort(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1020,8 +1036,22 @@ makeHeap(System* system)
|
|||||||
c.system->free(this);
|
c.system->free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void* follow(void* p) {
|
||||||
|
if (wasCollected(&c, p)) {
|
||||||
|
return ::follow(p);
|
||||||
|
} else {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Context c;
|
Context c;
|
||||||
};
|
};
|
||||||
|
|
||||||
return new (system->allocate(sizeof(Heap))) Heap(system);
|
unsigned count = sizeof(Heap);
|
||||||
|
void* p = system->allocate(&count);
|
||||||
|
if (count != sizeof(Heap)) {
|
||||||
|
system->abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new (p) Heap(system);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ class Heap {
|
|||||||
public:
|
public:
|
||||||
virtual ~Client() { }
|
virtual ~Client() { }
|
||||||
virtual void visitRoots(Visitor*) = 0;
|
virtual void visitRoots(Visitor*) = 0;
|
||||||
virtual void sizeInWords(void*) = 0;
|
virtual unsigned sizeInWords(void*) = 0;
|
||||||
virtual void walk(void*, Walker*) = 0;
|
virtual void walk(void*, Walker*) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,6 +34,7 @@ class Heap {
|
|||||||
virtual void collect(CollectionType type, Client* client) = 0;
|
virtual void collect(CollectionType type, Client* client) = 0;
|
||||||
virtual bool needsMark(void** p) = 0;
|
virtual bool needsMark(void** p) = 0;
|
||||||
virtual void mark(void** p) = 0;
|
virtual void mark(void** p) = 0;
|
||||||
|
virtual void* follow(void* p) = 0;
|
||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
57
src/vm.cpp
57
src/vm.cpp
@ -24,20 +24,6 @@ object allocate(Thread*, unsigned);
|
|||||||
object& arrayBody(Thread*, object, unsigned);
|
object& arrayBody(Thread*, object, unsigned);
|
||||||
void set(Thread*, object&, object);
|
void set(Thread*, object&, object);
|
||||||
|
|
||||||
inline unsigned
|
|
||||||
pad(unsigned n)
|
|
||||||
{
|
|
||||||
unsigned extra = n % BytesPerWord;
|
|
||||||
return (extra ? n + BytesPerWord - extra : n);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline T&
|
|
||||||
cast(object p, unsigned offset)
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
object&
|
object&
|
||||||
objectClass(object o)
|
objectClass(object o)
|
||||||
{
|
{
|
||||||
@ -52,7 +38,17 @@ class Machine {
|
|||||||
|
|
||||||
Machine(System* system, Heap* heap, ClassFinder* classFinder);
|
Machine(System* system, Heap* heap, ClassFinder* classFinder);
|
||||||
|
|
||||||
System* sys;
|
~Machine() {
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
stateLock->dispose();
|
||||||
|
heapLock->dispose();
|
||||||
|
classLock->dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
System* system;
|
||||||
Heap* heap;
|
Heap* heap;
|
||||||
ClassFinder* classFinder;
|
ClassFinder* classFinder;
|
||||||
Thread* rootThread;
|
Thread* rootThread;
|
||||||
@ -95,6 +91,8 @@ class Thread {
|
|||||||
static const unsigned HeapSize = 64 * 1024;
|
static const unsigned HeapSize = 64 * 1024;
|
||||||
static const unsigned StackSize = 64 * 1024;
|
static const unsigned StackSize = 64 * 1024;
|
||||||
|
|
||||||
|
Thread(Machine* m);
|
||||||
|
|
||||||
Machine* vm;
|
Machine* vm;
|
||||||
Thread* next;
|
Thread* next;
|
||||||
Thread* child;
|
Thread* child;
|
||||||
@ -149,7 +147,7 @@ class RawMonitorResource {
|
|||||||
inline void NO_RETURN
|
inline void NO_RETURN
|
||||||
abort(Thread* t)
|
abort(Thread* t)
|
||||||
{
|
{
|
||||||
t->vm->sys->abort(); // this should not return
|
t->vm->system->abort(); // this should not return
|
||||||
::abort();
|
::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,23 +171,14 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
|
|||||||
classMap(0),
|
classMap(0),
|
||||||
types(0)
|
types(0)
|
||||||
{
|
{
|
||||||
if (not system->success(system->make(&(m->stateLock))) or
|
if (not system->success(system->make(&stateLock)) or
|
||||||
not system->success(system->make(&(m->heapLock))) or
|
not system->success(system->make(&heapLock)) or
|
||||||
not system->success(system->make(&(m->classLock))))
|
not system->success(system->make(&classLock)))
|
||||||
{
|
{
|
||||||
system->abort();
|
system->abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
dispose(Machine* m)
|
|
||||||
{
|
|
||||||
m->stateLock->dispose();
|
|
||||||
m->heapLock->dispose();
|
|
||||||
m->classLock->dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Thread::Thread(Machine* m):
|
Thread::Thread(Machine* m):
|
||||||
vm(m),
|
vm(m),
|
||||||
next(0),
|
next(0),
|
||||||
@ -205,11 +194,13 @@ Thread::Thread(Machine* m):
|
|||||||
protector(0)
|
protector(0)
|
||||||
{
|
{
|
||||||
if (m->rootThread == 0) {
|
if (m->rootThread == 0) {
|
||||||
m->rootThread = t;
|
m->rootThread = this;
|
||||||
|
|
||||||
|
Thread* t = this;
|
||||||
|
|
||||||
#include "type-initializations.cpp"
|
#include "type-initializations.cpp"
|
||||||
|
|
||||||
m->classMap = makeHashMap(t, 0, 0);
|
m->classMap = makeHashMap(this, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,6 +244,8 @@ collect(Machine* m, Heap::CollectionType type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned sizeInWords(void* p) {
|
virtual unsigned sizeInWords(void* p) {
|
||||||
|
Thread* t = m->rootThread;
|
||||||
|
|
||||||
p = m->heap->follow(p);
|
p = m->heap->follow(p);
|
||||||
object class_ = m->heap->follow(objectClass(p));
|
object class_ = m->heap->follow(objectClass(p));
|
||||||
|
|
||||||
@ -265,6 +258,8 @@ collect(Machine* m, Heap::CollectionType type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void walk(void* p, Heap::Walker* w) {
|
virtual void walk(void* p, Heap::Walker* w) {
|
||||||
|
Thread* t = m->rootThread;
|
||||||
|
|
||||||
p = m->heap->follow(p);
|
p = m->heap->follow(p);
|
||||||
object class_ = m->heap->follow(objectClass(p));
|
object class_ = m->heap->follow(objectClass(p));
|
||||||
unsigned fixedSize = classFixedSize(t, class_);
|
unsigned fixedSize = classFixedSize(t, class_);
|
||||||
@ -273,7 +268,7 @@ collect(Machine* m, Heap::CollectionType type)
|
|||||||
|
|
||||||
object objectMask = m->heap->follow(classObjectMask(t, class_));
|
object objectMask = m->heap->follow(classObjectMask(t, class_));
|
||||||
int mask[intArrayLength(t, objectMask)];
|
int mask[intArrayLength(t, objectMask)];
|
||||||
memcpy(mask, &intArrayBody(t, objectMask),
|
memcpy(mask, &intArrayBody(t, objectMask, 0),
|
||||||
intArrayLength(t, objectMask) * 4);
|
intArrayLength(t, objectMask) * 4);
|
||||||
|
|
||||||
for (unsigned i = 0; i < fixedSize; ++i) {
|
for (unsigned i = 0; i < fixedSize; ++i) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user