mirror of
https://github.com/corda/corda.git
synced 2024-12-28 16:58:55 +00:00
sketch of finalizer/weak reference overhaul; type generator bugfixes involving array member layout
This commit is contained in:
parent
a77693fb29
commit
b70e4b368f
@ -83,8 +83,8 @@ arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t sl = cast<uint32_t>(s, offset * BytesPerWord);
|
intptr_t sl = cast<uintptr_t>(s, offset * BytesPerWord);
|
||||||
int32_t dl = cast<uint32_t>(d, offset * BytesPerWord);
|
intptr_t dl = cast<uintptr_t>(d, offset * BytesPerWord);
|
||||||
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
|
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
|
||||||
dstOffset >= 0 and dstOffset + length < dl))
|
dstOffset >= 0 and dstOffset + length < dl))
|
||||||
{
|
{
|
||||||
|
25
src/heap.cpp
25
src/heap.cpp
@ -1412,6 +1412,31 @@ makeHeap(System* system)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual Status status(void* p) {
|
||||||
|
p = mask(p);
|
||||||
|
|
||||||
|
if (c.nextGen1.contains(p)) {
|
||||||
|
return Reachable;
|
||||||
|
} else if (c.nextGen2.contains(p)
|
||||||
|
or (c.gen2.contains(p)
|
||||||
|
and c.gen2.indexOf(p) >= c.gen2Base))
|
||||||
|
{
|
||||||
|
return Tenured;
|
||||||
|
} else if (wasCollected(&c, p)) {
|
||||||
|
return Reachable;
|
||||||
|
} else {
|
||||||
|
return Unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual CollectionType collectionType() {
|
||||||
|
if (c.mode == ::MinorCollection) {
|
||||||
|
return MinorCollection;
|
||||||
|
} else {
|
||||||
|
return MajorCollection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Context c;
|
Context c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,12 @@ class Heap {
|
|||||||
MajorCollection
|
MajorCollection
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
Reachable,
|
||||||
|
Unreachable,
|
||||||
|
Tenured
|
||||||
|
};
|
||||||
|
|
||||||
class Visitor {
|
class Visitor {
|
||||||
public:
|
public:
|
||||||
virtual ~Visitor() { }
|
virtual ~Visitor() { }
|
||||||
@ -39,6 +45,8 @@ class Heap {
|
|||||||
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* follow(void* p) = 0;
|
||||||
|
virtual Status status(void* p) = 0;
|
||||||
|
virtual CollectionType collectionType() = 0;
|
||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
189
src/machine.cpp
189
src/machine.cpp
@ -127,6 +127,145 @@ visitRoots(Thread* t, Heap::Visitor* v)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
postVisit(Thread* t, Heap::Visitor* v)
|
||||||
|
{
|
||||||
|
Machine* m = t->vm;
|
||||||
|
|
||||||
|
object firstNewTenuredFinalizer = 0;
|
||||||
|
object lastNewTenuredFinalizer = 0;
|
||||||
|
|
||||||
|
for (object* p = &(m->finalizers); *p;) {
|
||||||
|
v->visit(p);
|
||||||
|
|
||||||
|
if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) {
|
||||||
|
// target is unreachable - queue it up for finalization
|
||||||
|
|
||||||
|
v->visit(&finalizerTarget(t, *p));
|
||||||
|
|
||||||
|
object finalizer = *p;
|
||||||
|
*p = finalizerNext(t, finalizer);
|
||||||
|
finalizerNext(t, finalizer) = m->finalizeQueue;
|
||||||
|
m->finalizeQueue = finalizer;
|
||||||
|
} else {
|
||||||
|
// target is reachable
|
||||||
|
|
||||||
|
v->visit(&finalizerTarget(t, *p));
|
||||||
|
|
||||||
|
if (m->heap->status(*p) == Heap::Tenured) {
|
||||||
|
// the finalizer is tenured, so we remove it from
|
||||||
|
// m->finalizers and later add it to m->tenuredFinalizers
|
||||||
|
|
||||||
|
if (lastNewTenuredFinalizer == 0) {
|
||||||
|
lastNewTenuredFinalizer = *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
object finalizer = *p;
|
||||||
|
*p = finalizerNext(t, finalizer);
|
||||||
|
finalizerNext(t, finalizer) = firstNewTenuredFinalizer;
|
||||||
|
firstNewTenuredFinalizer = finalizer;
|
||||||
|
} else {
|
||||||
|
p = &finalizerNext(t, *p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object firstNewTenuredWeakReference = 0;
|
||||||
|
object lastNewTenuredWeakReference = 0;
|
||||||
|
|
||||||
|
for (object* p = &(m->weakReferences); *p;) {
|
||||||
|
if (m->heap->status(*p) == Heap::Unreachable) {
|
||||||
|
// reference is unreachable - remove it from the list
|
||||||
|
|
||||||
|
*p = jreferenceNext(t, *p);
|
||||||
|
} else if (m->heap->status(jreferenceTarget(t, *p)) == Heap::Unreachable) {
|
||||||
|
// target is unreachable - clear the reference and remove it
|
||||||
|
// from the list
|
||||||
|
|
||||||
|
jreferenceTarget(t, *p) = 0;
|
||||||
|
*p = jreferenceNext(t, *p);
|
||||||
|
} else {
|
||||||
|
// both reference and target are reachable
|
||||||
|
|
||||||
|
v->visit(&jreferenceTarget(t, *p));
|
||||||
|
v->visit(p);
|
||||||
|
|
||||||
|
if (m->heap->status(*p) == Heap::Tenured) {
|
||||||
|
// the reference is tenured, so we remove it from
|
||||||
|
// m->weakReferences and later add it to
|
||||||
|
// m->tenuredWeakReferences
|
||||||
|
|
||||||
|
if (lastNewTenuredWeakReference == 0) {
|
||||||
|
lastNewTenuredWeakReference = *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
object reference = *p;
|
||||||
|
*p = jreferenceNext(t, reference);
|
||||||
|
jreferenceNext(t, reference) = firstNewTenuredWeakReference;
|
||||||
|
firstNewTenuredWeakReference = reference;
|
||||||
|
} else {
|
||||||
|
p = &jreferenceNext(t, *p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->heap->collectionType() == Heap::MajorCollection) {
|
||||||
|
for (object* p = &(m->tenuredFinalizers); *p;) {
|
||||||
|
v->visit(p);
|
||||||
|
|
||||||
|
if (m->heap->status(finalizerTarget(t, *p)) == Heap::Unreachable) {
|
||||||
|
// target is unreachable - queue it up for finalization
|
||||||
|
|
||||||
|
v->visit(&finalizerTarget(t, *p));
|
||||||
|
|
||||||
|
object finalizer = *p;
|
||||||
|
*p = finalizerNext(t, finalizer);
|
||||||
|
finalizerNext(t, finalizer) = m->finalizeQueue;
|
||||||
|
m->finalizeQueue = finalizer;
|
||||||
|
} else {
|
||||||
|
// target is reachable
|
||||||
|
|
||||||
|
v->visit(&finalizerTarget(t, *p));
|
||||||
|
|
||||||
|
p = &finalizerNext(t, *p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (object* p = &(m->tenuredWeakReferences); *p;) {
|
||||||
|
if (m->heap->status(*p) == Heap::Unreachable) {
|
||||||
|
// reference is unreachable - remove it from the list
|
||||||
|
|
||||||
|
*p = jreferenceNext(t, *p);
|
||||||
|
} else if (m->heap->status(jreferenceTarget(t, *p))
|
||||||
|
== Heap::Unreachable)
|
||||||
|
{
|
||||||
|
// target is unreachable - clear the reference and remove it
|
||||||
|
// from the list
|
||||||
|
|
||||||
|
jreferenceTarget(t, *p) = 0;
|
||||||
|
*p = jreferenceNext(t, *p);
|
||||||
|
} else {
|
||||||
|
// target is reachable
|
||||||
|
|
||||||
|
v->visit(&jreferenceTarget(t, *p));
|
||||||
|
v->visit(p);
|
||||||
|
|
||||||
|
p = &jreferenceNext(t, *p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastNewTenuredFinalizer) {
|
||||||
|
finalizerNext(t, lastNewTenuredFinalizer) = m->tenuredFinalizers;
|
||||||
|
m->tenuredFinalizers = lastNewTenuredFinalizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastNewTenuredWeakReference) {
|
||||||
|
jreferenceNext(t, lastNewTenuredWeakReference) = m->tenuredWeakReferences;
|
||||||
|
m->tenuredWeakReferences = lastNewTenuredWeakReference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
postCollect(Thread* t)
|
postCollect(Thread* t)
|
||||||
{
|
{
|
||||||
@ -160,37 +299,7 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
::visitRoots(t, v);
|
::visitRoots(t, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* t = m->rootThread;
|
postVisit(m->rootThread, v);
|
||||||
for (object* f = &(m->finalizers); *f;) {
|
|
||||||
object o = finalizerTarget(t, *f);
|
|
||||||
if (m->heap->follow(o) == o) {
|
|
||||||
// object has not been collected
|
|
||||||
object x = *f;
|
|
||||||
*f = finalizerNext(t, x);
|
|
||||||
finalizerNext(t, x) = m->doomed;
|
|
||||||
m->doomed = x;
|
|
||||||
} else {
|
|
||||||
f = &finalizerNext(t, *f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v->visit(&(m->finalizers));
|
|
||||||
v->visit(&(m->doomed));
|
|
||||||
|
|
||||||
for (object p = m->weakReferences; p;) {
|
|
||||||
object o = jreferenceTarget(t, p);
|
|
||||||
object followed = m->heap->follow(o);
|
|
||||||
if (followed == o) {
|
|
||||||
// object has not been collected
|
|
||||||
jreferenceTarget(t, p) = 0;
|
|
||||||
} else {
|
|
||||||
jreferenceTarget(t, p) = followed;
|
|
||||||
}
|
|
||||||
|
|
||||||
object last = p;
|
|
||||||
p = jreferenceNext(t, p);
|
|
||||||
jreferenceNext(t, last) = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned sizeInWords(object o) {
|
virtual unsigned sizeInWords(object o) {
|
||||||
@ -256,7 +365,8 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
unsigned fixedSize = classFixedSize(t, class_);
|
unsigned fixedSize = classFixedSize(t, class_);
|
||||||
unsigned arrayElementSize = classArrayElementSize(t, class_);
|
unsigned arrayElementSize = classArrayElementSize(t, class_);
|
||||||
unsigned arrayLength
|
unsigned arrayLength
|
||||||
= (arrayElementSize ? cast<uint32_t>(p, fixedSize - 4) : 0);
|
= (arrayElementSize ?
|
||||||
|
cast<uintptr_t>(p, fixedSize - BytesPerWord) : 0);
|
||||||
|
|
||||||
int mask[intArrayLength(t, objectMask)];
|
int mask[intArrayLength(t, objectMask)];
|
||||||
memcpy(mask, &intArrayBody(t, objectMask, 0),
|
memcpy(mask, &intArrayBody(t, objectMask, 0),
|
||||||
@ -317,13 +427,11 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
|
|
||||||
postCollect(m->rootThread);
|
postCollect(m->rootThread);
|
||||||
|
|
||||||
for (object f = m->doomed; f; f = finalizerNext(t, f)) {
|
for (object f = m->finalizeQueue; f; f = finalizerNext(t, f)) {
|
||||||
reinterpret_cast<void (*)(Thread*, object)>(finalizerFinalize(t, f))
|
reinterpret_cast<void (*)(Thread*, object)>(finalizerFinalize(t, f))
|
||||||
(t, finalizerTarget(t, f));
|
(t, finalizerTarget(t, f));
|
||||||
}
|
}
|
||||||
m->doomed = 0;
|
m->finalizeQueue = 0;
|
||||||
|
|
||||||
m->weakReferences = 0;
|
|
||||||
|
|
||||||
killZombies(t, m->rootThread);
|
killZombies(t, m->rootThread);
|
||||||
}
|
}
|
||||||
@ -372,8 +480,9 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
|
|||||||
monitorMap(0),
|
monitorMap(0),
|
||||||
types(0),
|
types(0),
|
||||||
finalizers(0),
|
finalizers(0),
|
||||||
doomed(0),
|
tenuredFinalizers(0),
|
||||||
weakReferences(0),
|
finalizeQueue(0),
|
||||||
|
tenuredWeakReferences(0),
|
||||||
unsafe(false)
|
unsafe(false)
|
||||||
{
|
{
|
||||||
jni::populate(&jniEnvVTable);
|
jni::populate(&jniEnvVTable);
|
||||||
@ -912,6 +1021,10 @@ objectMonitor(Thread* t, object o)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
noop()
|
||||||
|
{ }
|
||||||
|
|
||||||
#include "type-constructors.cpp"
|
#include "type-constructors.cpp"
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
@ -1076,6 +1076,9 @@ strcmp(const int8_t* a, const int8_t* b)
|
|||||||
reinterpret_cast<const char*>(b));
|
reinterpret_cast<const char*>(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
noop();
|
||||||
|
|
||||||
class Machine {
|
class Machine {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
@ -1108,8 +1111,10 @@ class Machine {
|
|||||||
object monitorMap;
|
object monitorMap;
|
||||||
object types;
|
object types;
|
||||||
object finalizers;
|
object finalizers;
|
||||||
object doomed;
|
object tenuredFinalizers;
|
||||||
|
object finalizeQueue;
|
||||||
object weakReferences;
|
object weakReferences;
|
||||||
|
object tenuredWeakReferences;
|
||||||
bool unsafe;
|
bool unsafe;
|
||||||
JNIEnvVTable jniEnvVTable;
|
JNIEnvVTable jniEnvVTable;
|
||||||
};
|
};
|
||||||
@ -1639,9 +1644,16 @@ hash(const int8_t* s, unsigned length)
|
|||||||
inline unsigned
|
inline unsigned
|
||||||
baseSize(Thread* t, object o, object class_)
|
baseSize(Thread* t, object o, object class_)
|
||||||
{
|
{
|
||||||
|
if (classArrayElementSize(t, class_)) {
|
||||||
|
noop();
|
||||||
|
if (cast<uintptr_t>(o, classFixedSize(t, class_) - BytesPerWord)) {
|
||||||
|
noop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return divide(classFixedSize(t, class_), BytesPerWord)
|
return divide(classFixedSize(t, class_), BytesPerWord)
|
||||||
+ divide(classArrayElementSize(t, class_)
|
+ divide(classArrayElementSize(t, class_)
|
||||||
* cast<uint32_t>(o, classFixedSize(t, class_) - 4),
|
* cast<uintptr_t>(o, classFixedSize(t, class_) - BytesPerWord),
|
||||||
BytesPerWord);
|
BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ addMember(Object* o, Object* member)
|
|||||||
case Object::Type: case Object::Pod:
|
case Object::Type: case Object::Pod:
|
||||||
if (member->type == Object::Array) {
|
if (member->type == Object::Array) {
|
||||||
static_cast<Type*>(o)->members.append
|
static_cast<Type*>(o)->members.append
|
||||||
(Scalar::make(o, 0, "uint32_t", "length", sizeof(uint32_t)));
|
(Scalar::make(o, 0, "uintptr_t", "length", sizeof(uintptr_t)));
|
||||||
}
|
}
|
||||||
static_cast<Type*>(o)->members.append(member);
|
static_cast<Type*>(o)->members.append(member);
|
||||||
break;
|
break;
|
||||||
@ -1390,7 +1390,7 @@ typeFixedSize(Object* type)
|
|||||||
Object* m = it.next();
|
Object* m = it.next();
|
||||||
switch (m->type) {
|
switch (m->type) {
|
||||||
case Object::Scalar: {
|
case Object::Scalar: {
|
||||||
length = pad(it.offset() + it.space());
|
length = pad(it.offset() + it.size());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Object::Array: break;
|
case Object::Array: break;
|
||||||
@ -1521,7 +1521,7 @@ writeInitializations(Output* out, Object* declarations)
|
|||||||
|
|
||||||
out->write("t->vm->types = allocate(t, pad((");
|
out->write("t->vm->types = allocate(t, pad((");
|
||||||
out->write(count);
|
out->write(count);
|
||||||
out->write(" * sizeof(void*)) + 4 + sizeof(void*)));\n");
|
out->write(" * sizeof(void*)) + sizeof(uintptr_t) + sizeof(void*)));\n");
|
||||||
out->write("cast<object>(t->vm->types, 0) = 0;\n");
|
out->write("cast<object>(t->vm->types, 0) = 0;\n");
|
||||||
out->write("arrayLength(t, t->vm->types) = ");
|
out->write("arrayLength(t, t->vm->types) = ");
|
||||||
out->write(count);
|
out->write(count);
|
||||||
|
@ -80,9 +80,9 @@
|
|||||||
(object third))
|
(object third))
|
||||||
|
|
||||||
(type finalizer
|
(type finalizer
|
||||||
(object target)
|
(void* target)
|
||||||
(void* finalize)
|
(void* finalize)
|
||||||
(object next))
|
(void* next))
|
||||||
|
|
||||||
(type hashMap
|
(type hashMap
|
||||||
(uint32_t size)
|
(uint32_t size)
|
||||||
|
Loading…
Reference in New Issue
Block a user