simplify monitor lookup; add finalization

This commit is contained in:
Joel Dice 2007-07-02 08:19:05 -06:00
parent 8acb32e4cb
commit 32b5d070fb
4 changed files with 160 additions and 130 deletions

View File

@ -707,13 +707,8 @@ bitset(Context* c, object o)
} }
inline object inline object
copyTo(Context* c, Segment* s, object o) copyTo(Context* c, Segment* s, object o, unsigned size)
{ {
class Allocator: public Heap::Allocator {
public:
Allocator(Segment* s): s(s) { }
virtual void* allocate(unsigned size) {
if (s->remaining() < size) { if (s->remaining() < size) {
s->ensure(size); s->ensure(size);
@ -733,22 +728,21 @@ copyTo(Context* c, Segment* s, object o)
} }
} }
return s->allocate(size); object dst = s->allocate(size);
} c->client->copy(o, dst);
} allocator(s); return dst;
c->client->copy(o, &allocator);
return p;
} }
object object
copy2(Context* c, object o) copy2(Context* c, object o)
{ {
unsigned size = c->client->copiedSizeInWords(o);
if (c->gen2.contains(o)) { if (c->gen2.contains(o)) {
assert(c, c->mode == MajorCollection assert(c, c->mode == MajorCollection
or c->mode == Gen2Collection); or c->mode == Gen2Collection);
return copyTo(c, &(c->nextGen2), o); 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 == TenureThreshold) { if (age == TenureThreshold) {
@ -760,7 +754,7 @@ copy2(Context* c, object o)
c->gen2Base = c->gen2.position(); c->gen2Base = c->gen2.position();
} }
return copyTo(c, &(c->gen2), o); return copyTo(c, &(c->gen2), o, size);
} else { } else {
if (Verbose) { if (Verbose) {
fprintf(stderr, "overflow collection\n"); fprintf(stderr, "overflow collection\n");
@ -768,13 +762,13 @@ copy2(Context* c, object o)
c->mode = OverflowCollection; c->mode = OverflowCollection;
initNextGen2(c); initNextGen2(c);
return copyTo(c, &(c->nextGen2), o); return copyTo(c, &(c->nextGen2), o, size);
} }
} else { } else {
return copyTo(c, &(c->nextGen2), o); return copyTo(c, &(c->nextGen2), o, size);
} }
} else { } else {
o = copyTo(c, &(c->nextGen1), o); o = copyTo(c, &(c->nextGen1), o, size);
c->nextAgeMap.setOnly(o, age + 1); c->nextAgeMap.setOnly(o, age + 1);
return o; return o;
} }
@ -782,7 +776,7 @@ copy2(Context* c, object o)
assert(c, not c->nextGen1.contains(o)); assert(c, not c->nextGen1.contains(o));
assert(c, not c->nextGen2.contains(o)); assert(c, not c->nextGen2.contains(o));
o = copyTo(c, &(c->nextGen1), o); o = copyTo(c, &(c->nextGen1), o, size);
c->nextAgeMap.clear(o); c->nextAgeMap.clear(o);

View File

@ -24,18 +24,13 @@ class Heap {
virtual bool visit(unsigned) = 0; virtual bool visit(unsigned) = 0;
}; };
class Allocator {
public:
virtual ~Allocator() { }
virtual void* allocate(unsigned sizeInWords) = 0;
};
class Client { class Client {
public: public:
virtual ~Client() { } virtual ~Client() { }
virtual void visitRoots(Visitor*) = 0; virtual void visitRoots(Visitor*) = 0;
virtual unsigned sizeInWords(void*) = 0; virtual unsigned sizeInWords(void*) = 0;
virtual void copy(void*, Allocator*) = 0; virtual unsigned copiedSizeInWords(void*) = 0;
virtual void copy(void*, void*) = 0;
virtual void walk(void*, Walker*) = 0; virtual void walk(void*, Walker*) = 0;
}; };

View File

@ -93,6 +93,11 @@
(object second) (object second)
(object third)) (object third))
(type finalizer
(object target)
(void* finalize)
(object next))
(type hashMap (type hashMap
(uint32_t size) (uint32_t size)
(object array)) (object array))

View File

@ -25,8 +25,6 @@ const bool Debug = false;
const uintptr_t HashTakenMark = 1; const uintptr_t HashTakenMark = 1;
const uintptr_t ExtendedMark = 2; const uintptr_t ExtendedMark = 2;
const uintptr_t MonitorFlag
= static_cast<uintptr_t>(1) << ((BytesPerWord * 8) - 1);
class Thread; class Thread;
@ -81,13 +79,15 @@ class Machine {
System::Monitor* stateLock; System::Monitor* stateLock;
System::Monitor* heapLock; System::Monitor* heapLock;
System::Monitor* classLock; System::Monitor* classLock;
System::Monitor* monitorMapLock; System::Monitor* finalizerLock;
System::Library* libraries; System::Library* libraries;
object classMap; object classMap;
object bootstrapClassMap; object bootstrapClassMap;
object builtinMap; object builtinMap;
object monitorMap; object monitorMap;
object types; object types;
object finalizers;
object doomed;
bool unsafe; bool unsafe;
JNIEnvVTable jniEnvVTable; JNIEnvVTable jniEnvVTable;
}; };
@ -271,30 +271,7 @@ baseSize(Thread* t, object o, object class_)
unsigned unsigned
extendedSize(Thread* t, object o, unsigned baseSize) extendedSize(Thread* t, object o, unsigned baseSize)
{ {
unsigned n = baseSize; return baseSize + objectExtended(t, o);
if (objectExtended(t, o)) {
if (extendedWord(t, o, n) & MonitorFlag) {
n += BytesPerWord;
}
n += BytesPerWord;
}
return n;
}
inline bool
monitorAttached(Thread* t, object o, unsigned baseSize)
{
return objectExtended(t, o)
and (extendedWord(t, o, baseSize) & MonitorFlag);
}
inline System::Monitor*&
attachedMonitor(Thread* t, object o, unsigned baseSize)
{
assert(t, monitorAttached(t, o, baseSize));
return cast<System::Monitor*>(o, (baseSize + 1) * BytesPerWord);
} }
inline bool inline bool
@ -320,7 +297,7 @@ inline uint32_t
objectHash(Thread* t, object o) objectHash(Thread* t, object o)
{ {
if (objectExtended(t, o)) { if (objectExtended(t, o)) {
return extendedWord(t, o, baseSize(t, o, objectClass(o))) & PointerMask; return extendedWord(t, o, baseSize(t, o, objectClass(t, o)));
} else { } else {
markHashTaken(t, o); markHashTaken(t, o);
return takeHash(t, o); return takeHash(t, o);
@ -402,7 +379,8 @@ hashMapFind(Thread* t, object map, object key,
} }
void void
hashMapGrow(Thread* t, object map, uint32_t (*hash)(Thread*, object)) hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
unsigned size)
{ {
PROTECT(t, map); PROTECT(t, map);
@ -410,7 +388,7 @@ hashMapGrow(Thread* t, object map, uint32_t (*hash)(Thread*, object))
unsigned oldLength = (oldArray ? arrayLength(t, oldArray) : 0); unsigned oldLength = (oldArray ? arrayLength(t, oldArray) : 0);
PROTECT(t, oldArray); PROTECT(t, oldArray);
unsigned newLength = (oldLength ? oldLength * 2 : 32); unsigned newLength = max(nextPowerOfTwo(size), 16);
object newArray = makeArray(t, newLength, true); object newArray = makeArray(t, newLength, true);
if (oldArray) { if (oldArray) {
@ -446,7 +424,7 @@ hashMapInsert(Thread* t, object map, object key, object value,
PROTECT(t, key); PROTECT(t, key);
PROTECT(t, value); PROTECT(t, value);
hashMapGrow(t, map, hash); hashMapResize(t, map, hash, arrayLength(t, array) * 2);
array = hashMapArray(t, map); array = hashMapArray(t, map);
} }
@ -458,6 +436,39 @@ hashMapInsert(Thread* t, object map, object key, object value,
set(t, arrayBody(t, array, index), n); set(t, arrayBody(t, array, index), n);
} }
object
hashMapRemove(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object array = hashMapArray(t, map);
object o = 0;
if (array) {
unsigned index = hash(t, key) & (arrayLength(t, array) - 1);
object n = arrayBody(t, array, index);
object p = 0;
while (n) {
if (equal(t, tripleFirst(t, n), key)) {
o = tripleFirst(t, n);
if (p) {
set(t, tripleThird(t, p), tripleThird(t, n));
} else {
set(t, arrayBody(t, array, index), tripleThird(t, n));
}
}
p = n;
n = tripleThird(t, n);
}
}
if (hashMapSize(t, map) <= arrayLength(t, array) / 3) {
hashMapResize(t, map, hash, arrayLength(t, array) / 2);
}
return o;
}
object object
hashMapIterator(Thread* t, object map) hashMapIterator(Thread* t, object map)
{ {
@ -594,6 +605,28 @@ collect(Machine* m, Heap::CollectionType type)
for (Thread* t = m->rootThread; t; t = t->next) { for (Thread* t = m->rootThread; t; t = t->next) {
::visitRoots(t, v); ::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);
}
}
for (object* f = &(m->finalizers); *f; f = &finalizerNext(t, *f)) {
v->visit(f);
}
for (object* f = &(m->doomed); *f; f = &finalizerNext(t, *f)) {
v->visit(f);
}
} }
virtual unsigned sizeInWords(object o) { virtual unsigned sizeInWords(object o) {
@ -605,55 +638,35 @@ collect(Machine* m, Heap::CollectionType type)
(t, o, baseSize(t, o, m->heap->follow(objectClass(t, o)))); (t, o, baseSize(t, o, m->heap->follow(objectClass(t, o))));
} }
virtual void copy(object o, Heap::Allocator* allocator) { virtual unsigned copiedSizeInWords(object o) {
Thread* t = m->rootThread;
o = m->heap->follow(mask(o));
unsigned n = baseSize(t, o, m->heap->follow(objectClass(t, o)));
if (objectExtended(t, o) or hashTaken(t, o)) {
++ n;
}
return n;
}
virtual void copy(object o, object dst) {
Thread* t = m->rootThread; Thread* t = m->rootThread;
o = m->heap->follow(mask(o)); o = m->heap->follow(mask(o));
unsigned base = baseSize(t, o, m->heap->follow(objectClass(t, o))); unsigned base = baseSize(t, o, m->heap->follow(objectClass(t, o)));
unsigned copyCount = base; unsigned n = extendedSize(t, o, base);
unsigned allocateCount = base;
System::Monitor* monitor = 0; memcpy(o, dst, n * BytesPerWord);
if (objectExtended(t, o)) {
copyCount += BytesPerWord;
allocateCount += BytesPerWord;
if (extendedWord(t, o, base) & MonitorFlag) {
copyCount += BytesPerWord;
allocateCount += BytesPerWord;
} else {
monitor = gcHashMapRemove
(t, m->monitorMap, o, gcObjectHash, gcObjectEqual);
if (monitor) {
allocateCount += BytesPerWord;
}
}
} else if (hashTaken(t, o)) {
allocateCount += BytesPerWord;
monitor = gcHashMapRemove
(t, m->monitorMap, o, gcObjectHash, gcObjectEqual);
if (monitor) {
allocateCount += BytesPerWord;
}
}
object dst = allocator->allocate(allocateCount);
memcpy(o, dst, copyCount * BytesPerWord);
if (hashTaken(t, o)) { if (hashTaken(t, o)) {
extendedWord(t, dst, base) = takeHash(t, o); extendedWord(t, dst, base) = takeHash(t, o);
cast<uintptr_t>(dst, 0) &= PointerMask; cast<uintptr_t>(dst, 0) &= PointerMask;
cast<uintptr_t>(dst, 0) |= ExtendedMark; cast<uintptr_t>(dst, 0) |= ExtendedMark;
} }
if (monitor) {
attachedMonitor(t, dst, base) = monitor;
}
} }
virtual void walk(void* p, Heap::Walker* w) { virtual void walk(void* p, Heap::Walker* w) {
@ -730,6 +743,13 @@ collect(Machine* m, Heap::CollectionType type)
m->unsafe = false; m->unsafe = false;
postCollect(m->rootThread); postCollect(m->rootThread);
Thread* t = m->rootThread;
for (object f = m->doomed; f; f = tripleThird(t, f)) {
reinterpret_cast<void (*)(Thread*, object)>(finalizerFinalize(t, f))
(t, finalizerTarget(t, f));
}
m->doomed = 0;
} }
void void
@ -913,39 +933,48 @@ make(Thread* t, object class_)
return instance; return instance;
} }
System::Monitor* void
mappedMonitor(Thread* t, object o) addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object))
{ {
PROTECT(t, o); PROTECT(t, target);
ACQUIRE(t, t->vm->monitorMapLock); ACQUIRE(t, t->vm->finalizerLock);
object p = makePointer(t, reinterpret_cast<void*>(finalize));
t->vm->finalizers = makeTriple(t, target, p, t->vm->finalizers);
}
void
removeMonitor(Thread* t, object o)
{
hashMapRemove(t, t->vm->monitorMap, o, objectHash, objectEqual);
}
System::Monitor*
objectMonitor(Thread* t, object o)
{
object p = hashMapFind(t, t->vm->monitorMap, o, objectHash, objectEqual); object p = hashMapFind(t, t->vm->monitorMap, o, objectHash, objectEqual);
if (p) { if (p) {
return static_cast<System::Monitor*>(pointerValue(t, p)); return static_cast<System::Monitor*>(pointerValue(t, p));
} else { } else {
PROTECT(t, o);
ENTER(t, Thread::ExclusiveState);
System::Monitor* m;
System::Status s = t->vm->system->make(&m); System::Status s = t->vm->system->make(&m);
expect(t, t->vm->system->success(s)); expect(t, t->vm->system->success(s));
object pointer = makePointer(t, m); p = makePointer(t, m);
hashMapInsert(t, t->vm->monitorMap, o, pointer, objectHash); hashMapInsert(t, t->vm->monitorMap, o, p, objectHash);
addFinalizer(t, o, removeMonitor);
return m; return m;
} }
} }
inline System::Monitor*
objectMonitor(Thread* t, object o)
{
unsigned base = baseSize(t, o);
if (monitorAttached(t, o, base)) {
return attachedMonitor(t, o, base);
} else {
return mappedMonitor(t, o);
}
}
object object
makeByteArray(Thread* t, const char* format, va_list a) makeByteArray(Thread* t, const char* format, va_list a)
{ {
@ -2167,7 +2196,10 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
ENTER(t, Thread::ExclusiveState); ENTER(t, Thread::ExclusiveState);
memcpy(bootstrapClass, class_, extendedSize(t, class_) * BytesPerWord); memcpy(bootstrapClass,
class_,
extendedSize(t, class_, baseSize(t, class_, objectClass(t, class_)))
* BytesPerWord);
object fieldTable = classFieldTable(t, class_); object fieldTable = classFieldTable(t, class_);
if (fieldTable) { if (fieldTable) {
@ -2471,7 +2503,7 @@ invokeNative(Thread* t, object method)
} }
} }
object object&
frameLocals(Thread* t, object frame, unsigned index) frameLocals(Thread* t, object frame, unsigned index)
{ {
return t->stack[frameStackBase(t, frame) + index]; return t->stack[frameStackBase(t, frame) + index];
@ -2608,13 +2640,15 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
stateLock(0), stateLock(0),
heapLock(0), heapLock(0),
classLock(0), classLock(0),
monitorMapLock(0), finalizerLock(0),
libraries(0), libraries(0),
classMap(0), classMap(0),
bootstrapClassMap(0), bootstrapClassMap(0),
builtinMap(0), builtinMap(0),
monitorMap(0), monitorMap(0),
types(0), types(0),
finalizers(0),
doomed(0),
unsafe(false) unsafe(false)
{ {
memset(&jniEnvVTable, 0, sizeof(JNIEnvVTable)); memset(&jniEnvVTable, 0, sizeof(JNIEnvVTable));
@ -2626,7 +2660,7 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
if (not system->success(system->make(&stateLock)) or if (not system->success(system->make(&stateLock)) or
not system->success(system->make(&heapLock)) or not system->success(system->make(&heapLock)) or
not system->success(system->make(&classLock)) or not system->success(system->make(&classLock)) or
not system->success(system->make(&monitorMapLock))) not system->success(system->make(&finalizerLock)))
{ {
system->abort(); system->abort();
} }
@ -2638,6 +2672,8 @@ Machine::dispose()
stateLock->dispose(); stateLock->dispose();
heapLock->dispose(); heapLock->dispose();
classLock->dispose(); classLock->dispose();
finalizerLock->dispose();
if (libraries) { if (libraries) {
libraries->dispose(); libraries->dispose();
} }