C: fix crash on GC when there are queued WeakReference instances in the heap

When performing young GC, we can encounter some WeakReferences which get into
corresponding ReferenceQueue. In this case queue internal state will be updated.
After it defragmentation phase runs which updates references to relocated objects.
For performance reason, defragmentation phase scans only regions either
marked with write barriers or regions that contain surviving objects in
young generation. However, sometimes a queue can be in neither of these sets,
so we additionally mark regions containing all affected queues.
This commit is contained in:
Alexey Andreev 2020-01-31 18:23:50 +03:00
parent 374f7c6634
commit 45d36eac83
2 changed files with 20 additions and 5 deletions

View File

@ -438,7 +438,9 @@ public final class GC {
hasObjectsFromYoungGen |= enqueueMark(object.object);
}
}
if (object.next == null && object.object != null) {
if (object.next != null) {
hasObjectsFromYoungGen |= enqueueMark(object.next);
} else if (object.object != null) {
object.next = firstWeakReference;
firstWeakReference = object;
}
@ -448,9 +450,8 @@ public final class GC {
private static boolean markReferenceQueue(RuntimeReferenceQueue object) {
RuntimeReference reference = object.first;
boolean hasObjectsFromYoungGen = false;
while (reference != null) {
if (reference != null) {
hasObjectsFromYoungGen |= enqueueMark(reference);
reference = reference.next;
}
return hasObjectsFromYoungGen;
}
@ -519,14 +520,22 @@ public final class GC {
queue.first = reference;
} else {
queue.last.next = reference;
makeInvalid(queue.last);
}
queue.last = reference;
makeInvalid(queue);
}
}
reference = next;
}
}
private static void makeInvalid(RuntimeObject object) {
long offset = object.toAddress().toLong() - heapAddress().toLong();
Address cardTableItem = cardTable().add(offset / regionSize());
cardTableItem.putByte((byte) (cardTableItem.getByte() & ~CARD_VALID));
}
private static void sweep() {
MemoryTrace.sweepStarted();

View File

@ -4,6 +4,7 @@
#include "definitions.h"
#include "memory.h"
#include "time.h"
#include "references.h"
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
@ -363,9 +364,14 @@ FILE* teavm_gc_openDumpFile(wchar_t* name) {
while (cls != NULL) {
int32_t kind = (cls->flags >> 7) & 7;
if (kind == 1) {
TeaVM_Reference* reference = (TeaVM_Reference*) obj;
teavm_verify(reference->next);
teavm_verify(reference->object);
teavm_verify(reference->queue);
} else if (kind == 2) {
TeaVM_ReferenceQueue* queue = (TeaVM_ReferenceQueue*) obj;
teavm_verify(queue->first);
teavm_verify(queue->last);
} else {
int16_t* layout = cls->layout;
if (layout != NULL) {