From 2756241f1d738df9848f63b857806a97b630fc52 Mon Sep 17 00:00:00 2001 From: Bernhard Urban-Forster Date: Mon, 19 Aug 2024 10:49:25 +0200 Subject: [PATCH 1/8] feat(core) EspressoVM compatibility `reserved0` is used by EspressoVM, thus it cannot serve as a "reference NULL" as on HotSpot: https://github.com/oracle/graal/blob/3149f62458029ffe92b8dcefe0b3e59612684cfa/espresso/src/com.oracle.truffle.espresso.mokapot/include/mokapot.h#L67-L73 The relevant config is `MOKA_LATTE`. `reserved3` is `NULL` though. --- .../org/lwjgl/system/ThreadLocalUtil.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java index 65d7666d50..ec3f43048d 100644 --- a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java +++ b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java @@ -90,6 +90,14 @@ be easy to workaround (attaching the agent at startup, making sure no contexts a /** The global JNIEnv. */ private static final long JNI_NATIVE_INTERFACE = memGetAddress(getThreadJNIEnv()); + /** The offset in JNIEnv at which to store the pointer to the capabilities array. */ + private static final int CAPABILITIES_OFFSET = 3 * POINTER_SIZE; + + // OpenJDK: NULL + // EspressoVM: NULL + // GraalVM Native Image: pointer to UnimplementedWithJNIEnvArgument function (see #875) + private static long RESERVED3_NULL = memGetAddress(JNI_NATIVE_INTERFACE + CAPABILITIES_OFFSET); + /** The number of pointers in the JNIEnv struct. */ private static final int JNI_NATIVE_INTERFACE_FUNCTION_COUNT; @@ -103,9 +111,6 @@ be easy to workaround (attaching the agent at startup, making sure no contexts a */ private static long FUNCTION_MISSING_ABORT_TABLE = NULL; - /** The offset in JNIEnv at which to store the pointer to the capabilities array. */ - private static final int CAPABILITIES_OFFSET = 3 * POINTER_SIZE; - static { int JNI_VERSION = GetVersion(); @@ -184,21 +189,17 @@ public static void setCapabilities(long capabilities) { // Ensures FUNCTION_MISSING_ABORT will be called even if no context is current, public static void setFunctionMissingAddresses(int functionCount) { - // OpenJDK: NULL - // GraalVM Native Image: pointer to UnimplementedWithJNIEnvArgument function (see #875) - long RESERVED0_NULL = memGetAddress(JNI_NATIVE_INTERFACE); - long ptr = JNI_NATIVE_INTERFACE + CAPABILITIES_OFFSET; long currentTable = memGetAddress(ptr); if (functionCount == 0) { - if (currentTable != RESERVED0_NULL) { + if (currentTable != RESERVED3_NULL) { FUNCTION_MISSING_ABORT_TABLE = NULL; getAllocator().free(currentTable); memPutAddress(ptr, NULL); } } else { - if (currentTable != RESERVED0_NULL) { + if (currentTable != RESERVED3_NULL) { throw new IllegalStateException("setFunctionMissingAddresses has been called already"); } if (currentTable != NULL) { @@ -233,4 +234,4 @@ public static boolean areCapabilitiesDifferent(PointerBuffer ref, PointerBuffer return false; } -} \ No newline at end of file +} From 9c78f5adfbc0c04c9b58b4f3ff0259fbe817952a Mon Sep 17 00:00:00 2001 From: Bernhard Urban-Forster Date: Mon, 19 Aug 2024 13:40:21 +0200 Subject: [PATCH 2/8] compare against RESERVED0 for native image --- .../java/org/lwjgl/system/ThreadLocalUtil.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java index ec3f43048d..c70551ceab 100644 --- a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java +++ b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java @@ -93,11 +93,6 @@ be easy to workaround (attaching the agent at startup, making sure no contexts a /** The offset in JNIEnv at which to store the pointer to the capabilities array. */ private static final int CAPABILITIES_OFFSET = 3 * POINTER_SIZE; - // OpenJDK: NULL - // EspressoVM: NULL - // GraalVM Native Image: pointer to UnimplementedWithJNIEnvArgument function (see #875) - private static long RESERVED3_NULL = memGetAddress(JNI_NATIVE_INTERFACE + CAPABILITIES_OFFSET); - /** The number of pointers in the JNIEnv struct. */ private static final int JNI_NATIVE_INTERFACE_FUNCTION_COUNT; @@ -199,7 +194,15 @@ public static void setFunctionMissingAddresses(int functionCount) { memPutAddress(ptr, NULL); } } else { - if (currentTable != RESERVED3_NULL) { + // OpenJDK: NULL + // EspressoVM: NULL + // GraalVM Native Image: pointer to UnimplementedWithJNIEnvArgument function (see #875) + long RESERVED0_NULL = memGetAddress(JNI_NATIVE_INTERFACE); + + boolean slotAvailable = currentTable == NULL; // on HotSpot or Espresso + slotAvailable |= currentTable == RESERVED0_NULL; // on Native Image + + if (!slotAvailable) { throw new IllegalStateException("setFunctionMissingAddresses has been called already"); } if (currentTable != NULL) { From 4f073a1dd55de7ae93abe278592a0bde068c14c9 Mon Sep 17 00:00:00 2001 From: Bernhard Urban-Forster Date: Mon, 19 Aug 2024 13:40:41 +0200 Subject: [PATCH 3/8] compare against known value that is set --- .../core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java index c70551ceab..e2e5e90cda 100644 --- a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java +++ b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java @@ -188,7 +188,7 @@ public static void setFunctionMissingAddresses(int functionCount) { long currentTable = memGetAddress(ptr); if (functionCount == 0) { - if (currentTable != RESERVED3_NULL) { + if (currentTable != FUNCTION_MISSING_ABORT) { FUNCTION_MISSING_ABORT_TABLE = NULL; getAllocator().free(currentTable); memPutAddress(ptr, NULL); From 8c06f6cb5a5ecd73fd6b60c94a310a2bfa304cda Mon Sep 17 00:00:00 2001 From: Bernhard Urban-Forster Date: Mon, 19 Aug 2024 13:51:03 +0200 Subject: [PATCH 4/8] move code to reduce diff --- .../src/main/java/org/lwjgl/system/ThreadLocalUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java index e2e5e90cda..29f54d3b7f 100644 --- a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java +++ b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java @@ -90,9 +90,6 @@ be easy to workaround (attaching the agent at startup, making sure no contexts a /** The global JNIEnv. */ private static final long JNI_NATIVE_INTERFACE = memGetAddress(getThreadJNIEnv()); - /** The offset in JNIEnv at which to store the pointer to the capabilities array. */ - private static final int CAPABILITIES_OFFSET = 3 * POINTER_SIZE; - /** The number of pointers in the JNIEnv struct. */ private static final int JNI_NATIVE_INTERFACE_FUNCTION_COUNT; @@ -106,6 +103,9 @@ be easy to workaround (attaching the agent at startup, making sure no contexts a */ private static long FUNCTION_MISSING_ABORT_TABLE = NULL; + /** The offset in JNIEnv at which to store the pointer to the capabilities array. */ + private static final int CAPABILITIES_OFFSET = 3 * POINTER_SIZE; + static { int JNI_VERSION = GetVersion(); From dcf6130fa3f636133b5a75bad49c170bf71da778 Mon Sep 17 00:00:00 2001 From: Bernhard Urban-Forster Date: Mon, 19 Aug 2024 15:04:29 +0200 Subject: [PATCH 5/8] fixup comment --- .../src/main/java/org/lwjgl/system/ThreadLocalUtil.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java index 29f54d3b7f..7fd4b516ee 100644 --- a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java +++ b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java @@ -186,7 +186,13 @@ public static void setCapabilities(long capabilities) { public static void setFunctionMissingAddresses(int functionCount) { long ptr = JNI_NATIVE_INTERFACE + CAPABILITIES_OFFSET; + // aka. reserved3 + // + // OpenJDK: NULL + // EspressoVM: NULL + // GraalVM Native Image: pointer to UnimplementedWithJNIEnvArgument function (see #875) long currentTable = memGetAddress(ptr); + if (functionCount == 0) { if (currentTable != FUNCTION_MISSING_ABORT) { FUNCTION_MISSING_ABORT_TABLE = NULL; @@ -195,7 +201,7 @@ public static void setFunctionMissingAddresses(int functionCount) { } } else { // OpenJDK: NULL - // EspressoVM: NULL + // EspressoVM: pointer to VM internal // GraalVM Native Image: pointer to UnimplementedWithJNIEnvArgument function (see #875) long RESERVED0_NULL = memGetAddress(JNI_NATIVE_INTERFACE); From c8a8187c190cd2a2eb4135a80bd3b7183f4dbace Mon Sep 17 00:00:00 2001 From: Bernhard Urban-Forster Date: Mon, 19 Aug 2024 15:12:59 +0200 Subject: [PATCH 6/8] restore with RESERVED3_NULL --- .../org/lwjgl/system/ThreadLocalUtil.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java index 7fd4b516ee..45ffc8437f 100644 --- a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java +++ b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java @@ -90,6 +90,18 @@ be easy to workaround (attaching the agent at startup, making sure no contexts a /** The global JNIEnv. */ private static final long JNI_NATIVE_INTERFACE = memGetAddress(getThreadJNIEnv()); + /** The offset in JNIEnv at which to store the pointer to the capabilities array. */ + private static final int CAPABILITIES_OFFSET = 3 * POINTER_SIZE; + + /** + * Initial value of reserved3 + * + * - OpenJDK: NULL + * - EspressoVM: NULL + * - GraalVM Native Image: pointer to UnimplementedWithJNIEnvArgument function (see #875) + */ + private static final long RESERVED3_NULL = memGetAddress(JNI_NATIVE_INTERFACE + CAPABILITIES_OFFSET); + /** The number of pointers in the JNIEnv struct. */ private static final int JNI_NATIVE_INTERFACE_FUNCTION_COUNT; @@ -103,9 +115,6 @@ be easy to workaround (attaching the agent at startup, making sure no contexts a */ private static long FUNCTION_MISSING_ABORT_TABLE = NULL; - /** The offset in JNIEnv at which to store the pointer to the capabilities array. */ - private static final int CAPABILITIES_OFFSET = 3 * POINTER_SIZE; - static { int JNI_VERSION = GetVersion(); @@ -187,17 +196,13 @@ public static void setFunctionMissingAddresses(int functionCount) { long ptr = JNI_NATIVE_INTERFACE + CAPABILITIES_OFFSET; // aka. reserved3 - // - // OpenJDK: NULL - // EspressoVM: NULL - // GraalVM Native Image: pointer to UnimplementedWithJNIEnvArgument function (see #875) long currentTable = memGetAddress(ptr); if (functionCount == 0) { if (currentTable != FUNCTION_MISSING_ABORT) { FUNCTION_MISSING_ABORT_TABLE = NULL; getAllocator().free(currentTable); - memPutAddress(ptr, NULL); + memPutAddress(ptr, RESERVED3_NULL); } } else { // OpenJDK: NULL @@ -205,7 +210,7 @@ public static void setFunctionMissingAddresses(int functionCount) { // GraalVM Native Image: pointer to UnimplementedWithJNIEnvArgument function (see #875) long RESERVED0_NULL = memGetAddress(JNI_NATIVE_INTERFACE); - boolean slotAvailable = currentTable == NULL; // on HotSpot or Espresso + boolean slotAvailable = currentTable == RESERVED3_NULL; // on HotSpot or Espresso slotAvailable |= currentTable == RESERVED0_NULL; // on Native Image if (!slotAvailable) { From a211af691bb576b45d24f721b00a87d10a96ecfd Mon Sep 17 00:00:00 2001 From: Bernhard Urban-Forster Date: Mon, 19 Aug 2024 15:13:33 +0200 Subject: [PATCH 7/8] restore bug --- .../core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java index 45ffc8437f..1da17df5cc 100644 --- a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java +++ b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java @@ -199,7 +199,7 @@ public static void setFunctionMissingAddresses(int functionCount) { long currentTable = memGetAddress(ptr); if (functionCount == 0) { - if (currentTable != FUNCTION_MISSING_ABORT) { + if (currentTable == FUNCTION_MISSING_ABORT) { FUNCTION_MISSING_ABORT_TABLE = NULL; getAllocator().free(currentTable); memPutAddress(ptr, RESERVED3_NULL); From 4825f8c964c14390a224027b72ab240c1190654f Mon Sep 17 00:00:00 2001 From: Bernhard Urban-Forster Date: Mon, 19 Aug 2024 15:38:28 +0200 Subject: [PATCH 8/8] use NULL for reserved3 check --- .../core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java index 1da17df5cc..fa7dc74429 100644 --- a/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java +++ b/modules/lwjgl/core/src/main/java/org/lwjgl/system/ThreadLocalUtil.java @@ -210,7 +210,7 @@ public static void setFunctionMissingAddresses(int functionCount) { // GraalVM Native Image: pointer to UnimplementedWithJNIEnvArgument function (see #875) long RESERVED0_NULL = memGetAddress(JNI_NATIVE_INTERFACE); - boolean slotAvailable = currentTable == RESERVED3_NULL; // on HotSpot or Espresso + boolean slotAvailable = currentTable == NULL; // on HotSpot or Espresso slotAvailable |= currentTable == RESERVED0_NULL; // on Native Image if (!slotAvailable) {