Skip to content

Commit

Permalink
Adapt JDK-8343704: Bad GC parallelism with processing Cleaner queues
Browse files Browse the repository at this point in the history
  • Loading branch information
mur47x111 committed Dec 3, 2024
1 parent 778210b commit 5447046
Showing 1 changed file with 92 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import java.lang.ref.Cleaner;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Array;

import org.graalvm.nativeimage.hosted.FieldValueTransformer;

Expand All @@ -35,8 +36,13 @@
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.annotate.TargetElement;
import com.oracle.svm.core.jdk.JDK21OrEarlier;
import com.oracle.svm.core.jdk.JDKLatest;
import com.oracle.svm.core.thread.VMThreads;
import com.oracle.svm.util.ReflectionUtil;

import jdk.graal.compiler.serviceprovider.JavaVersionUtil;
import jdk.internal.misc.InnocuousThread;

@TargetClass(className = "jdk.internal.ref.Cleaner")
Expand Down Expand Up @@ -74,8 +80,13 @@ final class Target_java_lang_ref_Cleaner_Cleanable {
@TargetClass(className = "jdk.internal.ref.CleanerImpl")
final class Target_jdk_internal_ref_CleanerImpl {

@TargetElement(onlyWith = JDK21OrEarlier.class)//
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "jdk.internal.ref.CleanerImpl$PhantomCleanableRef")//
Target_jdk_internal_ref_PhantomCleanable phantomCleanableList;
Target_jdk_internal_ref_PhantomCleanable_JDK21 phantomCleanableList;

@TargetElement(onlyWith = JDKLatest.class)//
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "jdk.internal.ref.CleanerImpl$CleanableList")//
Target_jdk_internal_ref_CleanerImpl_CleanableList activeList;

@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "java.lang.ref.ReferenceQueue")//
public ReferenceQueue<Object> queue;
Expand All @@ -85,8 +96,9 @@ final class Target_jdk_internal_ref_CleanerImpl {
* the {@code Cleaner} itself), ignoring {@link InterruptedException}. This blocks VM tear-down,
* so we add a check if the VM is tearing down here.
*/
@TargetElement(name = "run", onlyWith = JDK21OrEarlier.class)
@Substitute
public void run() {
public void runJDK21() {
Thread t = Thread.currentThread();
InnocuousThread mlThread = (t instanceof InnocuousThread) ? (InnocuousThread) t : null;
while (!phantomCleanableList.isListEmpty()) {
Expand All @@ -105,20 +117,42 @@ public void run() {
}
}
}

@TargetElement(name = "run", onlyWith = JDKLatest.class)
@Substitute
public void run() {
Thread t = Thread.currentThread();
InnocuousThread mlThread = (t instanceof InnocuousThread) ? (InnocuousThread) t : null;
while (!activeList.isEmpty()) {
if (mlThread != null) {
mlThread.eraseThreadLocals();
}
try {
Cleaner.Cleanable ref = (Cleaner.Cleanable) queue.remove(60 * 1000L);
if (ref != null) {
ref.clean();
}
} catch (Throwable e) {
if (VMThreads.isTearingDown()) {
return;
}
}
}
}
}

@TargetClass(className = "jdk.internal.ref.PhantomCleanable")
final class Target_jdk_internal_ref_PhantomCleanable {
@TargetClass(className = "jdk.internal.ref.PhantomCleanable", onlyWith = JDK21OrEarlier.class)
final class Target_jdk_internal_ref_PhantomCleanable_JDK21 {
/*
* Unlink from the list for the image heap so that we cannot reach Cleanables irrelevant for the
* image heap which could fail the image build; we reset the list head anyway.
*/
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = HolderObjectFieldTransformer.class) //
Target_jdk_internal_ref_PhantomCleanable prev;
Target_jdk_internal_ref_PhantomCleanable_JDK21 prev;
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = HolderObjectFieldTransformer.class) //
Target_jdk_internal_ref_PhantomCleanable next;
Target_jdk_internal_ref_PhantomCleanable_JDK21 next;
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = HolderObjectFieldTransformer.class) //
Target_jdk_internal_ref_PhantomCleanable list;
Target_jdk_internal_ref_PhantomCleanable_JDK21 list;

@Alias
native boolean isListEmpty();
Expand All @@ -128,9 +162,60 @@ final class Target_jdk_internal_ref_PhantomCleanable {
/* final */ native void clean();
}

@TargetClass(className = "jdk.internal.ref.PhantomCleanable", onlyWith = JDKLatest.class)
final class Target_jdk_internal_ref_PhantomCleanable {
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = GetCleanableListSingletonTransformer.class) //
Target_jdk_internal_ref_CleanerImpl_CleanableList list;
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) //
Target_jdk_internal_ref_CleanerImpl_CleanableList_Node node;
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = ResetToMinusOneTransformer.class) //
int index;

@AnnotateOriginal
@NeverInline("Ensure that every exception can be caught, including implicit exceptions.")
/* final */ native void clean();
}

@TargetClass(className = "jdk.internal.ref.CleanerImpl$CleanableList", onlyWith = JDKLatest.class)
final class Target_jdk_internal_ref_CleanerImpl_CleanableList {

@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "jdk.internal.ref.CleanerImpl$CleanableList$Node") //
Target_jdk_internal_ref_CleanerImpl_CleanableList_Node head;

@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) //
Target_jdk_internal_ref_CleanerImpl_CleanableList_Node cache;

@Alias
native boolean isEmpty();

}

@TargetClass(className = "jdk.internal.ref.CleanerImpl$CleanableList$Node", onlyWith = JDKLatest.class)
final class Target_jdk_internal_ref_CleanerImpl_CleanableList_Node {
}

final class HolderObjectFieldTransformer implements FieldValueTransformer {
@Override
public Object transform(Object receiver, Object originalValue) {
return receiver;
}
}

final class Target_jdk_internal_ref_CleanerImpl_CleanableList_Singleton {
static final Object list = ReflectionUtil.newInstance(ReflectionUtil.lookupClass("jdk.internal.ref.CleanerImpl$CleanableList"));
}

final class GetCleanableListSingletonTransformer implements FieldValueTransformer {
@Override
public Object transform(Object receiver, Object originalValue) {
return Target_jdk_internal_ref_CleanerImpl_CleanableList_Singleton.list;
}
}

final class ResetToMinusOneTransformer implements FieldValueTransformer {
@Override
public Object transform(Object receiver, Object originalValue) {
return -1;
}
}

0 comments on commit 5447046

Please sign in to comment.