Skip to content

[GR-66791] Introduce SingletonTraits annotation. #11722

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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 @@ -30,7 +30,6 @@
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.hosted.Feature;

import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.meta.AnalysisMethod;
Expand All @@ -52,9 +51,11 @@
import com.oracle.svm.core.graal.llvm.util.LLVMOptions;
import com.oracle.svm.core.graal.meta.RuntimeConfiguration;
import com.oracle.svm.core.graal.snippets.NodeLoweringProvider;
import com.oracle.svm.core.layeredimagesingleton.UnsupportedLayeredSingleton;
import com.oracle.svm.core.option.HostedOptionKey;
import com.oracle.svm.core.snippets.ExceptionUnwind;
import com.oracle.svm.core.traits.BuiltinTraits;
import com.oracle.svm.core.traits.SingletonLayeredInstallationKind;
import com.oracle.svm.core.traits.SingletonTraits;
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.hosted.FeatureImpl;
import com.oracle.svm.hosted.c.codegen.CCompilerInvoker;
Expand All @@ -81,7 +82,8 @@
*/
@AutomaticallyRegisteredFeature
@Platforms({Platform.LINUX.class, Platform.DARWIN.class})
public class LLVMFeature implements Feature, InternalFeature, UnsupportedLayeredSingleton {
@SingletonTraits(access = BuiltinTraits.BuildtimeAccessOnly.class, layeredCallbacks = BuiltinTraits.NoLayeredCallbacks.class, layeredInstallationKind = SingletonLayeredInstallationKind.Disallowed.class)
public class LLVMFeature implements InternalFeature {

@Override
public boolean isInConfiguration(IsInConfigurationAccess access) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,7 @@ public enum LayeredImageSingletonBuilderFlags {
/**
* This singleton can be accessed from the buildtime.
*/
BUILDTIME_ACCESS,
/**
* This singleton should not have been created. Throw error if it is created.
*/
UNSUPPORTED;
BUILDTIME_ACCESS;

/*
* Below are some common flag patterns.
Expand All @@ -57,15 +53,9 @@ public enum LayeredImageSingletonBuilderFlags {

public static final EnumSet<LayeredImageSingletonBuilderFlags> ALL_ACCESS = EnumSet.of(RUNTIME_ACCESS, BUILDTIME_ACCESS);

public static boolean verifyImageBuilderFlags(LayeredImageSingleton singleton) {
EnumSet<LayeredImageSingletonBuilderFlags> flags = singleton.getImageBuilderFlags();

if (!(flags.contains(UNSUPPORTED) || flags.contains(BUILDTIME_ACCESS) || flags.contains(RUNTIME_ACCESS))) {
assert false : String.format("At least one of the following flags must be set: %s, %s, %s", UNSUPPORTED, BUILDTIME_ACCESS, RUNTIME_ACCESS);
}

if (flags.contains(UNSUPPORTED)) {
assert flags.equals(EnumSet.of(UNSUPPORTED)) : "Unsupported should be the only flag set " + flags;
public static boolean verifyImageBuilderFlags(Object singleton, EnumSet<LayeredImageSingletonBuilderFlags> flags) {
if (!(flags.contains(BUILDTIME_ACCESS) || flags.contains(RUNTIME_ACCESS))) {
assert false : String.format("At least one of the following flags must be set: %s, %s", BUILDTIME_ACCESS, RUNTIME_ACCESS);
}

if (singleton instanceof MultiLayeredImageSingleton || ApplicationLayerOnlyImageSingleton.isSingletonInstanceOf(singleton)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.traits;

import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;

/**
* Commonly used {@link SingletonTrait}s.
*/
public class BuiltinTraits {

/**
* Trait indicating this singleton should only be accessed from code executed at runtime.
*/
public static final SingletonTrait RUNTIME_ONLY = new SingletonTrait(SingletonTraitKind.ACCESS,
(SingletonAccess.Supplier) () -> LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY);

public static final class RuntimeAccessOnly extends SingletonAccessSupplier {
@Override
public SingletonTrait getAccessTrait() {
return RUNTIME_ONLY;
}
}

/**
* Trait indicating this singleton should only be accessed from the native image generator
* process and not at runtime.
*/
public static final SingletonTrait BUILDTIME_ONLY = new SingletonTrait(SingletonTraitKind.ACCESS,
(SingletonAccess.Supplier) () -> LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY);

public static final class BuildtimeAccessOnly extends SingletonAccessSupplier {
@Override
public SingletonTrait getAccessTrait() {
return BUILDTIME_ONLY;
}
}

/**
* Trait indicating this singleton can be freely accessed both from the native image generator
* process and at runtime.
*/
public static final SingletonTrait ALL_ACCESS = new SingletonTrait(SingletonTraitKind.ACCESS,
(SingletonAccess.Supplier) () -> LayeredImageSingletonBuilderFlags.ALL_ACCESS);

public static final class AllAccess extends SingletonAccessSupplier {
@Override
public SingletonTrait getAccessTrait() {
return ALL_ACCESS;
}
}

/**
* Trait indicating this singleton has no special callbacks needed during layered builds.
*/
public static final SingletonTrait NO_LAYERED_CALLBACKS = new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() {
@Override
public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, Object singleton) {
return LayeredImageSingleton.PersistFlags.NOTHING;
}
});

public static class NoLayeredCallbacks extends SingletonLayeredCallbacksSupplier {
@Override
public SingletonTrait getLayeredCallbacksTrait() {
return NO_LAYERED_CALLBACKS;
}
}

/**
* Trait indicating this singleton can be made more layer-aware in the future. See
* {@link SingletonTraitKind#DUPLICABLE} for more information.
*/
public static final SingletonTrait DUPLICABLE_TRAIT = new SingletonTrait(SingletonTraitKind.DUPLICABLE, EmptyMetadata.EMPTY);

@SuppressWarnings("unused")
public static class Duplicable extends SingletonTraitsSupplier {
@Override
public SingletonTrait getTrait() {
return DUPLICABLE_TRAIT;
}
}
}
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 @@ -22,11 +22,15 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.layeredimagesingleton;
package com.oracle.svm.core.traits;

/**
* This is used to wrap singletons which are only allowed to be accessed at runtime. When a
* singleton wrapped with this is called during image build time an error is thrown.
* This metadata class is used for {@link SingletonTrait}s which need to store no additional
* content.
*/
public record RuntimeOnlyWrapper(LayeredImageSingleton wrappedObject) {
final class EmptyMetadata {
static final EmptyMetadata EMPTY = new EmptyMetadata();

private EmptyMetadata() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.traits;

import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton;

// GR-66792 remove once no custom persist actions exist

/**
* Temporarily used to convert {@link LayeredImageSingleton} callbacks into {@link SingletonTrait}
* information.
*/
public final class InjectedSingletonLayeredCallbacks extends SingletonLayeredCallbacks {
final LayeredImageSingleton singleton;

public InjectedSingletonLayeredCallbacks(LayeredImageSingleton singleton) {
this.singleton = singleton;
}

@Override
public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, Object obj) {
return singleton.preparePersist(writer);
}

public Class<?> getSingletonClass() {
return singleton.getClass();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.traits;

import java.util.EnumSet;

import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
import com.oracle.svm.core.util.VMError;

/**
* Metadata associated with the {@link SingletonTraitKind#ACCESS} trait. Describes when this
* singleton can be accessed (e.g., during the native image generator process and/or from within the
* generated code at runtime).
*/
public class SingletonAccess {
interface Supplier {
EnumSet<LayeredImageSingletonBuilderFlags> getAccessFlags();
}

public static EnumSet<LayeredImageSingletonBuilderFlags> getAccess(SingletonTrait trait) {
VMError.guarantee(trait.kind() == SingletonTraitKind.ACCESS);
return ((Supplier) trait.metadata()).getAccessFlags();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core.traits;

/**
* Represents a supplier of the {@link SingletonTraitKind#ACCESS} {@link SingletonTrait}. See
* {@link SingletonTraits} and {@link SingletonTraitKind#ACCESS} for more information.
*/
public abstract sealed class SingletonAccessSupplier permits BuiltinTraits.BuildtimeAccessOnly, BuiltinTraits.RuntimeAccessOnly, BuiltinTraits.AllAccess {
public abstract SingletonTrait getAccessTrait();
}
Loading