Skip to content
Permalink
Browse files
8262896: [macos_aarch64] Crash in jni_fast_GetLongField
Reviewed-by: aph, dholmes
  • Loading branch information
AntonKozlov authored and David Holmes committed Apr 13, 2021
1 parent 55d5649 commit 283d64f81531ec3edc156f13278a9a284445b61d
Showing with 69 additions and 8 deletions.
  1. +51 −8 src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp
  2. +5 −0 src/hotspot/share/prims/jniFastGetField.hpp
  3. +13 −0 test/hotspot/gtest/runtime/test_threads.cpp
@@ -32,6 +32,7 @@
#include "prims/jvm_misc.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/threadWXSetters.inline.hpp"

#define __ masm->

@@ -52,6 +53,48 @@ static const Register roffset = r5;
static const Register rcounter_addr = r6;
static const Register result = r7;

// On macos/aarch64 we need to ensure WXExec mode when running generated
// FastGetXXXField, as these functions can be called from WXWrite context
// (8262896). So each FastGetXXXField is wrapped into a C++ statically
// compiled template function that optionally switches to WXExec if necessary.

#ifdef __APPLE__

static address generated_fast_get_field[T_LONG + 1 - T_BOOLEAN];

template<int BType> struct BasicTypeToJni {};
template<> struct BasicTypeToJni<T_BOOLEAN> { static const jboolean jni_type; };
template<> struct BasicTypeToJni<T_BYTE> { static const jbyte jni_type; };
template<> struct BasicTypeToJni<T_CHAR> { static const jchar jni_type; };
template<> struct BasicTypeToJni<T_SHORT> { static const jshort jni_type; };
template<> struct BasicTypeToJni<T_INT> { static const jint jni_type; };
template<> struct BasicTypeToJni<T_LONG> { static const jlong jni_type; };
template<> struct BasicTypeToJni<T_FLOAT> { static const jfloat jni_type; };
template<> struct BasicTypeToJni<T_DOUBLE> { static const jdouble jni_type; };

template<int BType, typename JniType = decltype(BasicTypeToJni<BType>::jni_type)>
JniType static_fast_get_field_wrapper(JNIEnv *env, jobject obj, jfieldID fieldID) {
JavaThread* thread = JavaThread::thread_from_jni_environment(env);
ThreadWXEnable wx(WXExec, thread);
address get_field_addr = generated_fast_get_field[BType - T_BOOLEAN];
return ((JniType(*)(JNIEnv *env, jobject obj, jfieldID fieldID))get_field_addr)(env, obj, fieldID);
}

template<int BType>
address JNI_FastGetField::generate_fast_get_int_field1() {
generated_fast_get_field[BType - T_BOOLEAN] = generate_fast_get_int_field0((BasicType)BType);
return (address)static_fast_get_field_wrapper<BType>;
}

#else // __APPLE__

template<int BType>
address JNI_FastGetField::generate_fast_get_int_field1() {
return generate_fast_get_int_field0((BasicType)BType);
}

#endif // __APPLE__

address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
const char *name;
switch (type) {
@@ -168,33 +211,33 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
}

address JNI_FastGetField::generate_fast_get_boolean_field() {
return generate_fast_get_int_field0(T_BOOLEAN);
return generate_fast_get_int_field1<T_BOOLEAN>();
}

address JNI_FastGetField::generate_fast_get_byte_field() {
return generate_fast_get_int_field0(T_BYTE);
return generate_fast_get_int_field1<T_BYTE>();
}

address JNI_FastGetField::generate_fast_get_char_field() {
return generate_fast_get_int_field0(T_CHAR);
return generate_fast_get_int_field1<T_CHAR>();
}

address JNI_FastGetField::generate_fast_get_short_field() {
return generate_fast_get_int_field0(T_SHORT);
return generate_fast_get_int_field1<T_SHORT>();
}

address JNI_FastGetField::generate_fast_get_int_field() {
return generate_fast_get_int_field0(T_INT);
return generate_fast_get_int_field1<T_INT>();
}

address JNI_FastGetField::generate_fast_get_long_field() {
return generate_fast_get_int_field0(T_LONG);
return generate_fast_get_int_field1<T_LONG>();
}

address JNI_FastGetField::generate_fast_get_float_field() {
return generate_fast_get_int_field0(T_FLOAT);
return generate_fast_get_int_field1<T_FLOAT>();
}

address JNI_FastGetField::generate_fast_get_double_field() {
return generate_fast_get_int_field0(T_DOUBLE);
return generate_fast_get_int_field1<T_DOUBLE>();
}
@@ -65,6 +65,11 @@ class JNI_FastGetField : AllStatic {
static address generate_fast_get_int_field0(BasicType type);
static address generate_fast_get_float_field0(BasicType type);

#ifdef AARCH64
template<int BType>
static address generate_fast_get_int_field1();
#endif // AARCH64

public:
#if defined(_WINDOWS) && !defined(_WIN64)
static GetBooleanField_t jni_fast_GetBooleanField_fp;
@@ -176,3 +176,16 @@ TEST_VM(ThreadsTest, claim_overflow) {
ThreadInVMfromNative invm(JavaThread::current());
VMThread::execute(&op);
}

TEST_VM(ThreadsTest, fast_jni_in_vm) {
JavaThread* current = JavaThread::current();
JNIEnv* env = current->jni_environment();
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, current));

// DirectByteBuffer is an easy way to trigger GetIntField,
// see JDK-8262896
jlong capacity = 0x10000;
jobject buffer = env->NewDirectByteBuffer(NULL, (jlong)capacity);
ASSERT_NE((void*)NULL, buffer);
ASSERT_EQ(capacity, env->GetDirectBufferCapacity(buffer));
}

1 comment on commit 283d64f

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on 283d64f Apr 13, 2021

Please sign in to comment.