Skip to content

[GR-64554] Introduce DuplicableImageSingletons. #11120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,22 @@
*/
package com.oracle.svm.core.genscavenge;

import java.util.EnumSet;

import org.graalvm.nativeimage.PinnedObject;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.Pointer;

import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.heap.AbstractPinnedObjectSupport;
import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;

import jdk.graal.compiler.nodes.NamedLocationIdentity;

/** Support for pinning objects to a memory address with {@link PinnedObject}. */
public final class PinnedObjectSupportImpl extends AbstractPinnedObjectSupport {
public final class PinnedObjectSupportImpl extends AbstractPinnedObjectSupport implements InitialLayerOnlyImageSingleton {
@Platforms(Platform.HOSTED_ONLY.class)
public PinnedObjectSupportImpl() {
}
Expand All @@ -62,4 +66,14 @@ private static void modifyPinnedObjectCount(Object object, int delta) {

assert oldValue < Integer.MAX_VALUE;
}

@Override
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
return LayeredImageSingletonBuilderFlags.ALL_ACCESS;
}

@Override
public boolean accessibleInFutureLayers() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import java.util.List;
import java.util.Map;

import com.oracle.svm.core.jdk.SystemPropertiesSupport;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.impl.PinnedObjectSupport;
Expand Down Expand Up @@ -60,7 +59,9 @@
import com.oracle.svm.core.heap.BarrierSetProvider;
import com.oracle.svm.core.heap.Heap;
import com.oracle.svm.core.image.ImageHeapLayouter;
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
import com.oracle.svm.core.jdk.RuntimeSupportFeature;
import com.oracle.svm.core.jdk.SystemPropertiesSupport;
import com.oracle.svm.core.jvmstat.PerfDataFeature;
import com.oracle.svm.core.jvmstat.PerfDataHolder;
import com.oracle.svm.core.jvmstat.PerfManager;
Expand Down Expand Up @@ -100,7 +101,9 @@ public void duringSetup(DuringSetupAccess access) {
ImageSingletons.add(Heap.class, new HeapImpl());
ImageSingletons.add(ImageHeapInfo.class, new ImageHeapInfo());
ImageSingletons.add(GCAllocationSupport.class, new GenScavengeAllocationSupport());
ImageSingletons.add(PinnedObjectSupport.class, new PinnedObjectSupportImpl());
if (ImageLayerBuildingSupport.firstImageBuild()) {
ImageSingletons.add(PinnedObjectSupport.class, new PinnedObjectSupportImpl());
}

if (ImageSingletons.contains(PerfManager.class)) {
ImageSingletons.lookup(PerfManager.class).register(createPerfData());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,33 @@
package com.oracle.svm.core.posix;

import java.io.FileDescriptor;
import java.util.EnumSet;

import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
import org.graalvm.nativeimage.LogHandler;
import org.graalvm.nativeimage.c.type.CCharPointer;
import org.graalvm.word.UnsignedWord;

import com.oracle.svm.core.SubstrateDiagnostics;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.headers.LibC;
import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.thread.VMThreads;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;

@AutomaticallyRegisteredFeature
class PosixLogHandlerFeature implements InternalFeature {
@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
Log.finalizeDefaultLogHandler(new PosixLogHandler());
if (ImageLayerBuildingSupport.firstImageBuild()) {
Log.finalizeDefaultLogHandler(new PosixLogHandler());
}
}
}

public class PosixLogHandler implements LogHandler {
public class PosixLogHandler implements LogHandler, InitialLayerOnlyImageSingleton {

@Override
public void log(CCharPointer bytes, UnsignedWord length) {
Expand Down Expand Up @@ -88,4 +94,14 @@ public void fatalError() {
private static FileDescriptor getOutputFile() {
return FileDescriptor.err;
}

@Override
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY;
}

@Override
public boolean accessibleInFutureLayers() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import java.util.ArrayList;
import java.util.List;

import jdk.graal.compiler.word.Word;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.word.UnsignedWord;

Expand All @@ -40,9 +39,12 @@
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.heap.PhysicalMemory;
import com.oracle.svm.core.heap.PhysicalMemory.PhysicalMemorySupport;
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
import com.oracle.svm.core.posix.headers.Unistd;
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.word.Word;

public class LinuxPhysicalMemorySupportImpl implements PhysicalMemorySupport {

private static final long K = 1024;
Expand Down Expand Up @@ -121,7 +123,7 @@ private static long parseFirstNumber(String str) {
class LinuxPhysicalMemorySupportFeature implements InternalFeature {
@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
if (!ImageSingletons.contains(PhysicalMemorySupport.class)) {
if (ImageLayerBuildingSupport.firstImageBuild() && !ImageSingletons.contains(PhysicalMemorySupport.class)) {
ImageSingletons.add(PhysicalMemorySupport.class, new LinuxPhysicalMemorySupportImpl());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,31 @@
*/
package com.oracle.svm.core.posix.linux;

import java.util.EnumSet;

import org.graalvm.nativeimage.impl.ProcessPropertiesSupport;

import com.oracle.svm.core.posix.PosixProcessPropertiesSupport;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
import com.oracle.svm.core.posix.PosixProcessPropertiesSupport;

@AutomaticallyRegisteredImageSingleton(ProcessPropertiesSupport.class)
public class LinuxProcessPropertiesSupport extends PosixProcessPropertiesSupport {
public class LinuxProcessPropertiesSupport extends PosixProcessPropertiesSupport implements InitialLayerOnlyImageSingleton {

@Override
public String getExecutableName() {
final String exefileString = "/proc/self/exe";
return realpath(exefileString);
}

@Override
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY;
}

@Override
public boolean accessibleInFutureLayers() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.EnumSet;

import jdk.graal.compiler.word.Word;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.c.type.CCharPointer;
import org.graalvm.nativeimage.c.type.CCharPointerPointer;
Expand All @@ -45,9 +45,13 @@
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.handles.PrimitiveArrayView;
import com.oracle.svm.core.jdk.DirectByteBufferUtil;
import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;

import jdk.graal.compiler.word.Word;

@AutomaticallyRegisteredImageSingleton(CTypeConversionSupport.class)
class CTypeConversionSupportImpl implements CTypeConversionSupport {
class CTypeConversionSupportImpl implements CTypeConversionSupport, InitialLayerOnlyImageSingleton {

static final CCharPointerHolder NULL_HOLDER = new CCharPointerHolder() {
@Override
Expand Down Expand Up @@ -189,6 +193,16 @@ public ByteBuffer asByteBuffer(PointerBase address, int size) {
ByteBuffer byteBuffer = DirectByteBufferUtil.allocate(address.rawValue(), size);
return byteBuffer.order(ConfigurationValues.getTarget().arch.getByteOrder());
}

@Override
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY;
}

@Override
public boolean accessibleInFutureLayers() {
return true;
}
}

final class CCharPointerHolderImpl implements CCharPointerHolder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
*/
package com.oracle.svm.core.c.function;

import java.util.EnumSet;
import java.util.List;

import jdk.graal.compiler.word.Word;
import org.graalvm.nativeimage.Isolate;
import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.Isolates.CreateIsolateParameters;
Expand All @@ -41,14 +41,18 @@
import com.oracle.svm.core.c.function.CEntryPointNativeFunctions.IsolateThreadPointer;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
import com.oracle.svm.core.memory.NativeMemory;
import com.oracle.svm.core.nmt.NmtCategory;
import com.oracle.svm.core.option.SubstrateOptionsParser;
import com.oracle.svm.core.os.MemoryProtectionProvider;
import com.oracle.svm.core.os.MemoryProtectionProvider.UnsupportedDomainException;

import jdk.graal.compiler.word.Word;

@AutomaticallyRegisteredImageSingleton(IsolateSupport.class)
public final class IsolateSupportImpl implements IsolateSupport {
public final class IsolateSupportImpl implements IsolateSupport, InitialLayerOnlyImageSingleton {
private static final String ISOLATES_DISABLED_MESSAGE = "Spawning of multiple isolates is disabled, use " +
SubstrateOptionsParser.commandArgument(SubstrateOptions.SpawnIsolates, "+") + " option.";
private static final String PROTECTION_DOMAIN_UNSUPPORTED_MESSAGE = "Protection domains are unavailable";
Expand Down Expand Up @@ -167,4 +171,14 @@ private static void throwOnError(int code) {
throw new IsolateException(message);
}
}

@Override
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY;
}

@Override
public boolean accessibleInFutureLayers() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@
*/
package com.oracle.svm.core.handles;

import java.util.EnumSet;

import org.graalvm.nativeimage.ObjectHandles;
import org.graalvm.nativeimage.impl.ObjectHandlesSupport;

import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;

@AutomaticallyRegisteredImageSingleton(ObjectHandlesSupport.class)
class ObjectHandlesSupportImpl implements ObjectHandlesSupport {
class ObjectHandlesSupportImpl implements ObjectHandlesSupport, InitialLayerOnlyImageSingleton {
final ObjectHandlesImpl globalHandles = new ObjectHandlesImpl();

@Override
Expand All @@ -42,4 +46,19 @@ public ObjectHandles getGlobalHandles() {
public ObjectHandles createHandles() {
return new ObjectHandlesImpl();
}

@Override
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
/*
* In some cases object instances are accessed during code initialized at buildtime.
* However, when this is done, one must be very careful to ensure analysis sees all changes
* made to these objects.
*/
return LayeredImageSingletonBuilderFlags.ALL_ACCESS;
}

@Override
public boolean accessibleInFutureLayers() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
package com.oracle.svm.core.heap;

import java.lang.management.ManagementFactory;
import java.util.EnumSet;

import jdk.graal.compiler.word.Word;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.word.UnsignedWord;
Expand All @@ -36,18 +36,21 @@
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.container.Container;
import com.oracle.svm.core.container.OperatingSystem;
import com.oracle.svm.core.layeredimagesingleton.RuntimeOnlyImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
import com.oracle.svm.core.util.UnsignedUtils;
import com.oracle.svm.core.util.VMError;
import com.sun.management.OperatingSystemMXBean;

import jdk.graal.compiler.word.Word;

/**
* Contains static methods to get configuration of physical memory.
*/
public class PhysicalMemory {

/** Implemented by operating-system specific code. */
public interface PhysicalMemorySupport extends RuntimeOnlyImageSingleton {
public interface PhysicalMemorySupport extends InitialLayerOnlyImageSingleton {
/** Get the size of physical memory from the OS. */
UnsignedWord size();

Expand All @@ -62,6 +65,11 @@ public interface PhysicalMemorySupport extends RuntimeOnlyImageSingleton {
default long usedSize() {
return -1L;
}

@Override
default EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY;
}
}

private static final UnsignedWord UNSET_SENTINEL = UnsignedUtils.MAX_VALUE;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -24,17 +24,19 @@
*/
package com.oracle.svm.core.layeredimagesingleton;

import java.util.EnumSet;

public interface RuntimeOnlyImageSingleton extends LayeredImageSingleton {

@Override
default EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY;
}

@Override
default PersistFlags preparePersist(ImageSingletonWriter writer) {
return PersistFlags.NOTHING;
}
/**
* A Duplicable ImageSingleton can have multiple instances of the object installed in the Image Heap
* (at most one per a layer). The specific instance referred to from a given piece of code is
* dependent on the layer in which the code was installed in.
*
* It is expected that either the installed objects (1) have no instance fields or (2) have instance
* fields which have been made layer-aware through other means (e.g. using a layered ImageHeapMap).
*
* Note this is a temporary marker and eventually all instances of {@link DuplicableImageSingleton}s
* should be removed. This marker should only be used when there is not a correctness issue with
* installing multiple instances of the singleton. Instead, the marker indicates there is merely a
* performance/memory overhead due to having multiple copies of this singleton installed (via
* different layers) within the image heap.
*/
public interface DuplicableImageSingleton extends LayeredImageSingleton {
}
Loading