fix subtle bug in hashMapInsert which caused us to update the old array previously associated with the hash map, whereas a GC causes the table to be resized when a weak reference is removed and thus a new array used

This commit is contained in:
Joel Dice 2008-01-19 13:12:16 -07:00
parent f4e1473772
commit ee60d48cfe
3 changed files with 50 additions and 11 deletions

View File

@ -1571,6 +1571,11 @@ makeArrayClass(Thread* t, object spec)
void void
removeMonitor(Thread* t, object o) removeMonitor(Thread* t, object o)
{ {
unsigned hash;
if (DebugMonitors) {
hash = objectHash(t, o);
}
object p = hashMapRemove(t, t->m->monitorMap, o, objectHash, objectEqual); object p = hashMapRemove(t, t->m->monitorMap, o, objectHash, objectEqual);
assert(t, p); assert(t, p);
@ -1578,7 +1583,7 @@ removeMonitor(Thread* t, object o)
if (DebugMonitors) { if (DebugMonitors) {
fprintf(stderr, "dispose monitor %p for object %x\n", fprintf(stderr, "dispose monitor %p for object %x\n",
static_cast<System::Monitor*>(pointerValue(t, p)), static_cast<System::Monitor*>(pointerValue(t, p)),
objectHash(t, o)); hash);
} }
static_cast<System::Monitor*>(pointerValue(t, p))->dispose(); static_cast<System::Monitor*>(pointerValue(t, p))->dispose();

View File

@ -2015,11 +2015,16 @@ objectMonitor(Thread* t, object o, bool createNew);
inline void inline void
acquire(Thread* t, object o) acquire(Thread* t, object o)
{ {
unsigned hash;
if (DebugMonitors) {
hash = objectHash(t, o);
}
System::Monitor* m = objectMonitor(t, o, true); System::Monitor* m = objectMonitor(t, o, true);
if (DebugMonitors) { if (DebugMonitors) {
fprintf(stderr, "thread %p acquires %p for %x\n", fprintf(stderr, "thread %p acquires %p for %x\n",
t, m, objectHash(t, o)); t, m, hash);
} }
acquire(t, m); acquire(t, m);
@ -2028,11 +2033,16 @@ acquire(Thread* t, object o)
inline void inline void
release(Thread* t, object o) release(Thread* t, object o)
{ {
unsigned hash;
if (DebugMonitors) {
hash = objectHash(t, o);
}
System::Monitor* m = objectMonitor(t, o, false); System::Monitor* m = objectMonitor(t, o, false);
if (DebugMonitors) { if (DebugMonitors) {
fprintf(stderr, "thread %p releases %p for %x\n", fprintf(stderr, "thread %p releases %p for %x\n",
t, m, objectHash(t, o)); t, m, hash);
} }
release(t, m); release(t, m);
@ -2041,11 +2051,16 @@ release(Thread* t, object o)
inline void inline void
wait(Thread* t, object o, int64_t milliseconds) wait(Thread* t, object o, int64_t milliseconds)
{ {
unsigned hash;
if (DebugMonitors) {
hash = objectHash(t, o);
}
System::Monitor* m = objectMonitor(t, o, false); System::Monitor* m = objectMonitor(t, o, false);
if (DebugMonitors) { if (DebugMonitors) {
fprintf(stderr, "thread %p waits %"LLD" millis on %p for %x\n", fprintf(stderr, "thread %p waits %"LLD" millis on %p for %x\n",
t, milliseconds, m, objectHash(t, o)); t, milliseconds, m, hash);
} }
if (m and m->owner() == t->systemThread) { if (m and m->owner() == t->systemThread) {
@ -2063,7 +2078,7 @@ wait(Thread* t, object o, int64_t milliseconds)
if (DebugMonitors) { if (DebugMonitors) {
fprintf(stderr, "thread %p wakes up on %p for %x\n", fprintf(stderr, "thread %p wakes up on %p for %x\n",
t, m, objectHash(t, o)); t, m, hash);
} }
stress(t); stress(t);
@ -2072,11 +2087,16 @@ wait(Thread* t, object o, int64_t milliseconds)
inline void inline void
notify(Thread* t, object o) notify(Thread* t, object o)
{ {
unsigned hash;
if (DebugMonitors) {
hash = objectHash(t, o);
}
System::Monitor* m = objectMonitor(t, o, false); System::Monitor* m = objectMonitor(t, o, false);
if (DebugMonitors) { if (DebugMonitors) {
fprintf(stderr, "thread %p notifies on %p for %x\n", fprintf(stderr, "thread %p notifies on %p for %x\n",
t, m, objectHash(t, o)); t, m, hash);
} }
if (m and m->owner() == t->systemThread) { if (m and m->owner() == t->systemThread) {

View File

@ -102,24 +102,31 @@ void
hashMapInsert(Thread* t, object map, object key, object value, hashMapInsert(Thread* t, object map, object key, object value,
uint32_t (*hash)(Thread*, object)) uint32_t (*hash)(Thread*, object))
{ {
// note that we reinitialize the array and index variables whenever
// an allocation (and thus possibly a collection) occurs, in case
// the array changes due to a table resize.
PROTECT(t, map);
uint32_t h = hash(t, key);
bool weak = objectClass(t, map) bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType); == arrayBody(t, t->m->types, Machine::WeakHashMapType);
object array = hashMapArray(t, map); object array = hashMapArray(t, map);
PROTECT(t, array);
++ hashMapSize(t, map); ++ hashMapSize(t, map);
if (array == 0 or hashMapSize(t, map) >= arrayLength(t, array) * 2) { if (array == 0 or hashMapSize(t, map) >= arrayLength(t, array) * 2) {
PROTECT(t, map);
PROTECT(t, key); PROTECT(t, key);
PROTECT(t, value); PROTECT(t, value);
hashMapResize(t, map, hash, array ? arrayLength(t, array) * 2 : 16); hashMapResize(t, map, hash, array ? arrayLength(t, array) * 2 : 16);
array = hashMapArray(t, map); array = hashMapArray(t, map);
} }
unsigned index = hash(t, key) & (arrayLength(t, array) - 1); object k = key;
if (weak) { if (weak) {
PROTECT(t, key); PROTECT(t, key);
@ -128,10 +135,17 @@ hashMapInsert(Thread* t, object map, object key, object value,
object r = makeWeakReference(t, 0, 0, 0, 0); object r = makeWeakReference(t, 0, 0, 0, 0);
jreferenceTarget(t, r) = key; jreferenceTarget(t, r) = key;
jreferenceVmNext(t, r) = t->m->weakReferences; jreferenceVmNext(t, r) = t->m->weakReferences;
key = t->m->weakReferences = r; k = t->m->weakReferences = r;
array = hashMapArray(t, map);
} }
object n = makeTriple(t, key, value, arrayBody(t, array, index)); unsigned index = h & (arrayLength(t, array) - 1);
object n = makeTriple(t, k, value, arrayBody(t, array, index));
array = hashMapArray(t, map);
index = h & (arrayLength(t, array) - 1);
set(t, array, ArrayBody + (index * BytesPerWord), n); set(t, array, ArrayBody + (index * BytesPerWord), n);
} }