35 #include "oops/fieldStreams.inline.hpp"
36 #include "oops/objArrayOop.inline.hpp"
37 #include "oops/oop.inline.hpp"
38 #include "oops/typeArrayOop.inline.hpp"
39 #include "prims/unsafe.hpp"
40 #include "runtime/globals.hpp"
41 #include "runtime/handles.inline.hpp"
42 #include "runtime/interfaceSupport.inline.hpp"
43 #include "runtime/jniHandles.inline.hpp"
44 #include "runtime/orderAccess.hpp"
45 #include "runtime/reflection.hpp"
46 #include "runtime/sharedRuntime.hpp"
47 #include "runtime/thread.hpp"
48 #include "runtime/threadSMR.hpp"
49 #include "runtime/vm_version.hpp"
50 #include "services/threadService.hpp"
51 #include "utilities/align.hpp"
52 #include "utilities/copy.hpp"
53 #include "utilities/dtrace.hpp"
54 #include "utilities/macros.hpp"
55
56 /**
57 * Implementation of the jdk.internal.misc.Unsafe class
58 */
59
60
61 #define MAX_OBJECT_SIZE \
62 ( arrayOopDesc::header_size(T_DOUBLE) * HeapWordSize \
63 + ((julong)max_jint * sizeof(double)) )
64
65
66 #define UNSAFE_ENTRY(result_type, header) \
67 JVM_ENTRY(static result_type, header)
68
69 #define UNSAFE_LEAF(result_type, header) \
70 JVM_LEAF(static result_type, header)
71
72 #define UNSAFE_END JVM_END
73
74
246 }
247 }
248
249 void put_volatile(T x) {
250 if (_obj == NULL) {
251 GuardUnsafeAccess guard(_thread);
252 RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x));
253 } else {
254 HeapAccess<MO_SEQ_CST>::store_at(_obj, _offset, normalize_for_write(x));
255 }
256 }
257 };
258
259 // These functions allow a null base pointer with an arbitrary address.
260 // But if the base pointer is non-null, the offset should make some sense.
261 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
262 UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
263 oop p = JNIHandles::resolve(obj);
264 assert_field_offset_sane(p, offset);
265 oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
266 return JNIHandles::make_local(env, v);
267 } UNSAFE_END
268
269 UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
270 oop x = JNIHandles::resolve(x_h);
271 oop p = JNIHandles::resolve(obj);
272 assert_field_offset_sane(p, offset);
273 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
274 } UNSAFE_END
275
276 UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
277 oop p = JNIHandles::resolve(obj);
278 assert_field_offset_sane(p, offset);
279 oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
280 return JNIHandles::make_local(env, v);
281 } UNSAFE_END
282
283 UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
284 oop x = JNIHandles::resolve(x_h);
285 oop p = JNIHandles::resolve(obj);
286 assert_field_offset_sane(p, offset);
287 HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
288 } UNSAFE_END
289
290 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
291 oop v = *(oop*) (address) addr;
292 return JNIHandles::make_local(env, v);
293 } UNSAFE_END
294
295 #define DEFINE_GETSETOOP(java_type, Type) \
296 \
297 UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
298 return MemoryAccess<java_type>(thread, obj, offset).get(); \
299 } UNSAFE_END \
300 \
301 UNSAFE_ENTRY(void, Unsafe_Put##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
302 MemoryAccess<java_type>(thread, obj, offset).put(x); \
303 } UNSAFE_END \
304 \
305 // END DEFINE_GETSETOOP.
306
307 DEFINE_GETSETOOP(jboolean, Boolean)
308 DEFINE_GETSETOOP(jbyte, Byte)
309 DEFINE_GETSETOOP(jshort, Short);
310 DEFINE_GETSETOOP(jchar, Char);
311 DEFINE_GETSETOOP(jint, Int);
312 DEFINE_GETSETOOP(jlong, Long);
313 DEFINE_GETSETOOP(jfloat, Float);
314 DEFINE_GETSETOOP(jdouble, Double);
315
316 #undef DEFINE_GETSETOOP
317
318 #define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \
319 \
320 UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
321 return MemoryAccess<java_type>(thread, obj, offset).get_volatile(); \
322 } UNSAFE_END \
323 \
324 UNSAFE_ENTRY(void, Unsafe_Put##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
325 MemoryAccess<java_type>(thread, obj, offset).put_volatile(x); \
326 } UNSAFE_END \
327 \
328 // END DEFINE_GETSETOOP_VOLATILE.
329
330 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
331 DEFINE_GETSETOOP_VOLATILE(jbyte, Byte)
332 DEFINE_GETSETOOP_VOLATILE(jshort, Short);
333 DEFINE_GETSETOOP_VOLATILE(jchar, Char);
334 DEFINE_GETSETOOP_VOLATILE(jint, Int);
335 DEFINE_GETSETOOP_VOLATILE(jlong, Long);
336 DEFINE_GETSETOOP_VOLATILE(jfloat, Float);
337 DEFINE_GETSETOOP_VOLATILE(jdouble, Double);
338
339 #undef DEFINE_GETSETOOP_VOLATILE
340
341 UNSAFE_LEAF(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) {
342 OrderAccess::acquire();
343 } UNSAFE_END
344
882 // this point. The mirror and any instances of this class have to keep
883 // it alive afterwards.
884 if (anon_klass != NULL) {
885 anon_klass->class_loader_data()->dec_keep_alive();
886 }
887
888 // let caller initialize it as needed...
889
890 return (jclass) res_jh;
891 } UNSAFE_END
892
893
894
895 UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr)) {
896 ThreadToNativeFromVM ttnfv(thread);
897 env->Throw(thr);
898 } UNSAFE_END
899
900 // JSR166 ------------------------------------------------------------------
901
902 UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) {
903 oop x = JNIHandles::resolve(x_h);
904 oop e = JNIHandles::resolve(e_h);
905 oop p = JNIHandles::resolve(obj);
906 assert_field_offset_sane(p, offset);
907 oop res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x);
908 return JNIHandles::make_local(env, res);
909 } UNSAFE_END
910
911 UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
912 oop p = JNIHandles::resolve(obj);
913 if (p == NULL) {
914 volatile jint* addr = (volatile jint*)index_oop_from_field_offset_long(p, offset);
915 return RawAccess<>::atomic_cmpxchg(addr, e, x);
916 } else {
917 assert_field_offset_sane(p, offset);
918 return HeapAccess<>::atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x);
919 }
920 } UNSAFE_END
921
922 UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
923 oop p = JNIHandles::resolve(obj);
924 if (p == NULL) {
925 volatile jlong* addr = (volatile jlong*)index_oop_from_field_offset_long(p, offset);
926 return RawAccess<>::atomic_cmpxchg(addr, e, x);
927 } else {
928 assert_field_offset_sane(p, offset);
929 return HeapAccess<>::atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x);
930 }
931 } UNSAFE_END
932
933 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) {
934 oop x = JNIHandles::resolve(x_h);
935 oop e = JNIHandles::resolve(e_h);
936 oop p = JNIHandles::resolve(obj);
937 assert_field_offset_sane(p, offset);
938 oop ret = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x);
939 return ret == e;
940 } UNSAFE_END
941
942 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
943 oop p = JNIHandles::resolve(obj);
944 if (p == NULL) {
945 volatile jint* addr = (volatile jint*)index_oop_from_field_offset_long(p, offset);
946 return RawAccess<>::atomic_cmpxchg(addr, e, x) == e;
947 } else {
948 assert_field_offset_sane(p, offset);
949 return HeapAccess<>::atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x) == e;
950 }
951 } UNSAFE_END
952
953 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
954 oop p = JNIHandles::resolve(obj);
955 if (p == NULL) {
956 volatile jlong* addr = (volatile jlong*)index_oop_from_field_offset_long(p, offset);
957 return RawAccess<>::atomic_cmpxchg(addr, e, x) == e;
958 } else {
959 assert_field_offset_sane(p, offset);
960 return HeapAccess<>::atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x) == e;
961 }
962 } UNSAFE_END
963
964 static void post_thread_park_event(EventThreadPark* event, const oop obj, jlong timeout_nanos, jlong until_epoch_millis) {
965 assert(event != NULL, "invariant");
966 assert(event->should_commit(), "invariant");
967 event->set_parkedClass((obj != NULL) ? obj->klass() : NULL);
968 event->set_timeout(timeout_nanos);
969 event->set_until(until_epoch_millis);
970 event->set_address((obj != NULL) ? (u8)cast_from_oop<uintptr_t>(obj) : 0);
971 event->commit();
972 }
973
974 UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) {
975 HOTSPOT_THREAD_PARK_BEGIN((uintptr_t) thread->parker(), (int) isAbsolute, time);
976 EventThreadPark event;
977
978 JavaThreadParkedState jtps(thread, time != 0);
979 thread->parker()->park(isAbsolute != 0, time);
|
35 #include "oops/fieldStreams.inline.hpp"
36 #include "oops/objArrayOop.inline.hpp"
37 #include "oops/oop.inline.hpp"
38 #include "oops/typeArrayOop.inline.hpp"
39 #include "prims/unsafe.hpp"
40 #include "runtime/globals.hpp"
41 #include "runtime/handles.inline.hpp"
42 #include "runtime/interfaceSupport.inline.hpp"
43 #include "runtime/jniHandles.inline.hpp"
44 #include "runtime/orderAccess.hpp"
45 #include "runtime/reflection.hpp"
46 #include "runtime/sharedRuntime.hpp"
47 #include "runtime/thread.hpp"
48 #include "runtime/threadSMR.hpp"
49 #include "runtime/vm_version.hpp"
50 #include "services/threadService.hpp"
51 #include "utilities/align.hpp"
52 #include "utilities/copy.hpp"
53 #include "utilities/dtrace.hpp"
54 #include "utilities/macros.hpp"
55 #if INCLUDE_TSAN
56 #include "tsan/tsanExternalDecls.hpp"
57 #endif
58
59 /**
60 * Implementation of the jdk.internal.misc.Unsafe class
61 */
62
63
64 #define MAX_OBJECT_SIZE \
65 ( arrayOopDesc::header_size(T_DOUBLE) * HeapWordSize \
66 + ((julong)max_jint * sizeof(double)) )
67
68
69 #define UNSAFE_ENTRY(result_type, header) \
70 JVM_ENTRY(static result_type, header)
71
72 #define UNSAFE_LEAF(result_type, header) \
73 JVM_LEAF(static result_type, header)
74
75 #define UNSAFE_END JVM_END
76
77
249 }
250 }
251
252 void put_volatile(T x) {
253 if (_obj == NULL) {
254 GuardUnsafeAccess guard(_thread);
255 RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x));
256 } else {
257 HeapAccess<MO_SEQ_CST>::store_at(_obj, _offset, normalize_for_write(x));
258 }
259 }
260 };
261
262 // These functions allow a null base pointer with an arbitrary address.
263 // But if the base pointer is non-null, the offset should make some sense.
264 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
265 UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
266 oop p = JNIHandles::resolve(obj);
267 assert_field_offset_sane(p, offset);
268 oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
269 TSAN_RUNTIME_ONLY(
270 void* addr = index_oop_from_field_offset_long(p, offset);
271 if (UseCompressedOops) {
272 __tsan_read4_pc(addr, SharedRuntime::tsan_code_location(0, 0));
273 } else {
274 __tsan_read8_pc(addr, SharedRuntime::tsan_code_location(0, 0));
275 }
276 );
277 return JNIHandles::make_local(env, v);
278 } UNSAFE_END
279
280 UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
281 oop x = JNIHandles::resolve(x_h);
282 oop p = JNIHandles::resolve(obj);
283 assert_field_offset_sane(p, offset);
284 TSAN_RUNTIME_ONLY(
285 void* addr = index_oop_from_field_offset_long(p, offset);
286 if (UseCompressedOops) {
287 __tsan_write4_pc(addr, SharedRuntime::tsan_code_location(0, 0));
288 } else {
289 __tsan_write8_pc(addr, SharedRuntime::tsan_code_location(0, 0));
290 }
291 );
292 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
293 } UNSAFE_END
294
295 UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
296 oop p = JNIHandles::resolve(obj);
297 assert_field_offset_sane(p, offset);
298 oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
299 TSAN_RUNTIME_ONLY(
300 void* addr = index_oop_from_field_offset_long(p, offset);
301 __tsan_java_acquire(addr);
302 );
303 return JNIHandles::make_local(env, v);
304 } UNSAFE_END
305
306 UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
307 oop x = JNIHandles::resolve(x_h);
308 oop p = JNIHandles::resolve(obj);
309 assert_field_offset_sane(p, offset);
310 TSAN_RUNTIME_ONLY(
311 void* addr = index_oop_from_field_offset_long(p, offset);
312 __tsan_java_release(addr);
313 );
314 HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
315 } UNSAFE_END
316
317 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
318 oop v = *(oop*) (address) addr;
319 return JNIHandles::make_local(env, v);
320 } UNSAFE_END
321
322 #define DEFINE_GETSETOOP(java_type, Type, size) \
323 \
324 UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
325 java_type ret = MemoryAccess<java_type>(thread, obj, offset).get(); \
326 TSAN_RUNTIME_ONLY( \
327 void* addr = index_oop_from_field_offset_long(JNIHandles::resolve(obj), offset); \
328 __tsan_read##size##_pc(addr, SharedRuntime::tsan_code_location(0, 0)); \
329 ); \
330 return ret; \
331 } UNSAFE_END \
332 \
333 UNSAFE_ENTRY(void, Unsafe_Put##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
334 TSAN_RUNTIME_ONLY( \
335 void* addr = index_oop_from_field_offset_long(JNIHandles::resolve(obj), offset); \
336 __tsan_write##size##_pc(addr, SharedRuntime::tsan_code_location(0, 0)); \
337 ); \
338 MemoryAccess<java_type>(thread, obj, offset).put(x); \
339 } UNSAFE_END \
340 \
341 // END DEFINE_GETSETOOP.
342
343 DEFINE_GETSETOOP(jboolean, Boolean, 1)
344 DEFINE_GETSETOOP(jbyte, Byte, 1)
345 DEFINE_GETSETOOP(jshort, Short, 2);
346 DEFINE_GETSETOOP(jchar, Char, 2);
347 DEFINE_GETSETOOP(jint, Int, 4);
348 DEFINE_GETSETOOP(jlong, Long, 8);
349 DEFINE_GETSETOOP(jfloat, Float, 4);
350 DEFINE_GETSETOOP(jdouble, Double, 8);
351
352 #undef DEFINE_GETSETOOP
353
354 #define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \
355 \
356 UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
357 java_type ret = MemoryAccess<java_type>(thread, obj, offset).get_volatile(); \
358 TSAN_RUNTIME_ONLY( \
359 void* addr = index_oop_from_field_offset_long(JNIHandles::resolve(obj), offset); \
360 __tsan_java_acquire(addr); \
361 ); \
362 return ret; \
363 } UNSAFE_END \
364 \
365 UNSAFE_ENTRY(void, Unsafe_Put##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
366 TSAN_RUNTIME_ONLY( \
367 void* addr = index_oop_from_field_offset_long(JNIHandles::resolve(obj), offset); \
368 __tsan_java_release(addr); \
369 ); \
370 MemoryAccess<java_type>(thread, obj, offset).put_volatile(x); \
371 } UNSAFE_END \
372 \
373 // END DEFINE_GETSETOOP_VOLATILE.
374
375 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
376 DEFINE_GETSETOOP_VOLATILE(jbyte, Byte)
377 DEFINE_GETSETOOP_VOLATILE(jshort, Short);
378 DEFINE_GETSETOOP_VOLATILE(jchar, Char);
379 DEFINE_GETSETOOP_VOLATILE(jint, Int);
380 DEFINE_GETSETOOP_VOLATILE(jlong, Long);
381 DEFINE_GETSETOOP_VOLATILE(jfloat, Float);
382 DEFINE_GETSETOOP_VOLATILE(jdouble, Double);
383
384 #undef DEFINE_GETSETOOP_VOLATILE
385
386 UNSAFE_LEAF(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) {
387 OrderAccess::acquire();
388 } UNSAFE_END
389
927 // this point. The mirror and any instances of this class have to keep
928 // it alive afterwards.
929 if (anon_klass != NULL) {
930 anon_klass->class_loader_data()->dec_keep_alive();
931 }
932
933 // let caller initialize it as needed...
934
935 return (jclass) res_jh;
936 } UNSAFE_END
937
938
939
940 UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr)) {
941 ThreadToNativeFromVM ttnfv(thread);
942 env->Throw(thr);
943 } UNSAFE_END
944
945 // JSR166 ------------------------------------------------------------------
946
947 // Calls __tsan_java_release() on construct and __tsan_java_acquire() on destruct.
948 class ScopedReleaseAcquire: public StackObj {
949 private:
950 void* _addr;
951 public:
952 ScopedReleaseAcquire(volatile void* addr) {
953 TSAN_RUNTIME_ONLY(
954 _addr = const_cast<void*>(addr);
955 __tsan_java_release(_addr);
956 );
957 }
958
959 ScopedReleaseAcquire(oop obj, jlong offset) {
960 TSAN_RUNTIME_ONLY(
961 _addr = index_oop_from_field_offset_long(obj, offset);
962 __tsan_java_release(_addr);
963 );
964 }
965
966 ~ScopedReleaseAcquire() {
967 TSAN_RUNTIME_ONLY(__tsan_java_acquire(_addr));
968 }
969 };
970
971 UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) {
972 oop x = JNIHandles::resolve(x_h);
973 oop e = JNIHandles::resolve(e_h);
974 oop p = JNIHandles::resolve(obj);
975 assert_field_offset_sane(p, offset);
976 ScopedReleaseAcquire releaseAcquire(p, offset);
977 oop res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x);
978 return JNIHandles::make_local(env, res);
979 } UNSAFE_END
980
981 UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
982 oop p = JNIHandles::resolve(obj);
983 if (p == NULL) {
984 volatile jint* addr = (volatile jint*)index_oop_from_field_offset_long(p, offset);
985 ScopedReleaseAcquire releaseAcquire(addr);
986 return RawAccess<>::atomic_cmpxchg(addr, e, x);
987 } else {
988 assert_field_offset_sane(p, offset);
989 ScopedReleaseAcquire releaseAcquire(p, offset);
990 return HeapAccess<>::atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x);
991 }
992 } UNSAFE_END
993
994 UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
995 oop p = JNIHandles::resolve(obj);
996 if (p == NULL) {
997 volatile jlong* addr = (volatile jlong*)index_oop_from_field_offset_long(p, offset);
998 ScopedReleaseAcquire releaseAcquire(addr);
999 return RawAccess<>::atomic_cmpxchg(addr, e, x);
1000 } else {
1001 assert_field_offset_sane(p, offset);
1002 ScopedReleaseAcquire releaseAcquire(p, offset);
1003 return HeapAccess<>::atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x);
1004 }
1005 } UNSAFE_END
1006
1007 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) {
1008 oop x = JNIHandles::resolve(x_h);
1009 oop e = JNIHandles::resolve(e_h);
1010 oop p = JNIHandles::resolve(obj);
1011 assert_field_offset_sane(p, offset);
1012 ScopedReleaseAcquire releaseAcquire(p, offset);
1013 oop ret = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x);
1014 return ret == e;
1015 } UNSAFE_END
1016
1017 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
1018 oop p = JNIHandles::resolve(obj);
1019 if (p == NULL) {
1020 volatile jint* addr = (volatile jint*)index_oop_from_field_offset_long(p, offset);
1021 ScopedReleaseAcquire releaseAcquire(addr);
1022 return RawAccess<>::atomic_cmpxchg(addr, e, x) == e;
1023 } else {
1024 assert_field_offset_sane(p, offset);
1025 ScopedReleaseAcquire releaseAcquire(p, offset);
1026 return HeapAccess<>::atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x) == e;
1027 }
1028 } UNSAFE_END
1029
1030 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
1031 oop p = JNIHandles::resolve(obj);
1032 if (p == NULL) {
1033 volatile jlong* addr = (volatile jlong*)index_oop_from_field_offset_long(p, offset);
1034 ScopedReleaseAcquire releaseAcquire(addr);
1035 return RawAccess<>::atomic_cmpxchg(addr, e, x) == e;
1036 } else {
1037 assert_field_offset_sane(p, offset);
1038 ScopedReleaseAcquire releaseAcquire(p, offset);
1039 return HeapAccess<>::atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x) == e;
1040 }
1041 } UNSAFE_END
1042
1043 static void post_thread_park_event(EventThreadPark* event, const oop obj, jlong timeout_nanos, jlong until_epoch_millis) {
1044 assert(event != NULL, "invariant");
1045 assert(event->should_commit(), "invariant");
1046 event->set_parkedClass((obj != NULL) ? obj->klass() : NULL);
1047 event->set_timeout(timeout_nanos);
1048 event->set_until(until_epoch_millis);
1049 event->set_address((obj != NULL) ? (u8)cast_from_oop<uintptr_t>(obj) : 0);
1050 event->commit();
1051 }
1052
1053 UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) {
1054 HOTSPOT_THREAD_PARK_BEGIN((uintptr_t) thread->parker(), (int) isAbsolute, time);
1055 EventThreadPark event;
1056
1057 JavaThreadParkedState jtps(thread, time != 0);
1058 thread->parker()->park(isAbsolute != 0, time);
|