From 3fa204b3df5d1050abd78dc14deef67be36bb629 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 18 Jan 2024 13:39:46 +0100 Subject: [PATCH 1/6] svm: add @BasedOnJDKFile annotation and processor --- .../compiler/processor/AbstractProcessor.java | 2 +- substratevm/mx.substratevm/suite.py | 3 +- .../oracle/svm/core/util/BasedOnJDKFile.java | 69 +++++ .../javax.annotation.processing.Processor | 1 + .../processor/BasedOnJDKFileProcessor.java | 250 ++++++++++++++++++ 5 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKFile.java create mode 100644 substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/BasedOnJDKFileProcessor.java diff --git a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/processor/AbstractProcessor.java b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/processor/AbstractProcessor.java index 030c98250fc3..02f3192b2d29 100644 --- a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/processor/AbstractProcessor.java +++ b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/processor/AbstractProcessor.java @@ -342,7 +342,7 @@ public void createProviderFile(String providerClassName, String serviceClassName * Determines if a given exception is (most likely) caused by * Bug 367599. */ - private static boolean isBug367599(Throwable t) { + protected static boolean isBug367599(Throwable t) { if (t instanceof FilerException) { for (StackTraceElement ste : t.getStackTrace()) { if (ste.toString().contains("org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeFilerImpl.create")) { diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index c5968c40f9d7..b391bccfaa88 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -251,7 +251,8 @@ "compiler:GRAAL_PROCESSOR" ], "requires" : [ - "java.compiler" # javax.annotation.processing.* + "java.compiler", # javax.annotation.processing.* + "jdk.compiler", # com.sun.source.util.* ], "javaCompliance" : "21+", "checkstyle" : "com.oracle.svm.core", diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKFile.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKFile.java new file mode 100644 index 000000000000..c428734cdad7 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKFile.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +/** + * Documents that the element is based on a JDK source file. This is mainly useful for non-Java + * sources like C++ files. For Java classes, {@link BasedOnJDKClass} might be more appropriate. + */ +@Repeatable(BasedOnJDKFile.List.class) +@Retention(RetentionPolicy.RUNTIME) +@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD}) +@Platforms(Platform.HOSTED_ONLY.class) +public @interface BasedOnJDKFile { + + /** + * Path to the source file relative to the repository root (usually + * openjdk). The path elements must be separated by + * slashes ({@code /}) and since it is a relative path, it must not start with a slash. + * + * To specify a line range, a suffix of the form {@code #L[0-9]+-L[0-9]+} might be added. Full + * example: + * + *
+     *     @BasedOnJDKFile("src/hotspot/cpu/x86/vm_version_x86.hpp#L40-L304")
+     * 
+ */ + String value(); + + /** + * Support for making {@link BasedOnJDKFile} {@linkplain Repeatable repeatable}. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD}) + @Platforms(Platform.HOSTED_ONLY.class) + @interface List { + BasedOnJDKFile[] value(); + } +} diff --git a/substratevm/src/com.oracle.svm.processor/src/META-INF/services/javax.annotation.processing.Processor b/substratevm/src/com.oracle.svm.processor/src/META-INF/services/javax.annotation.processing.Processor index 43e591af1f6c..337184082127 100644 --- a/substratevm/src/com.oracle.svm.processor/src/META-INF/services/javax.annotation.processing.Processor +++ b/substratevm/src/com.oracle.svm.processor/src/META-INF/services/javax.annotation.processing.Processor @@ -1,2 +1,3 @@ com.oracle.svm.processor.AutomaticallyRegisteredFeatureProcessor com.oracle.svm.processor.AutomaticallyRegisteredImageSingletonProcessor +com.oracle.svm.processor.BasedOnJDKFileProcessor diff --git a/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/BasedOnJDKFileProcessor.java b/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/BasedOnJDKFileProcessor.java new file mode 100644 index 000000000000..4a1a612c8916 --- /dev/null +++ b/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/BasedOnJDKFileProcessor.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2024, 2024, 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.processor; + +// Checkstyle: allow Class.getSimpleName + +import static javax.tools.Diagnostic.Kind.ERROR; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.tools.Diagnostic.Kind; +import javax.tools.FileObject; +import javax.tools.StandardLocation; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.LineMap; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TreePath; +import com.sun.source.util.Trees; + +import jdk.graal.compiler.processor.AbstractProcessor; + +/** + * This processor visits {@code @BasedOnJDKFile} annotated elements, collect information from the + * annotation and the annotated element and writes the result as a JSON file to + * {@link StandardLocation#SOURCE_OUTPUT} for further processing. See {@link #processAnnotation} for + * the details. + */ +@SupportedAnnotationTypes({BasedOnJDKFileProcessor.ANNOTATION_CLASS_NAME, BasedOnJDKFileProcessor.ANNOTATION_LIST_CLASS_NAME}) +public class BasedOnJDKFileProcessor extends AbstractProcessor { + + static final String ANNOTATION_CLASS_NAME = "com.oracle.svm.core.util.BasedOnJDKFile"; + static final String ANNOTATION_LIST_CLASS_NAME = "com.oracle.svm.core.util.BasedOnJDKFile.List"; + static final Pattern FILE_PATTERN = Pattern.compile("^(?[-_.A-Za-z0-9][-_./A-Za-z0-9]*)(#L(?[0-9]+)-L(?[0-9]+))?$"); + static final String FILE_PATTERN_STR = "path/to/file.ext(#L[0-9]+-L[0-9]+)?"; + public static final int FULL_FILE_LINE_MARKER = 0; + + private final Set processed = new HashSet<>(); + private Trees trees; + private boolean isECJ = false; + + @Override + public synchronized void init(ProcessingEnvironment pe) { + super.init(pe); + try { + this.trees = Trees.instance(pe); + this.isECJ = false; + } catch (IllegalArgumentException e) { + // probably compiling with ECJ + this.isECJ = true; + } + } + + @SuppressWarnings("unchecked") + private List getAnnotationValues(Element element, TypeElement listTypeElement) { + AnnotationMirror listMirror = getAnnotation(element, listTypeElement.asType()); + return getAnnotationValue(listMirror, "value", List.class); + } + + record SourceInfo(String path, long lineStart, long lineEnd) { + } + + public static String quoteString(String s) { + if (s == null) { + return "null"; + } + StringBuilder sb = new StringBuilder(2 + s.length() + 8 /* room for escaping */); + sb.append('"'); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '"' || c == '\\') { + sb.append('\\'); + sb.append(c); + } else if (c < 0x001F) { + sb.append(String.format("\\u%04x", (int) c)); + } else { + sb.append(c); + } + } + sb.append('"'); + return sb.toString(); + } + + private void processAnnotation(Element annotatedElement, AnnotationMirror annotationMirror) { + String annotationValue = Objects.requireNonNull(getAnnotationValue(annotationMirror, "value", String.class)); + SourceInfo targetSourceInfo = parseBasedOnJDKFileAnnotation(annotationValue); + if (targetSourceInfo == null) { + // error parsing the annotation + return; + } + + String qualifiedName = getQualifiedName(annotatedElement); + + Element[] originatingElements = new Element[]{annotatedElement}; + String uniqueName = getUniqueName(qualifiedName, targetSourceInfo.path, targetSourceInfo.lineStart, targetSourceInfo.lineEnd); + + String filename = "jdk_source_info/" + URLEncoder.encode(uniqueName, StandardCharsets.UTF_8) + ".json"; + SourceInfo annotatedSourceInfo = getAnnotatedSourceInfo(annotatedElement); + try { + FileObject file = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", filename, originatingElements); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8")); + writer.println("{"); + writer.println(" \"annotatedElement\": {"); + writer.println(" \"qualifiedName\": " + quoteString(qualifiedName) + ","); + writer.println(" \"annotationValue\": " + quoteString(annotationValue) + ","); + writer.println(" \"uniqueName\": " + quoteString(uniqueName) + ","); + printSourceInfo(writer, annotatedSourceInfo, " "); + writer.println(); + writer.println(" },"); + writer.println(" \"target\": {"); + printSourceInfo(writer, targetSourceInfo, " "); + writer.println(); + writer.println(" }"); + writer.println("}"); + writer.close(); + } catch (IOException e) { + processingEnv.getMessager().printMessage(isBug367599(e) ? Kind.NOTE : ERROR, e.getMessage(), originatingElements[0]); + } + } + + private static String getQualifiedName(Element annotatedElement) { + if (annotatedElement instanceof TypeElement typeElement) { + return typeElement.getQualifiedName().toString(); + } + if (annotatedElement instanceof ExecutableElement executableElement) { + TypeElement enclosingElement = (TypeElement) executableElement.getEnclosingElement(); + return enclosingElement.getQualifiedName().toString() + "#" + executableElement.getSimpleName(); + } + if (annotatedElement instanceof VariableElement variableElement) { + TypeElement enclosingElement = (TypeElement) variableElement.getEnclosingElement(); + return enclosingElement.getQualifiedName().toString() + "#" + variableElement.getSimpleName(); + } + throw new RuntimeException("Unexpected element class: " + annotatedElement.getClass().getSimpleName()); + } + + private SourceInfo parseBasedOnJDKFileAnnotation(String annotationValue) { + Matcher matcher = FILE_PATTERN.matcher(annotationValue); + if (!matcher.matches()) { + env().getMessager().printMessage(ERROR, String.format("Invalid path: %s%nShould be %s", annotationValue, FILE_PATTERN_STR)); + return null; + } + String lineStart = matcher.group("lineStart"); + String lineEnd = matcher.group("lineEnd"); + return new SourceInfo(matcher.group("path"), lineStart == null ? FULL_FILE_LINE_MARKER : Long.parseLong(lineStart), lineEnd == null ? FULL_FILE_LINE_MARKER : Long.parseLong(lineEnd)); + } + + private SourceInfo getAnnotatedSourceInfo(Element annotatedElement) { + TreePath tp = this.trees.getPath(annotatedElement); + CompilationUnitTree cut = tp.getCompilationUnit(); + LineMap lineMap = cut.getLineMap(); + + String sourceFileName = cut.getSourceFile().getName(); + + SourcePositions sp = trees.getSourcePositions(); + long start = sp.getStartPosition(cut, tp.getLeaf()); + long end = sp.getEndPosition(cut, tp.getLeaf()); + + return new SourceInfo(sourceFileName, lineMap.getLineNumber(start), lineMap.getLineNumber(end)); + } + + private static String getUniqueName(String qualifiedName, String path, long lineStart, long lineEnd) { + return String.format("%s/%s-%s/%s", path, lineStart, lineEnd, qualifiedName); + } + + private static void printSourceInfo(PrintWriter writer, SourceInfo annotatedSourceInfo, String indent) { + writer.println(indent + "\"sourceInfo\": {"); + writer.println(indent + " \"path\": " + quoteString(annotatedSourceInfo.path) + ","); + writer.println(indent + " \"lineStart\": " + annotatedSourceInfo.lineStart + ","); + writer.println(indent + " \"lineEnd\": " + annotatedSourceInfo.lineEnd); + writer.print(indent + "}"); + } + + @Override + public boolean doProcess(Set annotations, RoundEnvironment roundEnv) { + if (isECJ) { + // ECJ is not supported + return true; + } + if (roundEnv.processingOver()) { + return true; + } + + // handle single annotations + TypeElement annotationType = getTypeElement(ANNOTATION_CLASS_NAME); + for (var element : roundEnv.getElementsAnnotatedWith(annotationType)) { + assert element.getKind().isClass() : "Only classes supported for now: " + element; + if (processed.add(element)) { + AnnotationMirror annotationMirror = getAnnotation(element, annotationType.asType()); + processAnnotation(element, annotationMirror); + } + } + + // handle repeated annotations + TypeElement annotationListType = getTypeElement(ANNOTATION_LIST_CLASS_NAME); + for (var element : roundEnv.getElementsAnnotatedWith(annotationListType)) { + assert element.getKind().isClass() : "Only classes supported for now: " + element; + if (processed.add(element)) { + List list = getAnnotationValues(element, annotationListType); + if (list != null) { + for (var annotationValue : list) { + AnnotationMirror mirror = (AnnotationMirror) annotationValue.getValue(); + processAnnotation(element, mirror); + } + } + } + } + return true; + } +} From de986e3b84521b8950387c41d201c8eacda23b27 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 15 Feb 2024 11:19:12 +0100 Subject: [PATCH 2/6] svm: annotate WindowsUtils with @BasedOnJDKFile --- .../src/com/oracle/svm/core/windows/WindowsUtils.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsUtils.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsUtils.java index 382e23b8bd4b..c0808ed094dd 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsUtils.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsUtils.java @@ -29,6 +29,7 @@ import java.io.FileDescriptor; import java.io.IOException; +import com.oracle.svm.core.util.BasedOnJDKFile; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.function.CFunctionPointer; import org.graalvm.nativeimage.c.struct.CPointerTo; @@ -170,6 +171,8 @@ static void writeBytes(FileDescriptor descriptor, byte[] bytes, int off, int len /** Retrieve a nanosecond counter for elapsed time measurement. */ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + @BasedOnJDKFile("src/hotspot/os/windows/os_windows.cpp#L970-L977") + @BasedOnJDKFile("src/hotspot/os/windows/os_windows.cpp#L1075-L1081") public static long getNanoCounter() { if (performanceFrequency == 0L) { CLongPointer count = StackValue.get(CLongPointer.class); From 097fdc5968454c4115d74ea311b6c28ef185028a Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 15 Feb 2024 11:19:28 +0100 Subject: [PATCH 3/6] svm: annotate AMD64LibCHelper with @BasedOnJDKFile --- .../src/com/oracle/svm/core/amd64/AMD64LibCHelper.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64LibCHelper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64LibCHelper.java index 40e66a67c958..57ffaa3a92ee 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64LibCHelper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64LibCHelper.java @@ -36,17 +36,14 @@ import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.word.PointerBase; -import jdk.graal.compiler.lir.SyncPort; +import com.oracle.svm.core.util.BasedOnJDKFile; -// @formatter:off -@SyncPort(from = "https://github.com/openjdk/jdk/blob/34f85ee94e8b45bcebbf8ba52a38c92a7185b54a/src/hotspot/cpu/x86/vm_version_x86.hpp#L40-L304", - sha1 = "5cc04c08555379223cc02a15774159076d3cdf1d") /* * To be kept in sync with: * - substratevm/src/com.oracle.svm.native.libchelper/include/amd64hotspotcpuinfo.h * - substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c */ -// @formatter:on +@BasedOnJDKFile("src/hotspot/cpu/x86/vm_version_x86.hpp#L40-L304") @CLibrary(value = "libchelper", requireStatic = true) public class AMD64LibCHelper { @Platforms(Platform.AMD64.class) From bc29ce438693cb767ec0dbc2d6fb6db8cce9e3ed Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 15 Feb 2024 11:19:45 +0100 Subject: [PATCH 4/6] svm: annotate JNIVersionJDKLatest with @BasedOnJDKFile --- .../com/oracle/svm/core/jni/headers/JNIVersionJDKLatest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNIVersionJDKLatest.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNIVersionJDKLatest.java index fa03c24a386c..4541ea6b907f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNIVersionJDKLatest.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNIVersionJDKLatest.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.jni.headers; +import com.oracle.svm.core.util.BasedOnJDKFile; import org.graalvm.nativeimage.c.CContext; import org.graalvm.nativeimage.c.constant.CConstant; @@ -46,6 +47,7 @@ public final class JNIVersionJDKLatest { * gets available, the "value" property of the CConstant annotation below must be removed. */ @CConstant(value = "JNI_VERSION_21") + @BasedOnJDKFile("src/java.base/share/native/include/jni.h#L1985-L1996") public static native int JNI_VERSION_LATEST(); // Checkstyle: resume From 0f45c8e864f884cc01a7b126a814a8cb6608f3fe Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Fri, 16 Feb 2024 07:53:32 +0000 Subject: [PATCH 5/6] svm: make BasedOnJDKFileProcessor#quoteString private --- .../src/com/oracle/svm/processor/BasedOnJDKFileProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/BasedOnJDKFileProcessor.java b/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/BasedOnJDKFileProcessor.java index 4a1a612c8916..68ddb01cc379 100644 --- a/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/BasedOnJDKFileProcessor.java +++ b/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/BasedOnJDKFileProcessor.java @@ -101,7 +101,7 @@ private List getAnnotationValues(Element element, Typ record SourceInfo(String path, long lineStart, long lineEnd) { } - public static String quoteString(String s) { + private static String quoteString(String s) { if (s == null) { return "null"; } From 1fddbfeddd02396e5fce9371c7e5a9f710574ee6 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 16 Feb 2024 09:10:06 +0100 Subject: [PATCH 6/6] svm: mention JDK latest in the Javadoc of BasedOnJDKFile#value --- .../src/com/oracle/svm/core/util/BasedOnJDKFile.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKFile.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKFile.java index c428734cdad7..d9da52e08b74 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKFile.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKFile.java @@ -54,6 +54,17 @@ *
      *     @BasedOnJDKFile("src/hotspot/cpu/x86/vm_version_x86.hpp#L40-L304")
      * 
+ * + * The path and line numbers always apply to the latest supported JDK version. That version can + * be retrieved from the {@code jdks.oraclejdk-latest} entry from {@code common.json} in the + * root of this repository, or by looking up the latest version in the + * {@code JVMCI_MIN_VERSIONS} map in {@link jdk.graal.compiler.hotspot.JVMCIVersionCheck}. At + * the time of writing this is {@code jdk-23+8} (formatted as a git tag as used by the openjdk). + * That information can also be used to view the respective line range on GitHub via + * {@code https://github.com/openjdk/jdk/blob//}. For the example above, it + * would translate to + * {@code https://github.com/openjdk/jdk/blob/jdk-23+8/src/hotspot/cpu/x86/vm_version_x86.hpp#L40-L304} */ String value();