sketch of finalizer/weak reference overhaul; type generator bugfixes involving array member layout

This commit is contained in:
Joel Dice 2007-07-09 19:43:43 -06:00
parent a77693fb29
commit b70e4b368f
7 changed files with 205 additions and 47 deletions

View File

@ -83,8 +83,8 @@ arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset,
}
}
int32_t sl = cast<uint32_t>(s, offset * BytesPerWord);
int32_t dl = cast<uint32_t>(d, offset * BytesPerWord);
intptr_t sl = cast<uintptr_t>(s, offset * BytesPerWord);
intptr_t dl = cast<uintptr_t>(d, offset * BytesPerWord);
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
dstOffset >= 0 and dstOffset + length < dl))
{

View File

@ -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;
};

View File

@ -12,6 +12,12 @@ class Heap {
MajorCollection
};
enum Status {
Reachable,
Unreachable,
Tenured
};
class Visitor {
public:
virtual ~Visitor() { }
@ -39,6 +45,8 @@ class Heap {
virtual bool needsMark(void** p) = 0;
virtual void mark(void** p) = 0;
virtual void* follow(void* p) = 0;
virtual Status status(void* p) = 0;
virtual CollectionType collectionType() = 0;
virtual void dispose() = 0;
};

View File

@ -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
postCollect(Thread* t)
{
@ -160,37 +299,7 @@ collect(Thread* t, Heap::CollectionType type)
::visitRoots(t, v);
}
Thread* t = m->rootThread;
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;
}
postVisit(m->rootThread, v);
}
virtual unsigned sizeInWords(object o) {
@ -256,7 +365,8 @@ collect(Thread* t, Heap::CollectionType type)
unsigned fixedSize = classFixedSize(t, class_);
unsigned arrayElementSize = classArrayElementSize(t, class_);
unsigned arrayLength
= (arrayElementSize ? cast<uint32_t>(p, fixedSize - 4) : 0);
= (arrayElementSize ?
cast<uintptr_t>(p, fixedSize - BytesPerWord) : 0);
int mask[intArrayLength(t, objectMask)];
memcpy(mask, &intArrayBody(t, objectMask, 0),
@ -317,13 +427,11 @@ collect(Thread* t, Heap::CollectionType type)
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))
(t, finalizerTarget(t, f));
}
m->doomed = 0;
m->weakReferences = 0;
m->finalizeQueue = 0;
killZombies(t, m->rootThread);
}
@ -372,8 +480,9 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
monitorMap(0),
types(0),
finalizers(0),
doomed(0),
weakReferences(0),
tenuredFinalizers(0),
finalizeQueue(0),
tenuredWeakReferences(0),
unsafe(false)
{
jni::populate(&jniEnvVTable);
@ -912,6 +1021,10 @@ objectMonitor(Thread* t, object o)
}
}
void
noop()
{ }
#include "type-constructors.cpp"
} // namespace vm

View File

@ -1076,6 +1076,9 @@ strcmp(const int8_t* a, const int8_t* b)
reinterpret_cast<const char*>(b));
}
void
noop();
class Machine {
public:
enum {
@ -1108,8 +1111,10 @@ class Machine {
object monitorMap;
object types;
object finalizers;
object doomed;
object tenuredFinalizers;
object finalizeQueue;
object weakReferences;
object tenuredWeakReferences;
bool unsafe;
JNIEnvVTable jniEnvVTable;
};
@ -1639,9 +1644,16 @@ hash(const int8_t* s, unsigned length)
inline unsigned
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)
+ divide(classArrayElementSize(t, class_)
* cast<uint32_t>(o, classFixedSize(t, class_) - 4),
* cast<uintptr_t>(o, classFixedSize(t, class_) - BytesPerWord),
BytesPerWord);
}

View File

@ -342,7 +342,7 @@ addMember(Object* o, Object* member)
case Object::Type: case Object::Pod:
if (member->type == Object::Array) {
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);
break;
@ -1390,7 +1390,7 @@ typeFixedSize(Object* type)
Object* m = it.next();
switch (m->type) {
case Object::Scalar: {
length = pad(it.offset() + it.space());
length = pad(it.offset() + it.size());
} break;
case Object::Array: break;
@ -1521,7 +1521,7 @@ writeInitializations(Output* out, Object* declarations)
out->write("t->vm->types = allocate(t, pad((");
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("arrayLength(t, t->vm->types) = ");
out->write(count);

View File

@ -80,9 +80,9 @@
(object third))
(type finalizer
(object target)
(void* target)
(void* finalize)
(object next))
(void* next))
(type hashMap
(uint32_t size)