From 087b0988d6ca111ace02fe5e73b3538167c12f74 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Fri, 7 Feb 2025 11:35:18 +0100 Subject: [PATCH 1/3] Use a non-static field to avoid problems if we build multiple images in a single HotSpot process. --- .../src/com/oracle/svm/core/deopt/Deoptimizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java index 2d4d16f722aa..4078d2c37b0b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java @@ -1552,7 +1552,7 @@ static class TargetContent { /** * The offset of the within the array object. I do not have to scale the offsets. */ - private static final int arrayBaseOffset = ConfigurationValues.getObjectLayout().getArrayBaseOffset(JavaKind.Byte); + private final int arrayBaseOffset = ConfigurationValues.getObjectLayout().getArrayBaseOffset(JavaKind.Byte); private static final ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException("TargetContent.offsetCheck"); From 993769713bb9f15aa8c70a245097c393c1faaaf5 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Fri, 7 Feb 2025 11:36:42 +0100 Subject: [PATCH 2/3] Updated the documentation for hybrid objects. --- .../src/com/oracle/svm/core/deopt/Deoptimizer.java | 3 --- .../src/com/oracle/svm/core/heap/Pod.java | 10 +++++++++- .../com/oracle/svm/core/heap/StoredContinuation.java | 4 ++++ .../src/com/oracle/svm/core/hub/Hybrid.java | 7 ++++++- .../com/oracle/svm/hosted/config/DynamicHubLayout.java | 5 ++--- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java index 4078d2c37b0b..4e991ff355c1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java @@ -1549,9 +1549,6 @@ static class TargetContent { /** All references in deopt frames are compressed when compressed references are enabled. */ private final int sizeofCompressedReference = ConfigurationValues.getObjectLayout().getReferenceSize(); private final int sizeofUncompressedReference = FrameAccess.uncompressedReferenceSize(); - /** - * The offset of the within the array object. I do not have to scale the offsets. - */ private final int arrayBaseOffset = ConfigurationValues.getObjectLayout().getArrayBaseOffset(JavaKind.Byte); private static final ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException("TargetContent.offsetCheck"); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Pod.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Pod.java index 970e26ff7180..155f91ce4d18 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Pod.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Pod.java @@ -38,7 +38,6 @@ import java.util.function.Supplier; import org.graalvm.collections.EconomicMap; -import jdk.graal.compiler.api.replacements.Fold; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -46,10 +45,13 @@ import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.hub.Hybrid; import com.oracle.svm.core.hub.LayoutEncoding; import com.oracle.svm.core.util.ImageHeapMap; import com.oracle.svm.core.util.UnsignedUtils; +import jdk.graal.compiler.api.replacements.Fold; +import jdk.graal.compiler.word.BarrieredAccess; import jdk.vm.ci.meta.JavaKind; /** @@ -58,6 +60,12 @@ * storing "plain old data" without further object-oriented features such as method dispatching or * type information, apart from having a Java superclass. * + * Pods are {@link Hybrid} objects. All fields that are not inherited from an actual Java class are + * layouted in the array part of the hybrid object. For object fields, the GC will use the provided + * {@link #referenceMap} to keep all the object references up-to-date. However, be aware that it is + * necessary to manually emit the correct GC read/write barriers (for example via + * {@link BarrieredAccess}) whenever such an object field is accessed. + * * @param The interface of the {@linkplain #getFactory() factory} that allocates instances. */ public final class Pod { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuation.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuation.java index bb4b36a7ecda..e908489ed287 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuation.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuation.java @@ -32,6 +32,10 @@ /** * Persisted execution state of a yielded continuation, use via {@link StoredContinuationAccess}. + * + * Stored continuations are {@link Hybrid} objects where the array part contains the raw stack data. + * After writing the stack data into the object, we manually emit the correct GC write barriers for + * all the references (see {@link Heap#dirtyAllReferencesOf}). */ @Hybrid(componentType = Word.class) public final class StoredContinuation { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/Hybrid.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/Hybrid.java index 663b91862acd..9dcc3936657b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/Hybrid.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/Hybrid.java @@ -40,7 +40,7 @@ * *

* The location of the identity hashcode is configuration-dependent and will follow the same - * placement convention as an array. The See {@link ObjectLayout} for more information on where the + * placement convention as an array. See {@link ObjectLayout} for more information on where the * identity hash can be placed. @Hybrid objects are treated the same way as instance classes for * determining whether (and where) they have a monitor slot; See {@link MultiThreadedMonitorSupport} * for more information on monitor slot placement. @@ -65,6 +65,11 @@ * return {@code true} and {@link Class#isArray()} will return {@code false}, while * {@link LayoutEncoding#isPureInstance} will return {@code false} and * {@link LayoutEncoding#isArrayLike} will return {@code true} for hybrid objects. + * + *

+ * Note that the array part of a hybrid object may only contain primitive data but no object + * references because the GC treats hybrid objects similar to normal instance objects. So, it would + * not be aware of any object references in the array part. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/DynamicHubLayout.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/DynamicHubLayout.java index dcff6ccdc621..3c29d05946fb 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/DynamicHubLayout.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/DynamicHubLayout.java @@ -74,9 +74,8 @@ * * *

- * Like {@link Hybrid}, DynamicHub objects have an instance {@link HubType}, but a - * {@link LayoutEncoding} like an array. See the javadoc for {@link Hybrid} more details its - * implications. + * Like {@link Hybrid} objects, DynamicHubs have an instance {@link HubType}, but a + * {@link LayoutEncoding} like an array (see the javadoc for {@link Hybrid}). */ public class DynamicHubLayout { From 6f2b7ade4e5ed923c81de1e42041f8c8927a3664 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Fri, 7 Feb 2025 11:37:26 +0100 Subject: [PATCH 3/3] Reenable all checks regarding @Uninterruptible. --- .../svm/hosted/code/UninterruptibleAnnotationChecker.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java index 10f4621de57e..f5ccebf38230 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java @@ -184,9 +184,7 @@ private void checkOverrides(HostedMethod method, Uninterruptible methodAnnotatio Uninterruptible implAnnotation = Uninterruptible.Utils.getAnnotation(impl); if (implAnnotation != null) { if (methodAnnotation.callerMustBe() != implAnnotation.callerMustBe()) { - // GR-45784: temporarily disabled so that we can remove legacy code - // violations.add("callerMustBe: " + method.format("%H.%n(%p):%r") + " != " + - // impl.format("%H.%n(%p):%r")); + violations.add("callerMustBe: " + method.format("%H.%n(%p):%r") + " != " + impl.format("%H.%n(%p):%r")); } if (methodAnnotation.calleeMustBe() != implAnnotation.calleeMustBe()) { violations.add("calleeMustBe: " + method.format("%H.%n(%p):%r") + " != " + impl.format("%H.%n(%p):%r"));