mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
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:
parent
f4e1473772
commit
ee60d48cfe
@ -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();
|
||||
|
@ -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) {
|
||||
|
24
src/util.cpp
24
src/util.cpp
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user