From d93add9ec60313ef41298f526310c67a6c0512a7 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Mon, 8 Jul 2024 14:24:22 +0200 Subject: [PATCH 1/2] Mokapot: Pass some options directly and only to isolate creation Some options might not be accepted by SVM later (e.g., size of the heap when using G1), split them out and pass them to SVM while creating the isolate. --- .../truffle/espresso/libjavavm/Arguments.java | 73 ++------ .../espresso/libjavavm/LibEspresso.java | 18 +- .../espresso/libjavavm/jniapi/JNIVersion.java | 40 +++-- .../include/libjavavm_dynamic.h | 2 +- .../src/mokapot.c | 160 +++++++++++++++++- 5 files changed, 213 insertions(+), 80 deletions(-) diff --git a/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/Arguments.java b/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/Arguments.java index 5989d51c5d0c..ebdcc9a9d935 100644 --- a/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/Arguments.java +++ b/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/Arguments.java @@ -26,10 +26,11 @@ import java.io.File; import java.io.PrintStream; +import java.io.Serial; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; @@ -78,7 +79,7 @@ private Arguments() { private static final Map MAPPED_XX_OPTIONS = Map.of( "TieredCompilation", "engine.MultiTier"); - public static int setupContext(Context.Builder builder, JNIJavaVMInitArgs args) { + public static int setupContext(Context.Builder builder, JNIJavaVMInitArgs args, BitSet ignoredArgs) { Pointer p = (Pointer) args.getOptions(); int count = args.getNOptions(); String classpath = null; @@ -88,8 +89,7 @@ public static int setupContext(Context.Builder builder, JNIJavaVMInitArgs args) ArgumentsHandler handler = new ArgumentsHandler(builder, IGNORED_XX_OPTIONS, MAPPED_XX_OPTIONS, args); List jvmArgs = new ArrayList<>(); - boolean ignoreUnrecognized = false; - boolean autoAdjustHeapSize = true; + boolean ignoreUnrecognized = args.getIgnoreUnrecognized(); List xOptions = new ArrayList<>(); for (int i = 0; i < count; i++) { @@ -99,6 +99,10 @@ public static int setupContext(Context.Builder builder, JNIJavaVMInitArgs args) if (str.isNonNull()) { String optionString = CTypeConversion.toJavaString(option.getOptionString()); buildJvmArg(jvmArgs, optionString); + if (ignoredArgs.get(i)) { + // this argument participates in jvmArgs but should otherwise be ignored + continue; + } if (optionString.startsWith("-Xbootclasspath:")) { bootClasspathPrepend = null; bootClasspathAppend = null; @@ -128,7 +132,7 @@ public static int setupContext(Context.Builder builder, JNIJavaVMInitArgs args) builder.option(AGENT_PATH + split[0], split[1]); } else if (optionString.startsWith("-D")) { String key = optionString.substring("-D".length()); - int splitAt = key.indexOf("="); + int splitAt = key.indexOf('='); String value = ""; if (splitAt >= 0) { value = key.substring(splitAt + 1); @@ -181,10 +185,6 @@ public static int setupContext(Context.Builder builder, JNIJavaVMInitArgs args) builder.option(JAVA_PROPS + "jdk.module.limitmods", optionString.substring("--limit-modules=".length())); } else if (optionString.equals("--enable-preview")) { builder.option("java.EnablePreview", "true"); - } else if (optionString.equals("-XX:-AutoAdjustHeapSize")) { - autoAdjustHeapSize = false; - } else if (optionString.equals("-XX:+AutoAdjustHeapSize")) { - autoAdjustHeapSize = true; } else if (isXOption(optionString)) { xOptions.add(optionString); } else if (optionString.equals("-XX:+IgnoreUnrecognizedVMOptions")) { @@ -233,11 +233,7 @@ public static int setupContext(Context.Builder builder, JNIJavaVMInitArgs args) } for (String xOption : xOptions) { - var opt = xOption; - if (autoAdjustHeapSize) { - opt = maybeAdjustMaxHeapSize(xOption); - } - RuntimeOptions.set(opt.substring(2 /* drop the -X */), null); + RuntimeOptions.set(xOption.substring(2 /* drop the -X */), null); } if (bootClasspathPrepend != null) { @@ -259,45 +255,6 @@ public static int setupContext(Context.Builder builder, JNIJavaVMInitArgs args) return JNIErrors.JNI_OK(); } - private static String maybeAdjustMaxHeapSize(String optionString) { - // (Jun 2024) Espresso uses more memory than HotSpot does, so if the user has set a very - // small heap size that would work on HotSpot then we have to bump it up. 64mb is too small - // to run Gradle's wrapper program which is required to use Espresso with Gradle, so, we - // go to the next power of two beyond that. This number can be reduced in future when - // memory efficiency is better. - if (!optionString.startsWith("-Xmx")) { - return optionString; - } - long maxHeapSizeBytes = parseLong(optionString.substring(4)); - final int floorMB = 128; - if (maxHeapSizeBytes < floorMB * 1024 * 1024) { - return "-Xmx" + floorMB + "m"; - } else { - return optionString; - } - } - - private static long parseLong(String v) { - String valueString = v.trim().toLowerCase(Locale.ROOT); - long scale = 1; - if (valueString.endsWith("k")) { - scale = 1024L; - } else if (valueString.endsWith("m")) { - scale = 1024L * 1024L; - } else if (valueString.endsWith("g")) { - scale = 1024L * 1024L * 1024L; - } else if (valueString.endsWith("t")) { - scale = 1024L * 1024L * 1024L * 1024L; - } - - if (scale != 1) { - /* Remove trailing scale character. */ - valueString = valueString.substring(0, valueString.length() - 1); - } - - return Long.parseLong(valueString) * scale; - } - private static void buildJvmArg(List jvmArgs, String optionString) { for (String ignored : ignoredJvmArgs) { if (optionString.startsWith(ignored)) { @@ -321,16 +278,16 @@ private static boolean isXOption(String optionString) { } private static String appendPath(String paths, String toAppend) { - if (paths != null && paths.length() != 0) { - return toAppend != null && toAppend.length() != 0 ? paths + File.pathSeparator + toAppend : paths; + if (paths != null && !paths.isEmpty()) { + return toAppend != null && !toAppend.isEmpty() ? paths + File.pathSeparator + toAppend : paths; } else { return toAppend; } } private static String prependPath(String toPrepend, String paths) { - if (paths != null && paths.length() != 0) { - return toPrepend != null && toPrepend.length() != 0 ? toPrepend + File.pathSeparator + paths : paths; + if (paths != null && !paths.isEmpty()) { + return toPrepend != null && !toPrepend.isEmpty() ? toPrepend + File.pathSeparator + paths : paths; } else { return toPrepend; } @@ -351,7 +308,7 @@ private static String[] splitEquals(String value) { } public static class ArgumentException extends RuntimeException { - private static final long serialVersionUID = 5430103471994299046L; + @Serial private static final long serialVersionUID = 5430103471994299046L; private final boolean isExperimental; diff --git a/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/LibEspresso.java b/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/LibEspresso.java index 40affb3b8d59..57386c7d2004 100644 --- a/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/LibEspresso.java +++ b/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/LibEspresso.java @@ -23,12 +23,14 @@ package com.oracle.truffle.espresso.libjavavm; import java.io.PrintStream; +import java.util.BitSet; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.ObjectHandle; import org.graalvm.nativeimage.ObjectHandles; import org.graalvm.nativeimage.VMRuntime; import org.graalvm.nativeimage.c.function.CEntryPoint; +import org.graalvm.nativeimage.c.type.CIntPointer; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.PolyglotException; import org.graalvm.polyglot.Value; @@ -48,12 +50,20 @@ public final class LibEspresso { private LibEspresso() { } + private static BitSet asBitSet(CIntPointer ignoredIndices, int nIgnoredIndices) { + BitSet result = new BitSet(); + for (int i = 0; i < nIgnoredIndices; i++) { + result.set(ignoredIndices.read(i)); + } + return result; + } + @CEntryPoint(name = "Espresso_CreateJavaVM") - static int createJavaVM(@SuppressWarnings("unused") IsolateThread thread, JNIJavaVMPointer javaVMPointer, JNIEnvironmentPointer penv, JNIJavaVMInitArgs args) { - if (args.getVersion() < JNIVersion.JNI_VERSION_1_2() || args.getVersion() > JNIVersion.JNI_VERSION_10) { + static int createJavaVM(@SuppressWarnings("unused") IsolateThread thread, JNIJavaVMPointer javaVMPointer, JNIEnvironmentPointer penv, JNIJavaVMInitArgs args, CIntPointer ignoredIndices, + int nIgnoredIndices) { + if (args.getVersion() < JNIVersion.JNI_VERSION_1_2() || args.getVersion() > JNIVersion.JNI_VERSION_21()) { return JNIErrors.JNI_EVERSION(); } - // TODO use Launcher infra to parse graalvm specific options Context.Builder builder = Context.newBuilder().allowAllAccess(true); // These option need to be set before calling `Arguments.setupContext()` so that cmd line @@ -63,7 +73,7 @@ static int createJavaVM(@SuppressWarnings("unused") IsolateThread thread, JNIJav // checks and can use unsafe casts. builder.option("engine.RelaxStaticObjectSafetyChecks", "true"); - int result = Arguments.setupContext(builder, args); + int result = Arguments.setupContext(builder, args, asBitSet(ignoredIndices, nIgnoredIndices)); if (result != JNIErrors.JNI_OK()) { return result; } diff --git a/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/jniapi/JNIVersion.java b/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/jniapi/JNIVersion.java index 4fd008be8c61..c8eab6e361cf 100644 --- a/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/jniapi/JNIVersion.java +++ b/espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/jniapi/JNIVersion.java @@ -44,14 +44,20 @@ public class JNIVersion { @CConstant public static native int JNI_VERSION_1_8(); - // Unfortunately those are not always available and "default" values are not supported - // @CConstant - // public static native int JNI_VERSION_9(); - public static int JNI_VERSION_9 = 0x00090000; + @CConstant + public static native int JNI_VERSION_9(); + + @CConstant + public static native int JNI_VERSION_10(); + + @CConstant + public static native int JNI_VERSION_19(); + + @CConstant + public static native int JNI_VERSION_20(); - // @CConstant - // public static native int JNI_VERSION_10(); - public static int JNI_VERSION_10 = 0x000A0000; + @CConstant + public static native int JNI_VERSION_21(); // Checkstyle: resume @@ -66,10 +72,16 @@ public static String versionString(int version) { return "1.6"; } else if (version == JNI_VERSION_1_8()) { return "1.8"; - } else if (version == JNI_VERSION_9) { + } else if (version == JNI_VERSION_9()) { return "9"; - } else if (version == JNI_VERSION_10) { + } else if (version == JNI_VERSION_10()) { return "10"; + } else if (version == JNI_VERSION_19()) { + return "19"; + } else if (version == JNI_VERSION_20()) { + return "20"; + } else if (version == JNI_VERSION_21()) { + return "21"; } return "unknown"; } @@ -85,10 +97,16 @@ public static int javaSpecVersion(int version) { return 6; } else if (version == JNI_VERSION_1_8()) { return 8; - } else if (version == JNI_VERSION_9) { + } else if (version == JNI_VERSION_9()) { return 9; - } else if (version == JNI_VERSION_10) { + } else if (version == JNI_VERSION_10()) { return 10; + } else if (version == JNI_VERSION_19()) { + return 19; + } else if (version == JNI_VERSION_20()) { + return 20; + } else if (version == JNI_VERSION_21()) { + return 21; } return -1; } diff --git a/espresso/src/com.oracle.truffle.espresso.mokapot/include/libjavavm_dynamic.h b/espresso/src/com.oracle.truffle.espresso.mokapot/include/libjavavm_dynamic.h index 237497905dd8..c48e7dff8356 100644 --- a/espresso/src/com.oracle.truffle.espresso.mokapot/include/libjavavm_dynamic.h +++ b/espresso/src/com.oracle.truffle.espresso.mokapot/include/libjavavm_dynamic.h @@ -30,7 +30,7 @@ extern "C" { #endif -typedef int (*Espresso_CreateJavaVM_fn_t)(graal_isolatethread_t* thread, struct JavaVM_** javaVMPointer, struct JNIEnv_** penv, JavaVMInitArgs* args); +typedef int (*Espresso_CreateJavaVM_fn_t)(graal_isolatethread_t* thread, struct JavaVM_** javaVMPointer, struct JNIEnv_** penv, JavaVMInitArgs* args, int* ignoredIndices, int nIgnoredIndices); typedef int (*Espresso_EnterContext_fn_t)(graal_isolatethread_t* thread, struct JavaVM_* javaVM); diff --git a/espresso/src/com.oracle.truffle.espresso.mokapot/src/mokapot.c b/espresso/src/com.oracle.truffle.espresso.mokapot/src/mokapot.c index 303d0573881e..b09110ac6bd0 100644 --- a/espresso/src/com.oracle.truffle.espresso.mokapot/src/mokapot.c +++ b/espresso/src/com.oracle.truffle.espresso.mokapot/src/mokapot.c @@ -32,6 +32,7 @@ #include #include #include +#include OS_THREAD_LOCAL MokapotEnv* tls_moka_env = NULL; @@ -952,7 +953,6 @@ JNIEXPORT jint JNICALL JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cb, jin JNIEXPORT void JNICALL JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cb, jint method_index, jint entry_index, JVM_ExceptionTableEntryType *entry) { UNIMPLEMENTED(JVM_GetMethodIxExceptionTableEntry); - } JNIEXPORT jint JNICALL JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cb, int index) { @@ -1999,12 +1999,139 @@ jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args) { return AttachCurrentThread_helper(vm, penv, args, (*espressoJavaVM)->AttachCurrentThreadAsDaemon); } +static int option_starts_with(const char *start, const JavaVMOption *option) { + return strncmp(start, option->optionString, strlen(start)) == 0; +} + +static jboolean multiply_by_1k(unsigned long long int *n) { + if (*n <= ULLONG_MAX / 1024) { + *n *= 1024; + return JNI_TRUE; + } else { + return JNI_FALSE; + } +} + +static unsigned long long int parse_long_size(const char *str) { + size_t len = strlen(str); + if (len == 0 || !isdigit(str[0])) { + return 0; + } + unsigned long long int result; + char *end; + const char *start = str; + errno = 0; + if (len > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { + // hex + start = str + 2; + result = strtoull(start, &end, 16); + } else { + // dec + result = strtoull(start, &end, 10); + } + if (errno != 0 || start == end) { + return 0; + } + switch (*end) { + case 't': + case 'T': + if (multiply_by_1k(&result) != JNI_TRUE) { + return 0; + } + case 'g': + case 'G': + if (multiply_by_1k(&result) != JNI_TRUE) { + return 0; + } + case 'm': + case 'M': + if (multiply_by_1k(&result) != JNI_TRUE) { + return 0; + } + case 'k': + case 'K': + if (multiply_by_1k(&result) != JNI_TRUE) { + return 0; + } + end += 1; + break; + } + if (*end != '\0') { + return 0; + } + return result; +} + +static char *maybe_adjust_max_heap_size(char *option_str, size_t size_offset, jboolean auto_adjust_heap_size) { + if (auto_adjust_heap_size != JNI_TRUE) { + return option_str; + } + unsigned long long int sz = parse_long_size(option_str + size_offset); + if (sz != 0 && sz < 128ULL * 1024 * 1024) { + printf("Adjusting max heap size of %llu to -Xmx128m", sz); + return "-Xmx128m"; + } else { + return option_str; + } +} + +static jint process_isolate_args(JavaVMInitArgs *initArgs, int *isolate_argc, char ***isolate_argv, int *n_ignored_indices, int **ignored_indices) { + // Pull out arguments that need to be handled by isolate creation in SVM and can't be set correctly later + // Mark those as ignored so that Espresso_CreateJavaVM knows not to act on them + // but still uses them to compose the jvm args as seen by management APIs + + jboolean auto_adjust_heap_size = JNI_TRUE; + for (int i = 0; i < initArgs->nOptions; i++) { + const JavaVMOption *option = initArgs->options + i; + char *optionString = NULL; + if (strcmp("-XX:+AutoAdjustHeapSize", option->optionString) == 0) { + auto_adjust_heap_size = JNI_TRUE; + } else if (strcmp("-XX:-AutoAdjustHeapSize", option->optionString) == 0) { + auto_adjust_heap_size = JNI_FALSE; + } else if (option_starts_with("-Xms", option) || + option_starts_with("-XX:MinHeapSize=", option) || + option_starts_with("-Xmn", option) || + option_starts_with("-XX:MaxNewSize=", option) || + option_starts_with("-XX:ReservedAddressSpaceSize=", option) || + option_starts_with("-XX:MaxRAM=", option) || + strcmp("-XX:+ExitOnOutOfMemoryError", option->optionString) == 0 || + strcmp("-XX:-ExitOnOutOfMemoryError", option->optionString) == 0) { + optionString = option->optionString; + } else if (option_starts_with("-Xmx", option)) { + optionString = maybe_adjust_max_heap_size(option->optionString, strlen("-Xmx"), auto_adjust_heap_size); + } else if (option_starts_with("-XX:MaxHeapSize=", option)) { + optionString = maybe_adjust_max_heap_size(option->optionString, strlen("-XX:MaxHeapSize="), auto_adjust_heap_size); + } else { + continue; + } + if (*ignored_indices == NULL) { + *ignored_indices = malloc(sizeof(int) * initArgs->nOptions); + if (*ignored_indices == NULL) { + return JNI_ENOMEM; + } + } + (*ignored_indices)[(*n_ignored_indices)++] = i; + if (optionString != NULL) { + if (*isolate_argv == NULL) { + *isolate_argv = malloc(sizeof(char *) * initArgs->nOptions); + if (*isolate_argv == NULL) { + return JNI_ENOMEM; + } + // initial argument that is usually the executable name is ignored + (*isolate_argv)[(*isolate_argc)++] = NULL; + } + (*isolate_argv)[(*isolate_argc)++] = optionString; + } + } + return JNI_OK; +} + _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm_ptr, void **penv, void *args) { JavaVMInitArgs *initArgs = args; int lib_javavm_type = LIB_JAVAVM_PLAIN; jboolean is_sun_standard_launcher = JNI_FALSE; for (int i = 0; i < initArgs->nOptions; i++) { - const JavaVMOption* option = initArgs->options + i; + const JavaVMOption *option = initArgs->options + i; if (strcmp("--polyglot", option->optionString) == 0) { lib_javavm_type = LIB_JAVAVM_POLYGLOT; } else if (strcmp("-Dsun.java.launcher=SUN_STANDARD", option->optionString) == 0) { @@ -2017,16 +2144,37 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm_ptr, void **pen } graal_isolate_t *isolate; graal_isolatethread_t *thread; - graal_create_isolate_params_t params; - params.version = 0; - params.reserved_address_space_size = 0; + graal_create_isolate_params_t params = {0}; + + int isolate_argc = 0; + char **isolate_argv = NULL; + int n_ignored_indices = 0; + int *ignored_indices = NULL; + int ret = process_isolate_args(initArgs, &isolate_argc, &isolate_argv, &n_ignored_indices, &ignored_indices); + if (ret != JNI_OK) { + if (isolate_argv != NULL) free(isolate_argv); + if (ignored_indices != NULL) free(ignored_indices); + return ret; + } + + params.version = 4; + char ignore_unrecognized_arguments = initArgs->ignoreUnrecognized == JNI_TRUE ? 1 : 0; + char exit_on_arg_parse_fail = 0; + params._reserved_1 = isolate_argc; + params._reserved_2 = isolate_argv; + params._reserved_3 = ignore_unrecognized_arguments; + params._reserved_4 = exit_on_arg_parse_fail; if (libjavavm->create_isolate(¶ms, &isolate, &thread) != 0) { + if (isolate_argv != NULL) free(isolate_argv); + if (ignored_indices != NULL) free(ignored_indices); return JNI_ERR; } struct JavaVM_ *espressoJavaVM; struct JNIEnv_ *espressoJNIEnv; - int ret = libjavavm->Espresso_CreateJavaVM(thread, &espressoJavaVM, &espressoJNIEnv, initArgs); + ret = libjavavm->Espresso_CreateJavaVM(thread, &espressoJavaVM, &espressoJNIEnv, initArgs, ignored_indices, n_ignored_indices); + if (isolate_argv != NULL) free(isolate_argv); + if (ignored_indices != NULL) free(ignored_indices); if (ret != JNI_OK) { libjavavm->detach_all_threads_and_tear_down_isolate(thread); return ret; From b77b19536fd9dbc22cbeb5dd8a35ae09e0417b84 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Tue, 13 Aug 2024 11:23:55 +0200 Subject: [PATCH 2/2] Remove unused file --- .../runtime/EspressoRuntimeResources.java | 53 ------------------- 1 file changed, 53 deletions(-) delete mode 100644 espresso/src/com.oracle.truffle.espresso.resources.runtime/src/com/oracle/truffle/espresso/resources/runtime/EspressoRuntimeResources.java diff --git a/espresso/src/com.oracle.truffle.espresso.resources.runtime/src/com/oracle/truffle/espresso/resources/runtime/EspressoRuntimeResources.java b/espresso/src/com.oracle.truffle.espresso.resources.runtime/src/com/oracle/truffle/espresso/resources/runtime/EspressoRuntimeResources.java deleted file mode 100644 index 48bd2b7c2acf..000000000000 --- a/espresso/src/com.oracle.truffle.espresso.resources.runtime/src/com/oracle/truffle/espresso/resources/runtime/EspressoRuntimeResources.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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.truffle.espresso.resources.runtime; - -import java.io.IOException; -import java.nio.file.Path; - -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.InternalResource; - -@InternalResource.Id(value = "espresso-runtime", componentId = "java", optional = true) -public final class EspressoRuntimeResources implements InternalResource { - - private static Path basePath(Env env) { - return Path.of("META-INF", "resources", "java", "espresso-runtime", env.getOS().toString(), env.getCPUArchitecture().toString()); - } - - @Override - public void unpackFiles(Env env, Path targetDirectory) throws IOException { - Path base = basePath(env); - env.unpackResourceFiles(base.resolve("files"), targetDirectory, base); - } - - @Override - public String versionHash(Env env) { - try { - Path hashResource = basePath(env).resolve("sha256"); - return env.readResourceLines(hashResource).get(0); - } catch (IOException ioe) { - throw CompilerDirectives.shouldNotReachHere(ioe); - } - } -}