mirror of
https://github.com/corda/corda.git
synced 2025-01-05 20: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
|
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();
|
||||||
|
@ -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) {
|
||||||
|
24
src/util.cpp
24
src/util.cpp
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user