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

View File

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

View File

@ -102,24 +102,31 @@ void
hashMapInsert(Thread* t, object map, object key, object value,
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)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
object array = hashMapArray(t, map);
PROTECT(t, array);
++ hashMapSize(t, map);
if (array == 0 or hashMapSize(t, map) >= arrayLength(t, array) * 2) {
PROTECT(t, map);
PROTECT(t, key);
PROTECT(t, value);
hashMapResize(t, map, hash, array ? arrayLength(t, array) * 2 : 16);
array = hashMapArray(t, map);
}
unsigned index = hash(t, key) & (arrayLength(t, array) - 1);
object k = key;
if (weak) {
PROTECT(t, key);
@ -128,10 +135,17 @@ hashMapInsert(Thread* t, object map, object key, object value,
object r = makeWeakReference(t, 0, 0, 0, 0);
jreferenceTarget(t, r) = key;
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);
}