mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 07:54:11 -08:00
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:
parent
374f7c6634
commit
45d36eac83
|
@ -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();
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user