diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheFixupWalker.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheFixupWalker.java index 1d747eafa3967..88170dde7a7c9 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheFixupWalker.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheFixupWalker.java @@ -31,18 +31,19 @@ import com.oracle.svm.core.code.CodeInfoAccess; import com.oracle.svm.core.code.RuntimeCodeCache.CodeInfoVisitor; import com.oracle.svm.core.code.RuntimeCodeInfoAccess; -import com.oracle.svm.core.heap.ObjectReferenceVisitor; +import com.oracle.svm.core.code.UntetheredCodeInfoAccess; +import com.oracle.svm.core.genscavenge.compacting.ObjectMoveInfo; +import com.oracle.svm.core.genscavenge.compacting.ObjectRefFixupVisitor; -/** - * Before compaction, updates the same references that were visited by - * {@link RuntimeCodeCacheWalker} during the mark phase. - */ +import jdk.graal.compiler.word.Word; + +/** Before compaction, updates references from {@link CodeInfo} structures. */ final class RuntimeCodeCacheFixupWalker implements CodeInfoVisitor { - private final ObjectReferenceVisitor visitor; + private final ObjectRefFixupVisitor visitor; @Platforms(Platform.HOSTED_ONLY.class) - RuntimeCodeCacheFixupWalker(ObjectReferenceVisitor visitor) { + RuntimeCodeCacheFixupWalker(ObjectRefFixupVisitor visitor) { this.visitor = visitor; } @@ -54,13 +55,16 @@ public boolean visitCode(CodeInfo codeInfo) { int state = CodeInfoAccess.getState(codeInfo); if (state == CodeInfo.STATE_UNREACHABLE || state == CodeInfo.STATE_READY_FOR_INVALIDATION) { - /* - * The code will be freed during this collection, but we need to make sure that all the - * objects that are accessed during the invalidation remain accessible. Those objects - * can only be collected in a subsequent garbage collection. - */ - RuntimeCodeInfoAccess.walkObjectFields(codeInfo, visitor); - return true; + Object tether = UntetheredCodeInfoAccess.getTetherUnsafe(codeInfo); + if (tether != null && !isReachable(tether)) { + /* + * The CodeInfo's state was changed to unreachable or to-be-invalidated during the + * mark phase, so we only need to visit references that will be accessed before the + * unmanaged memory is freed. + */ + RuntimeCodeInfoAccess.walkObjectFields(codeInfo, visitor); + return true; + } } /* The CodeInfo remains valid, so we need to fix up all references. */ @@ -68,4 +72,16 @@ public boolean visitCode(CodeInfo codeInfo) { RuntimeCodeInfoAccess.walkWeakReferences(codeInfo, visitor); return true; } + + public static boolean isReachable(Object tether) { + if (HeapImpl.getHeapImpl().isInImageHeap(tether)) { + return true; + } + Space space = HeapChunk.getSpace(HeapChunk.getEnclosingHeapChunk(tether)); + if (space == null || !space.isOldSpace()) { + return false; + } + Word ptr = Word.objectToUntrackedPointer(tether); + return ObjectMoveInfo.getNewObjectAddress(ptr).isNonNull(); + } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/compacting/ObjectMoveInfo.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/compacting/ObjectMoveInfo.java index 33503e44c5588..b3e96c1d5630f 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/compacting/ObjectMoveInfo.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/compacting/ObjectMoveInfo.java @@ -181,7 +181,7 @@ public static void walkObjects(AlignedHeapChunk.AlignedHeader chunkHeader, Objec } @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true) - static Pointer getNewObjectAddress(Pointer objPointer) { + public static Pointer getNewObjectAddress(Pointer objPointer) { assert ObjectHeaderImpl.isAlignedObject(objPointer.toObject()); AlignedHeapChunk.AlignedHeader chunk = AlignedHeapChunk.getEnclosingChunkFromObjectPointer(objPointer);