From acd1fe86afb69731f73ddc8382ebf92ba156cd1f Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 4 Nov 2025 15:38:23 +0100 Subject: [PATCH 1/5] update JVMCI to 25.0.1+8-jvmci-25.1-b09 --- common.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common.json b/common.json index fdef930cc0fb..a34a3289be67 100644 --- a/common.json +++ b/common.json @@ -49,12 +49,12 @@ "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25.0.1+8", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25.0.1+8-jvmci-25.1-b08", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25.0.1+8-jvmci-25.1-b08-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25.0.1+8-jvmci-25.1-b08-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25.0.1+8-jvmci-25.1-b08", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25.0.1+8-jvmci-25.1-b08-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25.0.1+8-jvmci-25.1-b08-sulong", "platformspecific": true } + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25.0.1+8-jvmci-25.1-b09", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25.0.1+8-jvmci-25.1-b09-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25.0.1+8-jvmci-25.1-b09-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25.0.1+8-jvmci-25.1-b09", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25.0.1+8-jvmci-25.1-b09-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25.0.1+8-jvmci-25.1-b09-sulong", "platformspecific": true } }, "eclipse": { From 3d40f51d5700cf031d59a91be58566de44b7f190 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 4 Nov 2025 19:59:29 +0100 Subject: [PATCH 2/5] disable some String intrinsics that cannot work in libgraal --- .../StandardGraphBuilderPlugins.java | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/StandardGraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/StandardGraphBuilderPlugins.java index df20a31851eb..9d4f4bcc070f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/StandardGraphBuilderPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/StandardGraphBuilderPlugins.java @@ -53,6 +53,7 @@ import jdk.graal.compiler.api.directives.GraalDirectives; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.calc.Condition; import jdk.graal.compiler.core.common.calc.Condition.CanonicalizedCondition; import jdk.graal.compiler.core.common.calc.UnsignedMath; @@ -349,30 +350,33 @@ private boolean tryConstantFold(GraphBuilderContext b, ResolvedJavaField field, private static void registerStringPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection, boolean supportsStubBasedPlugins) { final Registration r = new Registration(plugins, String.class); - r.register(new InvocationPlugin("hashCode", Receiver.class) { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - String s = asConstantObject(b, String.class, receiver.get(false)); - if (s != null) { - b.addPush(JavaKind.Int, b.add(ConstantNode.forInt(s.hashCode()))); - return true; + if (!LibGraalSupport.inLibGraalRuntime()) { + // These intrinsics require converting constants to String objects in + // the current heap which is not not supported on libgraal. + r.register(new InvocationPlugin("hashCode", Receiver.class) { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + String s = asConstantObject(b, String.class, receiver.get(false)); + if (s != null) { + b.addPush(JavaKind.Int, b.add(ConstantNode.forInt(s.hashCode()))); + return true; + } + return false; } - return false; - } - }); - r.register(new InvocationPlugin("intern", Receiver.class) { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - String s = asConstantObject(b, String.class, receiver.get(false)); - if (s != null) { - JavaConstant interned = snippetReflection.forObject(s.intern()); - b.addPush(JavaKind.Object, b.add(ConstantNode.forConstant(interned, b.getMetaAccess(), b.getGraph()))); - return true; + }); + r.register(new InvocationPlugin("intern", Receiver.class) { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + String s = asConstantObject(b, String.class, receiver.get(false)); + if (s != null) { + JavaConstant interned = snippetReflection.forObject(s.intern()); + b.addPush(JavaKind.Object, b.add(ConstantNode.forConstant(interned, b.getMetaAccess(), b.getGraph()))); + return true; + } + return false; } - return false; - } - }); - + }); + } if (supportsStubBasedPlugins) { r.register(new StringEqualsInvocationPlugin()); } From 104734eaa902c472b304c16832df8b97487edccf Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 4 Nov 2025 13:56:58 +0100 Subject: [PATCH 3/5] avoid searching for inherited annotations unnecessarily --- .../src/org/graalvm/nativeimage/AnnotationAccess.java | 4 ++-- .../graalvm/nativeimage/impl/AnnotationExtractor.java | 11 +++++++++++ .../oracle/graal/pointsto/meta/AnalysisMethod.java | 2 +- .../src/com/oracle/svm/hosted/ImageClassLoader.java | 4 ++-- .../oracle/svm/hosted/ImageSingletonsSupportImpl.java | 4 ++-- .../svm/hosted/annotation/AnnotationWrapper.java | 2 +- 6 files changed, 19 insertions(+), 8 deletions(-) diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/AnnotationAccess.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/AnnotationAccess.java index 272e1f2cf94a..6fbe88217a51 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/AnnotationAccess.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/AnnotationAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -93,7 +93,7 @@ public static boolean isAnnotationPresent(AnnotatedElement element, Class T getAnnotation(AnnotatedElement element, Class annotationType) { if (ImageInfo.inImageBuildtimeCode()) { - return ImageSingletons.lookup(AnnotationExtractor.class).extractAnnotation(element, annotationType, false); + return ImageSingletons.lookup(AnnotationExtractor.class).extractAnnotation(element, annotationType); } else { return element.getAnnotation(annotationType); } diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/AnnotationExtractor.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/AnnotationExtractor.java index f63864e78aaf..af30eddd2d73 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/AnnotationExtractor.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/AnnotationExtractor.java @@ -41,6 +41,7 @@ package org.graalvm.nativeimage.impl; import java.lang.annotation.Annotation; +import java.lang.annotation.Inherited; import java.lang.reflect.AnnotatedElement; import org.graalvm.nativeimage.Platform; @@ -67,6 +68,16 @@ public interface AnnotationExtractor { */ T extractAnnotation(AnnotatedElement element, Class annotationType, boolean declaredOnly); + /** + * Gets {@code element}'s annotation of type {@code annotationType} if such an annotation is + * present, else null. This method will also search {@code element}'s superclasses if + * {@code annotationType} is {@linkplain Inherited inherited}. + */ + default T extractAnnotation(AnnotatedElement element, Class annotationType) { + Inherited inherited = annotationType.getAnnotation(Inherited.class); + return extractAnnotation(element, annotationType, inherited == null); + } + /** * Gets the {@link Annotation#annotationType()}s for all annotations on {@code element}. This * method includes inherited annotations. diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java index f661ac832652..42a0247b2597 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java @@ -287,7 +287,7 @@ protected AnalysisMethod(AnalysisUniverse universe, ResolvedJavaMethod wrapped, if (universe.hostVM.buildingImageLayer()) { var annotationExtractor = universe.getAnnotationExtractor(); if (annotationExtractor.hasAnnotation(wrapped, LayeredCompilationBehavior.class)) { - LayeredCompilationBehavior behavior = annotationExtractor.extractAnnotation(wrapped, LayeredCompilationBehavior.class, true); + LayeredCompilationBehavior behavior = annotationExtractor.extractAnnotation(wrapped, LayeredCompilationBehavior.class); compilationBehavior = behavior.value(); if (compilationBehavior == LayeredCompilationBehavior.Behavior.PINNED_TO_INITIAL_LAYER && universe.hostVM.buildingExtensionLayer() && !isInBaseLayer) { var errorMessage = String.format("User methods with layered compilation behavior %s must be registered via %s in the initial layer", diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java index d0990bd1a2ee..d355fc07068e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java @@ -134,7 +134,7 @@ private void findSystemElements(Class systemClass) { private boolean isInPlatform(AnnotatedElement element) { try { - Platforms platformAnnotation = classLoaderSupport.annotationExtractor.extractAnnotation(element, Platforms.class, false); + Platforms platformAnnotation = classLoaderSupport.annotationExtractor.extractAnnotation(element, Platforms.class); return NativeImageGenerator.includedIn(platform, platformAnnotation); } catch (Throwable t) { handleClassLoadingError(t); @@ -167,7 +167,7 @@ void handleClass(Class clazz) { do { Platforms platformsAnnotation; try { - platformsAnnotation = classLoaderSupport.annotationExtractor.extractAnnotation(cur, Platforms.class, false); + platformsAnnotation = classLoaderSupport.annotationExtractor.extractAnnotation(cur, Platforms.class); } catch (Throwable t) { handleClassLoadingError(t); return; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java index bcbf20c26485..b251ee806bc2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java @@ -207,7 +207,7 @@ void seal() { static SingletonTraitMap getAnnotatedTraits(Class singletonClass, AnnotationExtractor extractor, boolean layeredBuild) { SingletonTraitMap traitMap = SingletonTraitMap.create(); if (extractor != null) { - SingletonTraits annotation = extractor.extractAnnotation(singletonClass, SingletonTraits.class, false); + SingletonTraits annotation = extractor.extractAnnotation(singletonClass, SingletonTraits.class); if (annotation != null) { if (annotation.access() != null) { @@ -630,7 +630,7 @@ public SingletonTraitMap getUninstalledSingletonTraitMap(Class key) { SingletonInfo info = configObjects.computeIfAbsent(key, k -> { - SingletonTraits annotation = extractor.extractAnnotation(k, SingletonTraits.class, false); + SingletonTraits annotation = extractor.extractAnnotation(k, SingletonTraits.class); if (annotation != null) { if (annotation.layeredInstallationKind() != null) { var installationKindSupplierClass = annotation.layeredInstallationKind(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationWrapper.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationWrapper.java index 36ac474d1d4f..bc18ad368ee5 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationWrapper.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationWrapper.java @@ -45,7 +45,7 @@ default boolean isAnnotationPresent(Class annotationClass) @Override default T getAnnotation(Class annotationClass) { - return ImageSingletons.lookup(AnnotationExtractor.class).extractAnnotation(this, annotationClass, false); + return ImageSingletons.lookup(AnnotationExtractor.class).extractAnnotation(this, annotationClass); } @Override From 778daaf7f5fcba838b41e95d35a565324c301e4d Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 4 Nov 2025 14:04:44 +0100 Subject: [PATCH 4/5] do not store AnnotationExtractor image singleton in a static field --- .../src/com/oracle/svm/util/AnnotationUtil.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationUtil.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationUtil.java index 3eda89c0ae8b..99bf317900c3 100644 --- a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationUtil.java +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationUtil.java @@ -53,21 +53,24 @@ */ public final class AnnotationUtil { + /** + * Lazily created singleton to be used when outside the scope of a Native Image build. + */ @Platforms(Platform.HOSTED_ONLY.class) static class Lazy { static final AnnotatedObjectAccess instance; static { - if (ImageSingletons.contains(AnnotationExtractor.class)) { - instance = (AnnotatedObjectAccess) ImageSingletons.lookup(AnnotationExtractor.class); - } else { - ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, AnnotatedObjectAccess.class, false, "java.base", "sun.reflect.annotation"); - instance = new AnnotatedObjectAccess(); - } + ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, AnnotatedObjectAccess.class, false, "java.base", "sun.reflect.annotation"); + instance = new AnnotatedObjectAccess(); } } @Platforms(Platform.HOSTED_ONLY.class) private static AnnotatedObjectAccess instance() { + if (ImageSingletons.contains(AnnotationExtractor.class)) { + return (AnnotatedObjectAccess) ImageSingletons.lookup(AnnotationExtractor.class); + } + // Fall back to singleton when outside scope of a Native Image build. return Lazy.instance; } From 6f2a17ac745ac44d9f746371bf2d8a6af6031ded Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Mon, 3 Nov 2025 09:59:09 +0100 Subject: [PATCH 5/5] remove AnnotatedObjectAccess caches --- compiler/mx.compiler/mx_compiler.py | 1 + compiler/mx.compiler/mx_graal_benchmark.py | 1 + compiler/mx.compiler/suite.py | 3 + .../replaycomp/test/CompilationProxyTest.java | 2 +- .../compiler/annotation/AnnotationValue.java | 25 +++ .../annotation/AnnotationValueSupport.java | 84 +++++----- .../compiler/hotspot/JVMCIVersionCheck.java | 4 +- .../hotspot/SnippetResolvedJavaMethod.java | 12 ++ .../hotspot/SnippetResolvedJavaType.java | 12 ++ .../CompilerInterfaceDeclarations.java | 11 ++ .../proxy/CompilationProxyBase.java | 26 +++- .../proxy/HotSpotResolvedJavaTypeProxy.java | 18 +++ .../truffle/host/TruffleHostEnvironment.java | 15 +- .../mx.espresso-compiler-stub/suite.py | 4 + .../jvmci/meta/EspressoResolvedArrayType.java | 11 ++ .../meta/EspressoResolvedInstanceType.java | 2 +- .../jvmci/meta/EspressoResolvedJavaField.java | 5 +- .../meta/EspressoResolvedJavaMethod.java | 5 +- .../EspressoResolvedJavaRecordComponent.java | 5 +- .../jvmci/meta/EspressoResolvedJavaType.java | 3 +- .../meta/EspressoResolvedPrimitiveType.java | 11 ++ .../nativeimage/impl/AnnotationExtractor.java | 2 +- substratevm/mx.substratevm/mx_substratevm.py | 4 + substratevm/mx.substratevm/suite.py | 43 +++++- .../graal/pointsto/meta/AnalysisElement.java | 12 +- .../graal/pointsto/meta/AnalysisUniverse.java | 5 +- .../oracle/svm/graal/meta/SubstrateField.java | 3 +- .../svm/graal/meta/SubstrateMethod.java | 3 +- .../oracle/svm/graal/meta/SubstrateType.java | 3 +- .../substitutions/GraalSubstitutions.java | 18 --- .../oracle/svm/hosted/meta/HostedElement.java | 12 +- .../metadata/InterpreterAnnotated.java | 45 ++++++ .../InterpreterResolvedJavaField.java | 2 +- .../InterpreterResolvedJavaMethod.java | 2 +- .../metadata/InterpreterResolvedJavaType.java | 2 +- .../native-image/native-image.properties | 3 +- .../svm/util/AnnotatedObjectAccess.java | 143 ++++++++---------- .../com/oracle/svm/util/AnnotatedWrapper.java | 22 ++- .../com/oracle/svm/util/AnnotationUtil.java | 23 ++- .../oracle/svm/util/AnnotationsContainer.java | 12 ++ vm/mx.vm/mx_vm_gate.py | 2 +- web-image/mx.web-image/suite.py | 8 +- 42 files changed, 420 insertions(+), 209 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterAnnotated.java diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index 3bcf2b3785ce..5a8be53fe387 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -252,6 +252,7 @@ def _ctw_jvmci_export_args(arg_prefix='--'): 'add-exports=java.base/jdk.internal.module=ALL-UNNAMED', 'add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot=ALL-UNNAMED', 'add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED', + 'add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta.annotation=ALL-UNNAMED', 'add-exports=jdk.internal.vm.ci/jdk.vm.ci.services=ALL-UNNAMED', 'add-exports=jdk.internal.vm.ci/jdk.vm.ci.runtime=ALL-UNNAMED', 'add-exports=jdk.graal.compiler/jdk.graal.compiler.hotspot=ALL-UNNAMED', diff --git a/compiler/mx.compiler/mx_graal_benchmark.py b/compiler/mx.compiler/mx_graal_benchmark.py index ac7a14ddf6fa..66c4d0137bf9 100644 --- a/compiler/mx.compiler/mx_graal_benchmark.py +++ b/compiler/mx.compiler/mx_graal_benchmark.py @@ -414,6 +414,7 @@ def extraVmArgs(self): '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.services=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.runtime=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED', + '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta.annotation=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=ALL-UNNAMED', '--add-exports=jdk.graal.compiler/jdk.graal.compiler.graph=ALL-UNNAMED', '--add-exports=org.graalvm.truffle/com.oracle.truffle.api.benchmark=ALL-UNNAMED', diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index c0c5f73aa259..3a54628c0b76 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -316,6 +316,7 @@ "GRAAL_PROCESSOR", ], "javaCompliance" : "21+", + "spotbugs": "false", "workingSets" : "Graal,HotSpot", }, @@ -330,6 +331,7 @@ "requiresConcealed" : { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.code" ], }, @@ -400,6 +402,7 @@ "checkstyle" : "jdk.graal.compiler", "javaCompliance" : "21+", "jacoco" : "exclude", + "spotbugs": "false", "graalCompilerSourceEdition": "ignore", }, diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/CompilationProxyTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/CompilationProxyTest.java index cba643af9d34..e801b92ecdc2 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/CompilationProxyTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/CompilationProxyTest.java @@ -91,7 +91,7 @@ public void checkProxyMethods() throws IllegalAccessException, InvocationTargetE assertTrue("protected method should throw UnsupportedOperationException", e.getTargetException() instanceof UnsupportedOperationException); continue; } - Assert.fail("expected the protected method to throw"); + Assert.fail("expected the protected method to throw: " + method); } Object returnValue = createValue(method.getReturnType()); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/annotation/AnnotationValue.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/annotation/AnnotationValue.java index ec2e81530de5..68fb2d7175c1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/annotation/AnnotationValue.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/annotation/AnnotationValue.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.function.BiFunction; import jdk.graal.compiler.util.CollectionsUtil; import jdk.vm.ci.meta.ResolvedJavaType; @@ -375,4 +376,28 @@ public int hashCode() { } return type.hashCode() ^ elements.hashCode(); } + + /** + * Result of last call to {@link #toAnnotation}. + */ + private volatile Annotation annotationCache; + + /** + * Converts this to an {@link Annotation} of type {@code annotationType}, utilizing the provided + * converter function. The result is cached to improve performance by reducing redundant + * conversions. + * + * @param the type of the annotation to be created + * @param annotationType the desired annotation type + * @param converter a function that does the conversion + */ + @SuppressWarnings("unchecked") + public T toAnnotation(Class annotationType, BiFunction, T> converter) { + Annotation res = annotationCache; + if (res == null || res.annotationType() != annotationType) { + res = converter.apply(this, annotationType); + annotationCache = res; + } + return (T) res; + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/annotation/AnnotationValueSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/annotation/AnnotationValueSupport.java index c8ff19c42d63..eb5700ec1be4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/annotation/AnnotationValueSupport.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/annotation/AnnotationValueSupport.java @@ -32,13 +32,13 @@ import java.lang.reflect.Method; import java.lang.reflect.RecordComponent; import java.nio.ByteBuffer; -import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.util.CollectionsUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.UnresolvedJavaType; @@ -77,12 +77,26 @@ public static AnnotationValue getDeclaredAnnotationValue(ResolvedJavaType annota * present on this element */ public static Map getDeclaredAnnotationValues(Annotated annotated) { - AnnotationsInfo info = annotated.getDeclaredAnnotationInfo(); + return annotated.getDeclaredAnnotationInfo(ANNOTATIONS_INFO_PARSER).values; + } + + /** + * Result type returned by {@link AnnotationValueSupport#ANNOTATIONS_INFO_PARSER}. + * + * @param values the parsed annotations + * @param container used to resolve type names in the annotations + */ + public record ParsedDeclaredAnnotationValues(Map values, ResolvedJavaType container) { + public static ParsedDeclaredAnnotationValues NONE = new ParsedDeclaredAnnotationValues(CollectionsUtil.mapOf(), null); + } + + public static final Function ANNOTATIONS_INFO_PARSER = info -> { if (info == null) { - return Collections.emptyMap(); + return ParsedDeclaredAnnotationValues.NONE; } - return AnnotationValueParser.parseAnnotations(info.bytes(), info.constPool(), info.container()); - } + ResolvedJavaType container = info.container(); + return new ParsedDeclaredAnnotationValues(AnnotationValueParser.parseAnnotations(info.bytes(), info.constPool(), container), container); + }; /** * Gets the type annotations for {@code annotated} that back the implementation of @@ -122,9 +136,9 @@ public static List> getParameterAnnotationValues(ResolvedJ * null if no default is associated with {@code method}, or if {@code method} does not represent * a declared member of an annotation type. * - * @see Method#getDefaultValue() * @return the default value for the annotation member represented by this object. The type of * the returned value is specified by {@link AnnotationValue#get} + * @see Method#getDefaultValue() */ public static Object getAnnotationDefaultValue(ResolvedJavaMethod method) { AnnotationsInfo info = method.getAnnotationDefaultInfo(); @@ -150,47 +164,14 @@ public static AnnotationValue getAnnotationValue(Annotated annotated, Class> declaredAnnotations; - static { - final int cacheMaxSize = 4096; - if (LibGraalSupport.INSTANCE == null) { - declaredAnnotations = Collections.synchronizedMap(new java.util.LinkedHashMap<>(cacheMaxSize, 0.75f, true) { - @Override - protected boolean removeEldestEntry(Map.Entry> eldest) { - return size() > cacheMaxSize; - } - }); - } else { - declaredAnnotations = null; - } - } - @LibGraalSupport.HostedOnly private static AnnotationValue getAnnotationValue0(Annotated annotated, Class annotationType, boolean inherited) { - AnnotationsInfo info = annotated.getDeclaredAnnotationInfo(); - if (info == null && !inherited) { + ParsedDeclaredAnnotationValues parsed = annotated.getDeclaredAnnotationInfo(ANNOTATIONS_INFO_PARSER); + if (parsed.values == null && !inherited) { return null; } - Map map = declaredAnnotations.get(annotated); - if (map == null) { - /* - * Do not use Map#computeIfAbsent as Collections.SynchronizedMap#computeIfAbsent blocks - * readers during the creation of the cached value. - */ - map = AnnotationValueParser.parseAnnotations(info.bytes(), info.constPool(), info.container()); - var existing = declaredAnnotations.putIfAbsent(annotated, map); - if (existing != null) { - map = existing; - } - } - AnnotationValue res = lookup(annotationType, map, info); + AnnotationValue res = lookup(annotationType, parsed.values, parsed.container); if (res != null) { return res; } @@ -201,19 +182,22 @@ private static AnnotationValue getAnnotationValue0(Annotated annotated, Class, ResolvedJavaType> resolvedAnnotationTypeCache = LibGraalSupport.INSTANCE != null ? null - : new ConcurrentHashMap<>(); - + /** + * Looks up the annotation value of type {@code annotationType} in {@code map}. + * + * @param annotationType the type of annotation to look up + * @param map the map of annotation values to search + * @param container used to resolve the annotation type + * @return the annotation value if found, or null if not found + */ @LibGraalSupport.HostedOnly - private static AnnotationValue lookup(Class annotationType, Map map, AnnotationsInfo info) { + private static AnnotationValue lookup(Class annotationType, Map map, ResolvedJavaType container) { String internalName = "L" + annotationType.getName().replace(".", "/") + ";"; for (var e : map.entrySet()) { ResolvedJavaType type = e.getKey(); if (type.getName().equals(internalName)) { // The name matches so now double-check the resolved type matches - ResolvedJavaType resolved = resolvedAnnotationTypeCache.computeIfAbsent(annotationType, a -> UnresolvedJavaType.create(internalName).resolve(info.container())); - if (resolved.equals(type)) { + if (UnresolvedJavaType.create(internalName).resolve(container).equals(type)) { return e.getValue(); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index e63fba03fb7c..bdba26566950 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -58,8 +58,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( - "Oracle Corporation", createLabsJDKVersion("25.0.1+8", "25.1", 8), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25.0.1+8", "25.1", 8))); + "Oracle Corporation", createLabsJDKVersion("25.0.1+8", "25.1", 9), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25.0.1+8", "25.1", 9))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaMethod.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaMethod.java index 0baf22212ca9..cebb60b21f4a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaMethod.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaMethod.java @@ -27,6 +27,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Objects; +import java.util.function.Function; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantPool; @@ -38,6 +39,7 @@ import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.SpeculationLog; +import jdk.vm.ci.meta.annotation.AnnotationsInfo; /** * A minimal implementation of {@link ResolvedJavaMethod} for use by libgraal. @@ -225,6 +227,16 @@ public Annotation[] getDeclaredAnnotations() { throw new UnsupportedOperationException(); } + @Override + public T getDeclaredAnnotationInfo(Function parser) { + throw new UnsupportedOperationException(); + } + + @Override + public AnnotationsInfo getTypeAnnotationInfo() { + throw new UnsupportedOperationException(); + } + @Override public int getModifiers() { return modifiers; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaType.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaType.java index 569301b8ede6..c76b8a2b68cc 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaType.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SnippetResolvedJavaType.java @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.function.Function; import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; @@ -41,6 +42,7 @@ import jdk.vm.ci.meta.ResolvedJavaRecordComponent; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.UnresolvedJavaType; +import jdk.vm.ci.meta.annotation.AnnotationsInfo; /** * A minimal implementation of {@link ResolvedJavaType} for use by libgraal. @@ -381,6 +383,16 @@ public Annotation[] getDeclaredAnnotations() { throw new UnsupportedOperationException(); } + @Override + public T getDeclaredAnnotationInfo(Function parser) { + throw new UnsupportedOperationException(); + } + + @Override + public AnnotationsInfo getTypeAnnotationInfo() { + throw new UnsupportedOperationException(); + } + @Override public boolean isArray() { return javaClass.isArray(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java index e72a0362c9c7..e878e82ba667 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java @@ -25,6 +25,7 @@ package jdk.graal.compiler.hotspot.replaycomp; import static java.util.FormattableFlags.ALTERNATE; +import static jdk.graal.compiler.annotation.AnnotationValueSupport.ANNOTATIONS_INFO_PARSER; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEDYNAMIC; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEINTERFACE; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESPECIAL; @@ -45,6 +46,7 @@ import org.graalvm.collections.Equivalence; import org.graalvm.collections.UnmodifiableEconomicMap; +import jdk.graal.compiler.annotation.AnnotationValueSupport; import jdk.graal.compiler.bytecode.BytecodeStream; import jdk.graal.compiler.core.common.CompilerProfiler; import jdk.graal.compiler.debug.DebugContext; @@ -796,6 +798,15 @@ public static CompilerInterfaceDeclarations build() { return null; }) .setStrategy(HotSpotResolvedJavaMethodProxy.getGenericParameterTypesMethod, MethodStrategy.Passthrough) + .setStrategy(HotSpotResolvedJavaMethodProxy.getDeclaredAnnotationInfoMethod, MethodStrategy.Passthrough) + .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.getDeclaredAnnotationInfoMethod, (proxy, method, args, metaAccess) -> { + // The HostInliningPhase can query Truffle-related annotations during replay on jargraal. + Object function = args[0]; + if (function == ANNOTATIONS_INFO_PARSER) { + return AnnotationValueSupport.ParsedDeclaredAnnotationValues.NONE; + } + return null; + }) .setDefaultValueStrategy(HotSpotResolvedJavaMethodProxy.hasCodeAtLevelMethod, false) .setDefaultValue(HotSpotResolvedJavaMethodProxy.isInVirtualMethodTableMethod, false) .setDefaultValue(HotSpotResolvedJavaMethodProxy.intrinsicIdMethod, 0) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java index 0ff8754cf966..c9281125bc17 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java @@ -26,6 +26,10 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; +import java.util.function.Function; + +import jdk.vm.ci.meta.annotation.Annotated; +import jdk.vm.ci.meta.annotation.AnnotationsInfo; /** * A base class for compilation proxies providing implementations of shared methods. @@ -75,9 +79,9 @@ public final String toString() { /** * Base class to share method implementations for proxies that implement - * {@link AnnotatedElement}. + * {@link AnnotatedElement} and {@link Annotated}. */ - public abstract static class CompilationProxyAnnotatedBase extends CompilationProxyBase implements AnnotatedElement { + public abstract static class CompilationProxyAnnotatedBase extends CompilationProxyBase implements AnnotatedElement, Annotated { CompilationProxyAnnotatedBase(InvocationHandler handler) { super(handler); } @@ -106,5 +110,23 @@ public final Annotation[] getAnnotations() { public final Annotation[] getDeclaredAnnotations() { return (Annotation[]) handle(getDeclaredAnnotationsMethod, getDeclaredAnnotationsInvokable); } + + public static final SymbolicMethod getDeclaredAnnotationInfoMethod = new SymbolicMethod(Annotated.class, "getDeclaredAnnotationInfo", Function.class); + @SuppressWarnings("unchecked") // + public static final InvokableMethod getDeclaredAnnotationInfoInvokable = (receiver, args) -> ((Annotated) receiver).getDeclaredAnnotationInfo((Function) args[0]); + + @Override + @SuppressWarnings("unchecked") + public final T getDeclaredAnnotationInfo(Function parser) { + return (T) handle(getDeclaredAnnotationInfoMethod, getDeclaredAnnotationInfoInvokable, parser); + } + + public static final SymbolicMethod getTypeAnnotationInfoMethod = new SymbolicMethod(Annotated.class, "getTypeAnnotationInfo"); + public static final InvokableMethod getTypeAnnotationInfoInvokable = (receiver, args) -> ((Annotated) receiver).getTypeAnnotationInfo(); + + @Override + public final AnnotationsInfo getTypeAnnotationInfo() { + return (AnnotationsInfo) handle(getTypeAnnotationInfoMethod, getTypeAnnotationInfoInvokable); + } } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java index 446758832f63..ddde351ba3e9 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java @@ -38,6 +38,8 @@ import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsMethod; import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsInvokable; import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getTypeAnnotationInfoInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getTypeAnnotationInfoMethod; import java.lang.annotation.Annotation; import java.util.List; @@ -55,6 +57,8 @@ import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.UnresolvedJavaField; import jdk.vm.ci.meta.UnresolvedJavaType; +import jdk.vm.ci.meta.annotation.AbstractAnnotated; +import jdk.vm.ci.meta.annotation.AnnotationsInfo; public sealed class HotSpotResolvedJavaTypeProxy extends HotSpotResolvedJavaType implements CompilationProxy permits HotSpotResolvedObjectTypeProxy { private final InvocationHandler handler; @@ -503,6 +507,20 @@ public final Annotation[] getDeclaredAnnotations() { return (Annotation[]) handle(getDeclaredAnnotationsMethod, getDeclaredAnnotationsInvokable); } + @Override + public AnnotationsInfo getRawDeclaredAnnotationInfo() { + return (AnnotationsInfo) handle(getRawDeclaredAnnotationInfoMethod, getRawDeclaredAnnotationInfoInvokable); + } + + public static final SymbolicMethod getRawDeclaredAnnotationInfoMethod = new SymbolicMethod(AbstractAnnotated.class, "getRawDeclaredAnnotationInfo"); + @SuppressWarnings("unchecked") // + public static final InvokableMethod getRawDeclaredAnnotationInfoInvokable = (receiver, args) -> ((AbstractAnnotated) receiver).getRawDeclaredAnnotationInfo(); + + @Override + public AnnotationsInfo getTypeAnnotationInfo() { + return (AnnotationsInfo) handle(getTypeAnnotationInfoMethod, getTypeAnnotationInfoInvokable); + } + @Override public final Object unproxify() { return handle(unproxifyMethod, unproxifyInvokable); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/host/TruffleHostEnvironment.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/host/TruffleHostEnvironment.java index 3757aa6d19c3..1fb6cecf0a85 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/host/TruffleHostEnvironment.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/host/TruffleHostEnvironment.java @@ -24,6 +24,12 @@ */ package jdk.graal.compiler.truffle.host; +import java.util.Map; +import java.util.function.Function; + +import com.oracle.truffle.compiler.TruffleCompilable; +import com.oracle.truffle.compiler.TruffleCompilerRuntime; + import jdk.graal.compiler.annotation.AnnotationValue; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.serviceprovider.GraalServices; @@ -31,18 +37,11 @@ import jdk.graal.compiler.truffle.HostMethodInfo; import jdk.graal.compiler.truffle.TruffleCompilerConfiguration; import jdk.graal.compiler.truffle.TruffleCompilerImpl; - -import com.oracle.truffle.compiler.TruffleCompilable; -import com.oracle.truffle.compiler.TruffleCompilerRuntime; - import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import java.util.Map; -import java.util.function.Function; - /** * This class manages Truffle resources used during host Java compilation. A host environment is * only available if the Truffle runtime was fully initialized. In practice this means that several @@ -187,7 +186,7 @@ protected final HostMethodInfo computeHostMethodInfo(Map getRecordComponents() static final int ANNOTATION_DEFAULT_VALUE = 3; @Override - public AnnotationsInfo getDeclaredAnnotationInfo() { + public AnnotationsInfo getRawDeclaredAnnotationInfo() { if (isArray()) { return null; } diff --git a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaField.java b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaField.java index ac902cbb9287..ecf8ab83cf00 100644 --- a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaField.java +++ b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaField.java @@ -44,9 +44,10 @@ import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.UnresolvedJavaType; +import jdk.vm.ci.meta.annotation.AbstractAnnotated; import jdk.vm.ci.meta.annotation.AnnotationsInfo; -public final class EspressoResolvedJavaField implements ResolvedJavaField { +public final class EspressoResolvedJavaField extends AbstractAnnotated implements ResolvedJavaField { private static final int JVM_FIELDS_MODIFIERS = PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | ENUM | SYNTHETIC; private final EspressoResolvedInstanceType holder; @@ -155,7 +156,7 @@ public Field getMirror() { private native Field getMirror0(); @Override - public AnnotationsInfo getDeclaredAnnotationInfo() { + public AnnotationsInfo getRawDeclaredAnnotationInfo() { byte[] bytes = getRawAnnotationBytes(DECLARED_ANNOTATIONS); EspressoResolvedInstanceType container = getDeclaringClass(); return AnnotationsInfo.make(bytes, container.getConstantPool(), container); diff --git a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaMethod.java b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaMethod.java index d87a59d648c2..60598441c6f8 100644 --- a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaMethod.java +++ b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaMethod.java @@ -58,9 +58,10 @@ import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.SpeculationLog; import jdk.vm.ci.meta.TriState; +import jdk.vm.ci.meta.annotation.AbstractAnnotated; import jdk.vm.ci.meta.annotation.AnnotationsInfo; -public final class EspressoResolvedJavaMethod implements ResolvedJavaMethod { +public final class EspressoResolvedJavaMethod extends AbstractAnnotated implements ResolvedJavaMethod { private static final int JVM_METHOD_MODIFIERS = PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | SYNCHRONIZED | BRIDGE | VARARGS | NATIVE | ABSTRACT | STRICT | SYNTHETIC; public static final Parameter[] NO_PARAMETERS = new Parameter[0]; @@ -349,7 +350,7 @@ public boolean isScoped() { } @Override - public AnnotationsInfo getDeclaredAnnotationInfo() { + public AnnotationsInfo getRawDeclaredAnnotationInfo() { if (!hasAnnotations()) { return null; } diff --git a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaRecordComponent.java b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaRecordComponent.java index 2b07601b2e52..dfe123c952e5 100644 --- a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaRecordComponent.java +++ b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaRecordComponent.java @@ -28,9 +28,10 @@ import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaRecordComponent; +import jdk.vm.ci.meta.annotation.AbstractAnnotated; import jdk.vm.ci.meta.annotation.AnnotationsInfo; -public final class EspressoResolvedJavaRecordComponent implements ResolvedJavaRecordComponent { +public final class EspressoResolvedJavaRecordComponent extends AbstractAnnotated implements ResolvedJavaRecordComponent { private final EspressoResolvedInstanceType declaringRecord; private final int index; private final String name; @@ -59,7 +60,7 @@ public JavaType getType() { } @Override - public AnnotationsInfo getDeclaredAnnotationInfo() { + public AnnotationsInfo getRawDeclaredAnnotationInfo() { byte[] bytes = getRawAnnotationBytes(declaringRecord, index, DECLARED_ANNOTATIONS); EspressoResolvedInstanceType container = getDeclaringRecord(); return AnnotationsInfo.make(bytes, container.getConstantPool(), container); diff --git a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaType.java b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaType.java index b3e65e7d3bf5..a83b638b9882 100644 --- a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaType.java +++ b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedJavaType.java @@ -31,8 +31,9 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.UnresolvedJavaType; +import jdk.vm.ci.meta.annotation.AbstractAnnotated; -public abstract class EspressoResolvedJavaType implements ResolvedJavaType { +public abstract class EspressoResolvedJavaType extends AbstractAnnotated implements ResolvedJavaType { static final Annotation[] NO_ANNOTATIONS = {}; protected static final EspressoResolvedJavaField[] NO_FIELDS = new EspressoResolvedJavaField[0]; protected static final ResolvedJavaType[] NO_TYPES = new ResolvedJavaType[0]; diff --git a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedPrimitiveType.java b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedPrimitiveType.java index 1d03c0153756..ffc0991c14f1 100644 --- a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedPrimitiveType.java +++ b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/meta/EspressoResolvedPrimitiveType.java @@ -40,6 +40,7 @@ import jdk.vm.ci.meta.ResolvedJavaRecordComponent; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.UnresolvedJavaType; +import jdk.vm.ci.meta.annotation.AnnotationsInfo; public final class EspressoResolvedPrimitiveType extends EspressoResolvedJavaType { private static final EspressoResolvedPrimitiveType[] primitives; @@ -314,6 +315,16 @@ public Annotation[] getDeclaredAnnotations() { return NO_ANNOTATIONS; } + @Override + public AnnotationsInfo getRawDeclaredAnnotationInfo() { + return null; + } + + @Override + public AnnotationsInfo getTypeAnnotationInfo() { + return null; + } + @Override public Class getMirror() { return kind.toJavaClass(); diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/AnnotationExtractor.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/AnnotationExtractor.java index af30eddd2d73..dff1a45a687a 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/AnnotationExtractor.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/AnnotationExtractor.java @@ -71,7 +71,7 @@ public interface AnnotationExtractor { /** * Gets {@code element}'s annotation of type {@code annotationType} if such an annotation is * present, else null. This method will also search {@code element}'s superclasses if - * {@code annotationType} is {@linkplain Inherited inherited}. + * {@code annotationType} itself is annotated with {@linkplain Inherited inherited}. */ default T extractAnnotation(AnnotatedElement element, Class annotationType) { Inherited inherited = annotationType.getAnnotation(Inherited.class); diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 920618990968..2c38c1daf01e 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -621,6 +621,7 @@ def run_nic_conditional_config_test(agent_path, conditional_config_filter_path): '-Dcom.oracle.svm.configure.test.conditionalconfig.PartialConfigurationGenerator.enabled=true', '--add-exports=jdk.graal.compiler/jdk.graal.compiler.options=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED', + '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta.annotation=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=ALL-UNNAMED', 'com.oracle.svm.configure.test.conditionalconfig.PartialConfigurationGenerator#' + test_case]) config_output_dir = join(nic_test_dir, 'config-output') @@ -636,6 +637,7 @@ def run_nic_conditional_config_test(agent_path, conditional_config_filter_path): "-Dcom.oracle.svm.configure.test.conditionalconfig.ConfigurationVerifier.enabled=true", '--add-exports=jdk.graal.compiler/jdk.graal.compiler.options=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED', + '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta.annotation=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=ALL-UNNAMED', 'com.oracle.svm.configure.test.conditionalconfig.ConfigurationVerifier']) @@ -653,6 +655,7 @@ def run_agent_conditional_config_test(agent_path, conditional_config_filter_path '-Dcom.oracle.svm.configure.test.conditionalconfig.ConfigurationGenerator.enabled=true', '--add-exports=jdk.graal.compiler/jdk.graal.compiler.options=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED', + '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta.annotation=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=ALL-UNNAMED', 'com.oracle.svm.configure.test.conditionalconfig.ConfigurationGenerator']) # This run verifies that the generated configuration matches the expected one @@ -660,6 +663,7 @@ def run_agent_conditional_config_test(agent_path, conditional_config_filter_path '-Dcom.oracle.svm.configure.test.conditionalconfig.ConfigurationVerifier.enabled=true', '--add-exports=jdk.graal.compiler/jdk.graal.compiler.options=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED', + '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta.annotation=ALL-UNNAMED', '--add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=ALL-UNNAMED', 'com.oracle.svm.configure.test.conditionalconfig.ConfigurationVerifier']) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 36101f502f46..62c02afb8813 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -261,6 +261,7 @@ "requiresConcealed" : { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ] }, "javaCompliance" : "21+", @@ -270,6 +271,7 @@ "checkstyle": "com.oracle.svm.core", "workingSets": "SVM", "jacoco" : "include", + "spotbugs": "false", }, # Shade Cap'n Proto Runtime @@ -432,7 +434,8 @@ ], "jdk.internal.vm.ci" : [ "jdk.vm.ci.code", - "jdk.vm.ci.meta" + "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], }, "checkstyle": "com.oracle.svm.core", @@ -457,7 +460,8 @@ "jdk.vm.ci.code.site", "jdk.vm.ci.amd64", "jdk.vm.ci.code", - "jdk.vm.ci.meta" + "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], }, "checkstyle": "com.oracle.svm.core", @@ -481,7 +485,8 @@ "jdk.vm.ci.code.site", "jdk.vm.ci.aarch64", "jdk.vm.ci.code", - "jdk.vm.ci.meta" + "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], }, "checkstyle": "com.oracle.svm.core", @@ -505,6 +510,7 @@ "jdk.vm.ci.code.site", "jdk.vm.ci.code", "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.riscv64" ], }, @@ -532,6 +538,7 @@ ], "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.code", "jdk.vm.ci.code.site", ], @@ -562,6 +569,7 @@ "jdk.internal.vm.ci" : [ "jdk.vm.ci.code", "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.aarch64", "jdk.vm.ci.amd64", "jdk.vm.ci.riscv64" @@ -588,6 +596,7 @@ "jdk.internal.vm.ci" : [ "jdk.vm.ci.code", "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.amd64" ], }, @@ -661,6 +670,7 @@ ], "workingSets": "SVM", "jacoco" : "exclude", + "spotbugs": "false" }, "com.oracle.graal.pointsto.standalone.test": { @@ -678,6 +688,7 @@ "requiresConcealed": { "jdk.internal.vm.ci": [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ] }, "checkstyle": "com.oracle.svm.test", @@ -709,6 +720,7 @@ "compiler:GRAAL_PROCESSOR", ], "workingSets": "SVM", + "spotbugs": "false", "jacoco" : "exclude", # experimental code not used in production }, @@ -1160,6 +1172,7 @@ "jdk.internal.vm.ci": [ "jdk.vm.ci.code", "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], }, "checkstyle": "com.oracle.svm.test", @@ -1219,8 +1232,9 @@ ], "requiresConcealed": { "jdk.internal.vm.ci": [ - "jdk.vm.ci.meta" - ], + "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", +], }, "checkstyle": "com.oracle.svm.test", "workingSets": "SVM", @@ -1262,7 +1276,8 @@ "jdk.vm.ci.code", "jdk.vm.ci.aarch64", "jdk.vm.ci.amd64", - "jdk.vm.ci.meta" + "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], }, "checkstyle" : "com.oracle.svm.hosted", @@ -1323,6 +1338,7 @@ "requiresConcealed" : { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], }, "checkstyle": "com.oracle.svm.test", @@ -1350,6 +1366,7 @@ "SVM_PROCESSOR", ], "workingSets": "SVM", + "spotbugs": "false", "jacoco" : "exclude", }, @@ -1470,6 +1487,7 @@ "requiresConcealed" : { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], }, "generatedDependencies": [ @@ -1501,6 +1519,7 @@ "requiresConcealed": { "jdk.internal.vm.ci": [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ] }, "checkstyle": "com.oracle.svm.hosted", @@ -1545,6 +1564,7 @@ "requiresConcealed" : { "jdk.internal.vm.ci": [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ] }, "checkstyle": "com.oracle.svm.hosted", @@ -1622,6 +1642,7 @@ "requiresConcealed" : { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], }, "checkstyle": "com.oracle.svm.hosted", @@ -1673,6 +1694,7 @@ "requiresConcealed" : { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], }, "checkstyle": "com.oracle.svm.hosted", @@ -1697,6 +1719,7 @@ "requiresConcealed" : { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], "java.base" : [ "jdk.internal.misc", # Signal @@ -1723,6 +1746,7 @@ "requiresConcealed" : { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.code", ], "java.base" : [ @@ -1845,6 +1869,7 @@ "jdk.internal.vm.ci": [ "jdk.vm.ci.common", "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.code", "jdk.vm.ci.services", "jdk.vm.ci.runtime", @@ -2076,6 +2101,7 @@ "jdk.internal.vm.ci": [ "jdk.vm.ci.common", "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.code", "jdk.vm.ci.services", "jdk.vm.ci.runtime", @@ -2184,6 +2210,7 @@ "jdk.graal.compiler.options.OptionDescriptors", ], "requires" : [ + "org.graalvm.nativeimage.configure", "org.graalvm.nativeimage.builder", "java.management", "jdk.management", @@ -2218,6 +2245,7 @@ "requiresConcealed" : { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", ], }, "requires": [ @@ -2394,6 +2422,7 @@ ], "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.common", "jdk.vm.ci.code", "jdk.vm.ci.runtime", @@ -2436,6 +2465,7 @@ ], "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.common", "jdk.vm.ci.code", "jdk.vm.ci.runtime", @@ -2605,6 +2635,7 @@ "requiresConcealed": { "jdk.internal.vm.ci" : [ "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", "jdk.vm.ci.code", "jdk.vm.ci.amd64", "jdk.vm.ci.aarch64", diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisElement.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisElement.java index a1acc1e60a80..df6fcd5fa272 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisElement.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisElement.java @@ -56,10 +56,11 @@ import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.annotation.AbstractAnnotated; import jdk.vm.ci.meta.annotation.Annotated; import jdk.vm.ci.meta.annotation.AnnotationsInfo; -public abstract class AnalysisElement implements AnnotatedElement { +public abstract class AnalysisElement extends AbstractAnnotated implements AnnotatedElement { protected static final AtomicReferenceFieldUpdater trackAcrossLayersUpdater = AtomicReferenceFieldUpdater .newUpdater(AnalysisElement.class, Object.class, "trackAcrossLayers"); @@ -77,12 +78,9 @@ protected AnalysisElement(boolean enableTrackAcrossLayers) { protected abstract AnalysisUniverse getUniverse(); - public AnnotationsInfo getDeclaredAnnotationInfo() { - return ((Annotated) getWrapped()).getDeclaredAnnotationInfo(); - } - - public AnnotationsInfo getTypeAnnotationInfo() { - return ((Annotated) getWrapped()).getTypeAnnotationInfo(); + @Override + public AnnotationsInfo getRawDeclaredAnnotationInfo() { + return ((Annotated) getWrapped()).getDeclaredAnnotationInfo(null); } @Override diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java index fb28d6f3d7a7..2b48d49f2b7c 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java @@ -47,8 +47,8 @@ import com.oracle.graal.pointsto.api.HostVM; import com.oracle.graal.pointsto.api.ImageLayerLoader; import com.oracle.graal.pointsto.api.ImageLayerWriter; -import com.oracle.graal.pointsto.constraints.UnsupportedPlatformException; import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; +import com.oracle.graal.pointsto.constraints.UnsupportedPlatformException; import com.oracle.graal.pointsto.heap.HeapSnapshotVerifier; import com.oracle.graal.pointsto.heap.HostedValuesProvider; import com.oracle.graal.pointsto.heap.ImageHeapConstant; @@ -419,12 +419,11 @@ public JavaMethod lookupAllowUnresolved(JavaMethod rawMethod) { if (rawMethod == null) { return null; } - if (!(rawMethod instanceof ResolvedJavaMethod)) { + if (!(rawMethod instanceof ResolvedJavaMethod method)) { return rawMethod; } assert !(rawMethod instanceof AnalysisMethod) : rawMethod; - ResolvedJavaMethod method = (ResolvedJavaMethod) rawMethod; method = substitutions.lookup(method); AnalysisMethod result = methods.get(method); if (result == null) { diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateField.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateField.java index bdcbfb5790a1..9cd0c9b2caf6 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateField.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateField.java @@ -28,6 +28,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Modifier; +import java.util.function.Function; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -163,7 +164,7 @@ private RuntimeException annotationsUnimplemented() { } @Override - public AnnotationsInfo getDeclaredAnnotationInfo() { + public T getDeclaredAnnotationInfo(Function parser) { throw annotationsUnimplemented(); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMethod.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMethod.java index 7a872eae2c87..4c1e83a6ad0a 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMethod.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateMethod.java @@ -31,6 +31,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Modifier; import java.lang.reflect.Type; +import java.util.function.Function; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -422,7 +423,7 @@ private RuntimeException annotationsUnimplemented() { } @Override - public AnnotationsInfo getDeclaredAnnotationInfo() { + public T getDeclaredAnnotationInfo(Function parser) { throw annotationsUnimplemented(); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateType.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateType.java index f8b8e26ba271..621b9e8e4e6f 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateType.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateType.java @@ -30,6 +30,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.function.Function; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -386,7 +387,7 @@ private RuntimeException annotationsUnimplemented() { } @Override - public AnnotationsInfo getDeclaredAnnotationInfo() { + public T getDeclaredAnnotationInfo(Function parser) { throw annotationsUnimplemented(); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/substitutions/GraalSubstitutions.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/substitutions/GraalSubstitutions.java index 84ee13a5b619..fc9f2b8dc83b 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/substitutions/GraalSubstitutions.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/substitutions/GraalSubstitutions.java @@ -30,10 +30,8 @@ import java.io.IOException; import java.io.PrintStream; -import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Set; import org.graalvm.collections.EconomicMap; @@ -65,8 +63,6 @@ import com.oracle.svm.graal.meta.SubstrateMethod; import com.oracle.svm.util.ReflectionUtil; -import jdk.graal.compiler.annotation.AnnotationValue; -import jdk.graal.compiler.annotation.AnnotationValueSupport; import jdk.graal.compiler.core.common.CompilationIdentifier; import jdk.graal.compiler.core.gen.NodeLIRBuilder; import jdk.graal.compiler.core.match.MatchRuleRegistry; @@ -96,8 +92,6 @@ import jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.annotation.Annotated; @TargetClass(value = InvocationPlugins.class, onlyWith = RuntimeCompilationFeature.IsEnabled.class) final class Target_jdk_graal_compiler_nodes_graphbuilderconf_InvocationPlugins { @@ -215,18 +209,6 @@ final class Target_jdk_graal_compiler_debug_TTY { private static PrintStream out = Log.logStream(); } -@TargetClass(value = AnnotationValueSupport.class, onlyWith = RuntimeCompilationFeature.IsEnabled.class) -final class Target_jdk_graal_compiler_annotation_AnnotationValueSupport { - - @Alias// - @RecomputeFieldValue(kind = Reset)// - private static Map> declaredAnnotations; - - @Alias// - @RecomputeFieldValue(kind = Reset)// - private static Map, ResolvedJavaType> resolvedAnnotationTypeCache; -} - @TargetClass(className = "jdk.graal.compiler.serviceprovider.IsolateUtil", onlyWith = GraalCompilerFeature.IsEnabled.class) final class Target_jdk_graal_compiler_serviceprovider_IsolateUtil { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedElement.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedElement.java index d082dc505a95..03f9636d9436 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedElement.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedElement.java @@ -31,19 +31,17 @@ import com.oracle.svm.util.AnnotationUtil; import jdk.graal.compiler.debug.GraalError; +import jdk.vm.ci.meta.annotation.AbstractAnnotated; import jdk.vm.ci.meta.annotation.Annotated; import jdk.vm.ci.meta.annotation.AnnotationsInfo; -public abstract class HostedElement implements AnnotatedElement { +public abstract class HostedElement extends AbstractAnnotated implements AnnotatedElement { protected abstract AnnotatedElement getWrapped(); - public AnnotationsInfo getDeclaredAnnotationInfo() { - return ((Annotated) getWrapped()).getDeclaredAnnotationInfo(); - } - - public AnnotationsInfo getTypeAnnotationInfo() { - return ((Annotated) getWrapped()).getTypeAnnotationInfo(); + @Override + public AnnotationsInfo getRawDeclaredAnnotationInfo() { + return ((Annotated) getWrapped()).getDeclaredAnnotationInfo(null); } @Override diff --git a/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterAnnotated.java b/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterAnnotated.java new file mode 100644 index 000000000000..3c29023f4514 --- /dev/null +++ b/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterAnnotated.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023, 2023, 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.interpreter.metadata; + +import java.util.function.Function; + +import com.oracle.svm.core.util.VMError; + +import jdk.vm.ci.meta.annotation.Annotated; +import jdk.vm.ci.meta.annotation.AnnotationsInfo; + +public class InterpreterAnnotated implements Annotated { + + @Override + public T getDeclaredAnnotationInfo(Function parser) { + throw VMError.intentionallyUnimplemented(); + } + + @Override + public AnnotationsInfo getTypeAnnotationInfo() { + throw VMError.intentionallyUnimplemented(); + } +} diff --git a/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaField.java b/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaField.java index e7a3deefdee5..c01300b28627 100644 --- a/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaField.java +++ b/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaField.java @@ -50,7 +50,7 @@ import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.UnresolvedJavaType; -public class InterpreterResolvedJavaField implements ResolvedJavaField, CremaFieldAccess, ResolvedMember { +public class InterpreterResolvedJavaField extends InterpreterAnnotated implements ResolvedJavaField, CremaFieldAccess, ResolvedMember { public static final InterpreterResolvedJavaField[] EMPTY_ARRAY = new InterpreterResolvedJavaField[0]; // Special offset values diff --git a/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaMethod.java b/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaMethod.java index 4b832ecb4ce1..2f7eba06c692 100644 --- a/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaMethod.java +++ b/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaMethod.java @@ -83,7 +83,7 @@ * Encapsulates resolved methods used under close-world assumptions, compiled and interpretable, but * also abstract methods for vtable calls. */ -public class InterpreterResolvedJavaMethod implements ResolvedJavaMethod, CremaMethodAccess, ResolvedMember { +public class InterpreterResolvedJavaMethod extends InterpreterAnnotated implements ResolvedJavaMethod, CremaMethodAccess, ResolvedMember { @Platforms(Platform.HOSTED_ONLY.class)// @SuppressWarnings("unchecked") // private static final Class CALLER_SENSITIVE_CLASS = (Class) ReflectionUtil.lookupClass("jdk.internal.reflect.CallerSensitive"); diff --git a/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaType.java b/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaType.java index 6985455920b2..e09fe07a30b5 100644 --- a/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaType.java +++ b/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/InterpreterResolvedJavaType.java @@ -52,7 +52,7 @@ * Represents a primitive or reference resolved Java type, including additional capabilities of the * closed world e.g. instantiable, instantiated, effectively final ... */ -public abstract class InterpreterResolvedJavaType implements ResolvedJavaType, CremaTypeAccess { +public abstract class InterpreterResolvedJavaType extends InterpreterAnnotated implements ResolvedJavaType, CremaTypeAccess { public static final InterpreterResolvedJavaType[] EMPTY_ARRAY = new InterpreterResolvedJavaType[0]; private final Symbol type; diff --git a/substratevm/src/com.oracle.svm.truffle.tck/src/META-INF/native-image/native-image.properties b/substratevm/src/com.oracle.svm.truffle.tck/src/META-INF/native-image/native-image.properties index 192b903e9912..8f90a6ccec2e 100644 --- a/substratevm/src/com.oracle.svm.truffle.tck/src/META-INF/native-image/native-image.properties +++ b/substratevm/src/com.oracle.svm.truffle.tck/src/META-INF/native-image/native-image.properties @@ -18,7 +18,8 @@ JavaArgs = --add-exports org.graalvm.nativeimage.base/com.oracle.svm.util=ALL-UN --add-exports org.graalvm.truffle.runtime/com.oracle.truffle.runtime=ALL-UNNAMED \ --add-exports jdk.graal.compiler/jdk.graal.compiler.util.json=ALL-UNNAMED \ --add-exports jdk.internal.vm.ci/jdk.vm.ci.common=ALL-UNNAMED \ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED + --add-exports jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.meta.annotation=ALL-UNNAMED ProvidedHostedOptions = \ TruffleTCKCollectMode= \ diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotatedObjectAccess.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotatedObjectAccess.java index 532018fa012f..0c329dc6445c 100644 --- a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotatedObjectAccess.java +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotatedObjectAccess.java @@ -33,12 +33,13 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import jdk.graal.compiler.annotation.AnnotationValue; +import jdk.graal.compiler.annotation.AnnotationValueParser; import jdk.graal.compiler.annotation.AnnotationValueSupport; import jdk.graal.compiler.annotation.ElementTypeMismatch; import jdk.graal.compiler.annotation.EnumElement; @@ -51,6 +52,7 @@ import jdk.vm.ci.meta.ResolvedJavaRecordComponent; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.annotation.Annotated; +import jdk.vm.ci.meta.annotation.AnnotationsInfo; import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationSupport; import sun.reflect.annotation.AnnotationType; @@ -62,12 +64,6 @@ */ @Platforms(Platform.HOSTED_ONLY.class) public class AnnotatedObjectAccess { - private final Map> annotationCache = new ConcurrentHashMap<>(); - private final Map> declaredAnnotationCache = new ConcurrentHashMap<>(); - private final Map>> parameterAnnotationCache = new ConcurrentHashMap<>(); - private final Map> typeAnnotationCache = new ConcurrentHashMap<>(); - private final Map annotationDefaultCache = new ConcurrentHashMap<>(); - private final Map resolvedAnnotationsCache = new ConcurrentHashMap<>(); /** * Gets the annotation of type {@code annotationType} from {@code element}. @@ -169,7 +165,7 @@ private static Object toAnnotationElement(Class returnType, Object avElement) } case AnnotationValue av -> { Class type = (Class) OriginalClassProvider.getJavaClass(av.getAnnotationType()); - return toAnnotation(av, type); + return toAnnotation0(av, type); } case List adList -> { int length = adList.size(); @@ -247,6 +243,10 @@ private static Object toAnnotationElement(Class returnType, Object avElement) * Converts {@code annotationValue} to an instance of {@code type}. */ private static T toAnnotation(AnnotationValue annotationValue, Class type) { + return annotationValue.toAnnotation(type, AnnotatedObjectAccess::toAnnotation0); + } + + private static T toAnnotation0(AnnotationValue annotationValue, Class type) { AnnotationType annotationType = AnnotationType.getInstance(type); Map memberValues = new EconomicHashMap<>(); for (var e : annotationType.members().entrySet()) { @@ -271,36 +271,16 @@ protected T getAnnotation(Annotated element, Class ann Map annotationValues = getAnnotationValues(element, declaredOnly); AnnotationValue annotation = annotationValues.get(GraalAccess.lookupType(annotationType)); if (annotation != null) { - return (T) resolvedAnnotationsCache.computeIfAbsent(annotation, value -> toAnnotation(value, annotationType)); + return toAnnotation(annotation, annotationType); } return null; } - private static String loaderName(ClassLoader loader) { - if (loader == null) { - return "null"; - } - var loaderName = loader.getName(); - if (loaderName == null || loaderName.isBlank()) { - return loader.getClass().getName(); - } else { - return loaderName; - } - } - /** * Converts an {@link AnnotationValue} to an {@link Annotation} of type {@code annotationType}. */ public T asAnnotation(AnnotationValue annotationValue, Class annotationType) { - T res = annotationType.cast(resolvedAnnotationsCache.computeIfAbsent(annotationValue, value -> toAnnotation(value, annotationType))); - Class resType = res.annotationType(); - if (!resType.equals(annotationType)) { - - throw new IllegalArgumentException("Conversion failed: expected %s (loader: %s), got %s (loader: %s)".formatted( - annotationType.getName(), loaderName(annotationType.getClassLoader()), - resType.getName(), loaderName(resType.getClassLoader()))); - } - return res; + return toAnnotation(annotationValue, annotationType); } /** @@ -312,7 +292,10 @@ public AnnotationValue asAnnotationValue(Annotation annotation) { protected boolean hasAnnotation(Annotated element, Class annotationType) { try { - return getAnnotationValues(element, false).containsKey(GraalAccess.lookupType(annotationType)); + // Checkstyle: allow direct annotation access + Inherited inherited = annotationType.getAnnotation(Inherited.class); + // Checkstyle: disallow direct annotation access + return getAnnotationValues(element, inherited == null).containsKey(GraalAccess.lookupType(annotationType)); } catch (LinkageError e) { /* * Returning false essentially means that the element doesn't declare the @@ -390,35 +373,28 @@ private Map getAnnotationValuesFromRoot(Annot return getDeclaredAnnotationValuesFromRoot(rootElement); } - Map existing = annotationCache.get(clazz); - if (existing != null) { - return existing; - } - /* * Inheritable annotations must be computed first to avoid recursively updating * annotationCache. */ Map inheritableAnnotations = getInheritableAnnotations(clazz); - return annotationCache.computeIfAbsent(clazz, element -> { - Map declaredAnnotations = getDeclaredAnnotationValuesFromRoot(element); - Map annotations = null; - if (inheritableAnnotations != null) { - for (var e : inheritableAnnotations.entrySet()) { - if (!declaredAnnotations.containsKey(e.getKey())) { - if (annotations == null) { - annotations = new EconomicHashMap<>(declaredAnnotations); - } - annotations.put(e.getKey(), e.getValue()); + Map declaredAnnotations = getDeclaredAnnotationValuesFromRoot(rootElement); + Map annotations = null; + if (inheritableAnnotations != null) { + for (var e : inheritableAnnotations.entrySet()) { + if (!declaredAnnotations.containsKey(e.getKey())) { + if (annotations == null) { + annotations = new EconomicHashMap<>(declaredAnnotations); } + annotations.put(e.getKey(), e.getValue()); } } - return annotations != null ? annotations : declaredAnnotations; - }); + } + return annotations != null ? annotations : declaredAnnotations; } - private Map getDeclaredAnnotationValuesFromRoot(Annotated rootElement) { - return declaredAnnotationCache.computeIfAbsent(rootElement, AnnotatedObjectAccess::parseDeclaredAnnotationValues); + private static Map getDeclaredAnnotationValuesFromRoot(Annotated rootElement) { + return rootElement.getDeclaredAnnotationInfo(ANNOTATIONS_INFO_PARSER); } /** @@ -426,15 +402,23 @@ private Map getDeclaredAnnotationValuesFromRo */ public static final ResolvedJavaType ANNOTATION_FORMAT_ERROR_TYPE = GraalAccess.lookupType(Void.TYPE); - private static Map parseDeclaredAnnotationValues(Annotated element) { + /** + * Annotation parser function stored as a singleton as recommended by + * {@link Annotated#getDeclaredAnnotationInfo(Function)}. + */ + private static final Function> ANNOTATIONS_INFO_PARSER = info -> { + if (info == null) { + return Map.of(); + } + ResolvedJavaType container = info.container(); try { - return AnnotationValueSupport.getDeclaredAnnotationValues(element); + return AnnotationValueParser.parseAnnotations(info.bytes(), info.constPool(), container); } catch (AnnotationFormatError e) { return Map.of(ANNOTATION_FORMAT_ERROR_TYPE, new AnnotationValue(e)); } catch (IllegalArgumentException | BufferUnderflowException | GenericSignatureFormatError e) { return Map.of(ANNOTATION_FORMAT_ERROR_TYPE, new AnnotationValue(new AnnotationFormatError(e))); } - } + }; /** * Gets the annotation values associated with the parameters of {@code element}. @@ -449,17 +433,15 @@ public List> getParameterAnnotationValues(Annotated elemen return root != null ? getParameterAnnotationValuesFromRoot((ResolvedJavaMethod) root) : List.of(); } - private List> getParameterAnnotationValuesFromRoot(ResolvedJavaMethod rootElement) { - return parameterAnnotationCache.computeIfAbsent(rootElement, element -> { - try { - List> parameterAnnotationValues = AnnotationValueSupport.getParameterAnnotationValues(element); - return parameterAnnotationValues == null ? List.of() : parameterAnnotationValues; - } catch (IllegalArgumentException | BufferUnderflowException | GenericSignatureFormatError e) { - return List.of(List.of(new AnnotationValue(new AnnotationFormatError(e)))); - } catch (AnnotationFormatError e) { - return List.of(List.of(new AnnotationValue(e))); - } - }); + private static List> getParameterAnnotationValuesFromRoot(ResolvedJavaMethod rootElement) { + try { + List> parameterAnnotationValues = AnnotationValueSupport.getParameterAnnotationValues(rootElement); + return parameterAnnotationValues == null ? List.of() : parameterAnnotationValues; + } catch (IllegalArgumentException | BufferUnderflowException | GenericSignatureFormatError e) { + return List.of(List.of(new AnnotationValue(new AnnotationFormatError(e)))); + } catch (AnnotationFormatError e) { + return List.of(List.of(new AnnotationValue(e))); + } } /** @@ -473,20 +455,16 @@ public List getTypeAnnotationValues(Annotated element) { return root != null ? getTypeAnnotationValuesFromRoot(root) : List.of(); } - private List getTypeAnnotationValuesFromRoot(Annotated rootElement) { - return typeAnnotationCache.computeIfAbsent(rootElement, AnnotatedObjectAccess::parseTypeAnnotationValues); - } - - private static List parseTypeAnnotationValues(Annotated element) { + private static List getTypeAnnotationValuesFromRoot(Annotated rootElement) { try { - return switch (element) { + return switch (rootElement) { case ResolvedJavaType type -> AnnotationValueSupport.getTypeAnnotationValues(type); case ResolvedJavaMethod method -> AnnotationValueSupport.getTypeAnnotationValues(method); case ResolvedJavaField field -> AnnotationValueSupport.getTypeAnnotationValues(field); case ResolvedJavaRecordComponent recordComponent -> AnnotationValueSupport.getTypeAnnotationValues(recordComponent); default -> - throw new AnnotatedObjectAccessError(element, "Unexpected annotated element type: " + element.getClass()); + throw new AnnotatedObjectAccessError(rootElement, "Unexpected annotated element type: " + rootElement.getClass()); }; } catch (IllegalArgumentException | BufferUnderflowException | GenericSignatureFormatError e) { return List.of(new TypeAnnotationValue(new AnnotationFormatError(e))); @@ -502,19 +480,16 @@ private static List parseTypeAnnotationValues(Annotated ele */ public Object getAnnotationDefaultValue(Annotated method) { Annotated root = unwrap(method, null); - return root != null ? getAnnotationDefaultValueFromRoot((ResolvedJavaMethod) root) : null; - } - - private Object getAnnotationDefaultValueFromRoot(ResolvedJavaMethod accessorMethod) { - return annotationDefaultCache.computeIfAbsent(accessorMethod, method -> { - try { - return AnnotationValueSupport.getAnnotationDefaultValue(method); - } catch (IllegalArgumentException | BufferUnderflowException | GenericSignatureFormatError e) { - return new AnnotationFormatError(e); - } catch (AnnotationFormatError e) { - return e; - } - }); + if (root == null) { + return null; + } + try { + return AnnotationValueSupport.getAnnotationDefaultValue((ResolvedJavaMethod) root); + } catch (IllegalArgumentException | BufferUnderflowException | GenericSignatureFormatError e) { + return new AnnotationFormatError(e); + } catch (AnnotationFormatError e) { + return e; + } } private static Annotated unwrap(Annotated element, List injectedAnnotationsCollector) { diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotatedWrapper.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotatedWrapper.java index b6d3bd728bb5..48f63d8e5f5e 100644 --- a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotatedWrapper.java +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotatedWrapper.java @@ -25,16 +25,18 @@ package com.oracle.svm.util; import java.util.List; +import java.util.function.Function; import jdk.graal.compiler.annotation.AnnotationValue; import jdk.vm.ci.meta.annotation.Annotated; +import jdk.vm.ci.meta.annotation.AnnotationsInfo; /** * An annotated element may have its annotations provided by multiple, layered objects that * implement this interface. A layer can optionally {@linkplain #getInjectedAnnotations() inject * annotations}. */ -public interface AnnotatedWrapper { +public interface AnnotatedWrapper extends Annotated { /** * Gets the annotated element wrapped by this wrapper. */ @@ -46,4 +48,22 @@ public interface AnnotatedWrapper { default List getInjectedAnnotations() { return List.of(); } + + /** + * Gets the class file info for the annotations from the wrapped element. + */ + @Override + default T getDeclaredAnnotationInfo(Function parser) { + Annotated wrapped = getWrappedAnnotated(); + return wrapped == null ? null : wrapped.getDeclaredAnnotationInfo(parser); + } + + /** + * Gets the class file info for the type annotations from the wrapped element. + */ + @Override + default AnnotationsInfo getTypeAnnotationInfo() { + Annotated wrapped = getWrappedAnnotated(); + return wrapped == null ? null : wrapped.getTypeAnnotationInfo(); + } } diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationUtil.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationUtil.java index 99bf317900c3..0f0446ce6937 100644 --- a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationUtil.java +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationUtil.java @@ -36,10 +36,12 @@ import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.impl.AnnotationExtractor; +import org.graalvm.nativeimage.impl.ImageSingletonsSupport; import jdk.graal.compiler.annotation.AnnotationValue; import jdk.graal.compiler.annotation.AnnotationValueType; import jdk.graal.compiler.annotation.EnumElement; +import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.util.EconomicHashMap; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.UnresolvedJavaType; @@ -59,18 +61,35 @@ public final class AnnotationUtil { @Platforms(Platform.HOSTED_ONLY.class) static class Lazy { static final AnnotatedObjectAccess instance; + static final Throwable initLocation; static { ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, AnnotatedObjectAccess.class, false, "java.base", "sun.reflect.annotation"); instance = new AnnotatedObjectAccess(); + initLocation = new Throwable("Lazy.instance created here:"); } } + /** + * Used to ensure only one path through {@link #instance()} is taken per VM execution to prevent + * leaking data via {@link Lazy#instance}. + */ + @Platforms(Platform.HOSTED_ONLY.class) // + private static Boolean instanceIsSingleton; + @Platforms(Platform.HOSTED_ONLY.class) private static AnnotatedObjectAccess instance() { - if (ImageSingletons.contains(AnnotationExtractor.class)) { + if (ImageSingletonsSupport.isInstalled() && ImageSingletons.contains(AnnotationExtractor.class)) { + if (instanceIsSingleton == null) { + instanceIsSingleton = true; + } else if (!instanceIsSingleton) { + throw new GraalError(Lazy.initLocation, "Cannot use image singleton AnnotatedObjectAccess after Lazy.instance initialized"); + } return (AnnotatedObjectAccess) ImageSingletons.lookup(AnnotationExtractor.class); } - // Fall back to singleton when outside scope of a Native Image build. + // Fall back to singleton when no AnnotationExtractor singleton is available (e.g., + // running `mx unittest com.oracle.graal.pointsto.standalone.test`). + GraalError.guarantee(instanceIsSingleton == null || !instanceIsSingleton, "Cannot use image singleton AnnotatedObjectAccess and Lazy.instance in one process"); + instanceIsSingleton = false; return Lazy.instance; } diff --git a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationsContainer.java b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationsContainer.java index 887df8946494..38e0f53aaff7 100644 --- a/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationsContainer.java +++ b/substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/AnnotationsContainer.java @@ -26,6 +26,10 @@ import java.lang.annotation.Annotation; import java.util.List; +import java.util.function.Function; + +import jdk.graal.compiler.debug.GraalError; +import jdk.vm.ci.meta.annotation.AnnotationsInfo; /** * A container for an array of annotations. @@ -43,4 +47,12 @@ public AnnotationsContainer(Annotation[] annotations) { public List getContainedAnnotations() { return annotations; } + + public T getDeclaredAnnotationInfo(Function parser) { + throw GraalError.unimplemented(this + ":" + parser); + } + + public AnnotationsInfo getTypeAnnotationInfo() { + throw GraalError.unimplemented(toString()); + } } diff --git a/vm/mx.vm/mx_vm_gate.py b/vm/mx.vm/mx_vm_gate.py index 4cbb4a44f10b..fde561a9c474 100644 --- a/vm/mx.vm/mx_vm_gate.py +++ b/vm/mx.vm/mx_vm_gate.py @@ -476,7 +476,7 @@ def _test_libgraal_truffle(extra_vm_arguments): "-Dpolyglot.engine.CompilationFailureAction=Throw", "-Djdk.graal.CompilationFailureAction=ExitVM", "-Dgraalvm.locatorDisabled=true", - "truffle", "LibGraalCompilerTest"]) + "truffle", "LibGraalCompilerTest", "TruffleHostInliningTest"]) def gate_body(args, tasks): with Task('Vm: GraalVM dist names', tasks, tags=['names']) as t: diff --git a/web-image/mx.web-image/suite.py b/web-image/mx.web-image/suite.py index 18e024c682b7..3572f3082a5c 100644 --- a/web-image/mx.web-image/suite.py +++ b/web-image/mx.web-image/suite.py @@ -105,7 +105,13 @@ "jdk.internal.misc", "jdk.internal.util", ], - "jdk.internal.vm.ci": ["jdk.vm.ci.code.site", "jdk.vm.ci.code", "jdk.vm.ci.common", "jdk.vm.ci.meta"], + "jdk.internal.vm.ci": [ + "jdk.vm.ci.code.site", + "jdk.vm.ci.code", + "jdk.vm.ci.common", + "jdk.vm.ci.meta", + "jdk.vm.ci.meta.annotation", + ], }, "javaCompliance": "21+", "spotbugs": "false", # depends on SVM which has compliance level 24 which SpotBugs does not support