8186787: clang-4.0 SIGSEGV in Unsafe_PutByte

Reviewed-by: coleenp, dholmes, aph, dsamersoff, kbarrett
This commit is contained in:
Erik Österlund 2017-11-30 20:37:20 +01:00
parent 3f3f0cb67e
commit 6dc1d8c06d

View file

@ -146,18 +146,25 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
* Normalizes values and wraps accesses in
* JavaThread::doing_unsafe_access() if needed.
*/
template <typename T>
class MemoryAccess : StackObj {
JavaThread* _thread;
oop _obj;
ptrdiff_t _offset;
// Resolves and returns the address of the memory access
void* addr() {
return index_oop_from_field_offset_long(_obj, _offset);
// Resolves and returns the address of the memory access.
// This raw memory access may fault, so we make sure it happens within the
// guarded scope by making the access volatile at least. Since the store
// of Thread::set_doing_unsafe_access() is also volatile, these accesses
// can not be reordered by the compiler. Therefore, if the access triggers
// a fault, we will know that Thread::doing_unsafe_access() returns true.
volatile T* addr() {
void* addr = index_oop_from_field_offset_long(_obj, _offset);
return static_cast<volatile T*>(addr);
}
template <typename T>
T normalize_for_write(T x) {
template <typename U>
U normalize_for_write(U x) {
return x;
}
@ -165,8 +172,8 @@ class MemoryAccess : StackObj {
return x & 1;
}
template <typename T>
T normalize_for_read(T x) {
template <typename U>
U normalize_for_read(U x) {
return x;
}
@ -199,11 +206,10 @@ public:
assert_field_offset_sane(_obj, offset);
}
template <typename T>
T get() {
if (oopDesc::is_null(_obj)) {
GuardUnsafeAccess guard(_thread);
T ret = RawAccess<>::load((T*)addr());
T ret = RawAccess<>::load(addr());
return normalize_for_read(ret);
} else {
T ret = HeapAccess<>::load_at(_obj, _offset);
@ -211,22 +217,20 @@ public:
}
}
template <typename T>
void put(T x) {
if (oopDesc::is_null(_obj)) {
GuardUnsafeAccess guard(_thread);
RawAccess<>::store((T*)addr(), normalize_for_write(x));
RawAccess<>::store(addr(), normalize_for_write(x));
} else {
HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x));
}
}
template <typename T>
T get_volatile() {
if (oopDesc::is_null(_obj)) {
GuardUnsafeAccess guard(_thread);
volatile T ret = RawAccess<MO_SEQ_CST>::load((volatile T*)addr());
volatile T ret = RawAccess<MO_SEQ_CST>::load(addr());
return normalize_for_read(ret);
} else {
T ret = HeapAccess<MO_SEQ_CST>::load_at(_obj, _offset);
@ -234,11 +238,10 @@ public:
}
}
template <typename T>
void put_volatile(T x) {
if (oopDesc::is_null(_obj)) {
GuardUnsafeAccess guard(_thread);
RawAccess<MO_SEQ_CST>::store((volatile T*)addr(), normalize_for_write(x));
RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x));
} else {
HeapAccess<MO_SEQ_CST>::store_at(_obj, _offset, normalize_for_write(x));
}
@ -296,11 +299,11 @@ UNSAFE_LEAF(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) {
#define DEFINE_GETSETOOP(java_type, Type) \
\
UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
return MemoryAccess(thread, obj, offset).get<java_type>(); \
return MemoryAccess<java_type>(thread, obj, offset).get(); \
} UNSAFE_END \
\
UNSAFE_ENTRY(void, Unsafe_Put##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
MemoryAccess(thread, obj, offset).put<java_type>(x); \
MemoryAccess<java_type>(thread, obj, offset).put(x); \
} UNSAFE_END \
\
// END DEFINE_GETSETOOP.
@ -319,11 +322,11 @@ DEFINE_GETSETOOP(jdouble, Double);
#define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \
\
UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
return MemoryAccess(thread, obj, offset).get_volatile<java_type>(); \
return MemoryAccess<java_type>(thread, obj, offset).get_volatile(); \
} UNSAFE_END \
\
UNSAFE_ENTRY(void, Unsafe_Put##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
MemoryAccess(thread, obj, offset).put_volatile<java_type>(x); \
MemoryAccess<java_type>(thread, obj, offset).put_volatile(x); \
} UNSAFE_END \
\
// END DEFINE_GETSETOOP_VOLATILE.