From b70e4b368ff42839d7d362947893b04fbe8216ba Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 9 Jul 2007 19:43:43 -0600 Subject: [PATCH] sketch of finalizer/weak reference overhaul; type generator bugfixes involving array member layout --- src/builtin.cpp | 4 +- src/heap.cpp | 25 ++++++ src/heap.h | 8 ++ src/machine.cpp | 189 ++++++++++++++++++++++++++++++++--------- src/machine.h | 16 +++- src/type-generator.cpp | 6 +- src/types.def | 4 +- 7 files changed, 205 insertions(+), 47 deletions(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index c15e4329a8..901ab309f9 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -83,8 +83,8 @@ arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset, } } - int32_t sl = cast(s, offset * BytesPerWord); - int32_t dl = cast(d, offset * BytesPerWord); + intptr_t sl = cast(s, offset * BytesPerWord); + intptr_t dl = cast(d, offset * BytesPerWord); if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and dstOffset >= 0 and dstOffset + length < dl)) { diff --git a/src/heap.cpp b/src/heap.cpp index c00f7043f4..6d3d96568e 100644 --- a/src/heap.cpp +++ b/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; }; diff --git a/src/heap.h b/src/heap.h index 4efe8ec5ca..f8f25ba8b6 100644 --- a/src/heap.h +++ b/src/heap.h @@ -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; }; diff --git a/src/machine.cpp b/src/machine.cpp index e2a6988a75..3d2afc4355 100644 --- a/src/machine.cpp +++ b/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 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(p, fixedSize - 4) : 0); + = (arrayElementSize ? + cast(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(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 diff --git a/src/machine.h b/src/machine.h index 93ecc743ff..b4866ad459 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1076,6 +1076,9 @@ strcmp(const int8_t* a, const int8_t* b) reinterpret_cast(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(o, classFixedSize(t, class_) - BytesPerWord)) { + noop(); + } + } + return divide(classFixedSize(t, class_), BytesPerWord) + divide(classArrayElementSize(t, class_) - * cast(o, classFixedSize(t, class_) - 4), + * cast(o, classFixedSize(t, class_) - BytesPerWord), BytesPerWord); } diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 9a5017183b..d15726ddbd 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -342,7 +342,7 @@ addMember(Object* o, Object* member) case Object::Type: case Object::Pod: if (member->type == Object::Array) { static_cast(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(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(t->vm->types, 0) = 0;\n"); out->write("arrayLength(t, t->vm->types) = "); out->write(count); diff --git a/src/types.def b/src/types.def index 057cd26672..2096ba915d 100644 --- a/src/types.def +++ b/src/types.def @@ -80,9 +80,9 @@ (object third)) (type finalizer - (object target) + (void* target) (void* finalize) - (object next)) + (void* next)) (type hashMap (uint32_t size)