Skip to content

Commit 960db2e

Browse files
committed
[GR-66791] Introduce SingletonTraits annotation.
PullRequest: graal/21443
2 parents 728ff77 + 00608fc commit 960db2e

27 files changed

+1176
-145
lines changed

substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import org.graalvm.nativeimage.ImageSingletons;
3131
import org.graalvm.nativeimage.Platform;
3232
import org.graalvm.nativeimage.Platforms;
33-
import org.graalvm.nativeimage.hosted.Feature;
3433

3534
import com.oracle.graal.pointsto.BigBang;
3635
import com.oracle.graal.pointsto.meta.AnalysisMethod;
@@ -52,9 +51,11 @@
5251
import com.oracle.svm.core.graal.llvm.util.LLVMOptions;
5352
import com.oracle.svm.core.graal.meta.RuntimeConfiguration;
5453
import com.oracle.svm.core.graal.snippets.NodeLoweringProvider;
55-
import com.oracle.svm.core.layeredimagesingleton.UnsupportedLayeredSingleton;
5654
import com.oracle.svm.core.option.HostedOptionKey;
5755
import com.oracle.svm.core.snippets.ExceptionUnwind;
56+
import com.oracle.svm.core.traits.BuiltinTraits;
57+
import com.oracle.svm.core.traits.SingletonLayeredInstallationKind;
58+
import com.oracle.svm.core.traits.SingletonTraits;
5859
import com.oracle.svm.core.util.UserError;
5960
import com.oracle.svm.hosted.FeatureImpl;
6061
import com.oracle.svm.hosted.c.codegen.CCompilerInvoker;
@@ -81,7 +82,8 @@
8182
*/
8283
@AutomaticallyRegisteredFeature
8384
@Platforms({Platform.LINUX.class, Platform.DARWIN.class})
84-
public class LLVMFeature implements Feature, InternalFeature, UnsupportedLayeredSingleton {
85+
@SingletonTraits(access = BuiltinTraits.BuildtimeAccessOnly.class, layeredCallbacks = BuiltinTraits.NoLayeredCallbacks.class, layeredInstallationKind = SingletonLayeredInstallationKind.Disallowed.class)
86+
public class LLVMFeature implements InternalFeature {
8587

8688
@Override
8789
public boolean isInConfiguration(IsInConfigurationAccess access) {

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonBuilderFlags.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,7 @@ public enum LayeredImageSingletonBuilderFlags {
4141
/**
4242
* This singleton can be accessed from the buildtime.
4343
*/
44-
BUILDTIME_ACCESS,
45-
/**
46-
* This singleton should not have been created. Throw error if it is created.
47-
*/
48-
UNSUPPORTED;
44+
BUILDTIME_ACCESS;
4945

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

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

60-
public static boolean verifyImageBuilderFlags(LayeredImageSingleton singleton) {
61-
EnumSet<LayeredImageSingletonBuilderFlags> flags = singleton.getImageBuilderFlags();
62-
63-
if (!(flags.contains(UNSUPPORTED) || flags.contains(BUILDTIME_ACCESS) || flags.contains(RUNTIME_ACCESS))) {
64-
assert false : String.format("At least one of the following flags must be set: %s, %s, %s", UNSUPPORTED, BUILDTIME_ACCESS, RUNTIME_ACCESS);
65-
}
66-
67-
if (flags.contains(UNSUPPORTED)) {
68-
assert flags.equals(EnumSet.of(UNSUPPORTED)) : "Unsupported should be the only flag set " + flags;
56+
public static boolean verifyImageBuilderFlags(Object singleton, EnumSet<LayeredImageSingletonBuilderFlags> flags) {
57+
if (!(flags.contains(BUILDTIME_ACCESS) || flags.contains(RUNTIME_ACCESS))) {
58+
assert false : String.format("At least one of the following flags must be set: %s, %s", BUILDTIME_ACCESS, RUNTIME_ACCESS);
6959
}
7060

7161
if (singleton instanceof MultiLayeredImageSingleton || ApplicationLayerOnlyImageSingleton.isSingletonInstanceOf(singleton)) {
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.traits;
26+
27+
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
28+
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton;
29+
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
30+
31+
/**
32+
* Commonly used {@link SingletonTrait}s.
33+
*/
34+
public class BuiltinTraits {
35+
36+
/**
37+
* Trait indicating this singleton should only be accessed from code executed at runtime.
38+
*/
39+
public static final SingletonTrait RUNTIME_ONLY = new SingletonTrait(SingletonTraitKind.ACCESS,
40+
(SingletonAccess.Supplier) () -> LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY);
41+
42+
public static final class RuntimeAccessOnly extends SingletonAccessSupplier {
43+
@Override
44+
public SingletonTrait getAccessTrait() {
45+
return RUNTIME_ONLY;
46+
}
47+
}
48+
49+
/**
50+
* Trait indicating this singleton should only be accessed from the native image generator
51+
* process and not at runtime.
52+
*/
53+
public static final SingletonTrait BUILDTIME_ONLY = new SingletonTrait(SingletonTraitKind.ACCESS,
54+
(SingletonAccess.Supplier) () -> LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY);
55+
56+
public static final class BuildtimeAccessOnly extends SingletonAccessSupplier {
57+
@Override
58+
public SingletonTrait getAccessTrait() {
59+
return BUILDTIME_ONLY;
60+
}
61+
}
62+
63+
/**
64+
* Trait indicating this singleton can be freely accessed both from the native image generator
65+
* process and at runtime.
66+
*/
67+
public static final SingletonTrait ALL_ACCESS = new SingletonTrait(SingletonTraitKind.ACCESS,
68+
(SingletonAccess.Supplier) () -> LayeredImageSingletonBuilderFlags.ALL_ACCESS);
69+
70+
public static final class AllAccess extends SingletonAccessSupplier {
71+
@Override
72+
public SingletonTrait getAccessTrait() {
73+
return ALL_ACCESS;
74+
}
75+
}
76+
77+
/**
78+
* Trait indicating this singleton has no special callbacks needed during layered builds.
79+
*/
80+
public static final SingletonTrait NO_LAYERED_CALLBACKS = new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() {
81+
@Override
82+
public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, Object singleton) {
83+
return LayeredImageSingleton.PersistFlags.NOTHING;
84+
}
85+
});
86+
87+
public static class NoLayeredCallbacks extends SingletonLayeredCallbacksSupplier {
88+
@Override
89+
public SingletonTrait getLayeredCallbacksTrait() {
90+
return NO_LAYERED_CALLBACKS;
91+
}
92+
}
93+
94+
/**
95+
* Trait indicating this singleton can be made more layer-aware in the future. See
96+
* {@link SingletonTraitKind#DUPLICABLE} for more information.
97+
*/
98+
public static final SingletonTrait DUPLICABLE_TRAIT = new SingletonTrait(SingletonTraitKind.DUPLICABLE, EmptyMetadata.EMPTY);
99+
100+
@SuppressWarnings("unused")
101+
public static class Duplicable extends SingletonTraitsSupplier {
102+
@Override
103+
public SingletonTrait getTrait() {
104+
return DUPLICABLE_TRAIT;
105+
}
106+
}
107+
}
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -22,11 +22,15 @@
2222
* or visit www.oracle.com if you need additional information or have any
2323
* questions.
2424
*/
25-
package com.oracle.svm.core.layeredimagesingleton;
25+
package com.oracle.svm.core.traits;
2626

2727
/**
28-
* This is used to wrap singletons which are only allowed to be accessed at runtime. When a
29-
* singleton wrapped with this is called during image build time an error is thrown.
28+
* This metadata class is used for {@link SingletonTrait}s which need to store no additional
29+
* content.
3030
*/
31-
public record RuntimeOnlyWrapper(LayeredImageSingleton wrappedObject) {
31+
final class EmptyMetadata {
32+
static final EmptyMetadata EMPTY = new EmptyMetadata();
33+
34+
private EmptyMetadata() {
35+
}
3236
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.traits;
26+
27+
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
28+
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton;
29+
30+
// GR-66792 remove once no custom persist actions exist
31+
32+
/**
33+
* Temporarily used to convert {@link LayeredImageSingleton} callbacks into {@link SingletonTrait}
34+
* information.
35+
*/
36+
public final class InjectedSingletonLayeredCallbacks extends SingletonLayeredCallbacks {
37+
final LayeredImageSingleton singleton;
38+
39+
public InjectedSingletonLayeredCallbacks(LayeredImageSingleton singleton) {
40+
this.singleton = singleton;
41+
}
42+
43+
@Override
44+
public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, Object obj) {
45+
return singleton.preparePersist(writer);
46+
}
47+
48+
public Class<?> getSingletonClass() {
49+
return singleton.getClass();
50+
}
51+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.traits;
26+
27+
import java.util.EnumSet;
28+
29+
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
30+
import com.oracle.svm.core.util.VMError;
31+
32+
/**
33+
* Metadata associated with the {@link SingletonTraitKind#ACCESS} trait. Describes when this
34+
* singleton can be accessed (e.g., during the native image generator process and/or from within the
35+
* generated code at runtime).
36+
*/
37+
public class SingletonAccess {
38+
interface Supplier {
39+
EnumSet<LayeredImageSingletonBuilderFlags> getAccessFlags();
40+
}
41+
42+
public static EnumSet<LayeredImageSingletonBuilderFlags> getAccess(SingletonTrait trait) {
43+
VMError.guarantee(trait.kind() == SingletonTraitKind.ACCESS);
44+
return ((Supplier) trait.metadata()).getAccessFlags();
45+
}
46+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.traits;
26+
27+
/**
28+
* Represents a supplier of the {@link SingletonTraitKind#ACCESS} {@link SingletonTrait}. See
29+
* {@link SingletonTraits} and {@link SingletonTraitKind#ACCESS} for more information.
30+
*/
31+
public abstract sealed class SingletonAccessSupplier permits BuiltinTraits.BuildtimeAccessOnly, BuiltinTraits.RuntimeAccessOnly, BuiltinTraits.AllAccess {
32+
public abstract SingletonTrait getAccessTrait();
33+
}

0 commit comments

Comments
 (0)