< prev index next >

src/share/vm/prims/unsafe.cpp

Print this page
rev 12906 : [mq]: gc_interface

*** 26,39 **** --- 26,41 ---- #include "classfile/classFileStream.hpp" #include "classfile/vmSymbols.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "oops/objArrayOop.inline.hpp" + #include "oops/typeArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "prims/jni.h" #include "prims/jvm.h" #include "prims/unsafe.hpp" + #include "runtime/access.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/globals.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/orderAccess.inline.hpp" #include "runtime/reflection.hpp"
*** 41,53 **** #include "services/threadService.hpp" #include "trace/tracing.hpp" #include "utilities/copy.hpp" #include "utilities/dtrace.hpp" #include "utilities/macros.hpp" - #if INCLUDE_ALL_GCS - #include "gc/g1/g1SATBCardTableModRefBS.hpp" - #endif // INCLUDE_ALL_GCS /** * Implementation of the jdk.internal.misc.Unsafe class */ --- 43,52 ----
*** 96,108 **** static inline jlong field_offset_from_byte_offset(jlong byte_offset) { return byte_offset; } ! static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { ! jlong byte_offset = field_offset_to_byte_offset(field_offset); ! #ifdef ASSERT if (p != NULL) { assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset"); if (byte_offset == (jint)byte_offset) { void* ptr_plus_disp = (address)p + byte_offset; --- 95,105 ---- static inline jlong field_offset_from_byte_offset(jlong byte_offset) { return byte_offset; } ! static inline void assert_sane_byte_offset(oop p, jlong byte_offset) { #ifdef ASSERT if (p != NULL) { assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset"); if (byte_offset == (jint)byte_offset) { void* ptr_plus_disp = (address)p + byte_offset;
*** 111,121 **** --- 108,122 ---- } jlong p_size = HeapWordSize * (jlong)(p->size()); assert(byte_offset < p_size, "Unsafe access: offset " INT64_FORMAT " > object's size " INT64_FORMAT, byte_offset, p_size); } #endif + } + static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { + jlong byte_offset = field_offset_to_byte_offset(field_offset); + assert_sane_byte_offset(p, byte_offset); if (sizeof(char*) == sizeof(jint)) { // (this constant folds!) return (address)p + (jint) byte_offset; } else { return (address)p + byte_offset; }
*** 138,425 **** * * Normalizes values and wraps accesses in * JavaThread::doing_unsafe_access() if needed. */ class MemoryAccess : StackObj { ! JavaThread* _thread; ! jobject _obj; ! jlong _offset; ! ! // Resolves and returns the address of the memory access ! void* addr() { ! return index_oop_from_field_offset_long(JNIHandles::resolve(_obj), _offset); ! } template <typename T> ! T normalize_for_write(T x) { return x; } ! jboolean normalize_for_write(jboolean x) { return x & 1; } template <typename T> ! T normalize_for_read(T x) { return x; } ! jboolean normalize_for_read(jboolean x) { return x != 0; } /** * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access() */ class GuardUnsafeAccess { ! JavaThread* _thread; ! bool _active; public: ! GuardUnsafeAccess(JavaThread* thread, jobject _obj) : _thread(thread) { ! if (JNIHandles::resolve(_obj) == NULL) { ! // native/off-heap access which may raise SIGBUS if accessing ! // memory mapped file data in a region of the file which has ! // been truncated and is now invalid _thread->set_doing_unsafe_access(true); - _active = true; - } else { - _active = false; - } } ~GuardUnsafeAccess() { - if (_active) { _thread->set_doing_unsafe_access(false); } - } }; public: MemoryAccess(JavaThread* thread, jobject obj, jlong offset) ! : _thread(thread), _obj(obj), _offset(offset) { } ! template <typename T> ! T get() { ! GuardUnsafeAccess guard(_thread, _obj); ! ! T* p = (T*)addr(); ! ! T x = normalize_for_read(*p); ! return x; } template <typename T> void put(T x) { ! GuardUnsafeAccess guard(_thread, _obj); ! ! T* p = (T*)addr(); ! ! *p = normalize_for_write(x); } template <typename T> T get_volatile() { ! GuardUnsafeAccess guard(_thread, _obj); ! ! T* p = (T*)addr(); ! ! if (support_IRIW_for_not_multiple_copy_atomic_cpu) { ! OrderAccess::fence(); } - - T x = OrderAccess::load_acquire((volatile T*)p); - return normalize_for_read(x); } template <typename T> void put_volatile(T x) { ! GuardUnsafeAccess guard(_thread, _obj); ! ! T* p = (T*)addr(); ! ! OrderAccess::release_store_fence((volatile T*)p, normalize_for_write(x)); ! } ! ! ! #ifndef SUPPORTS_NATIVE_CX8 ! jlong get_jlong_locked() { ! GuardUnsafeAccess guard(_thread, _obj); ! ! MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); ! ! jlong* p = (jlong*)addr(); ! ! jlong x = Atomic::load(p); ! ! return x; } - - void put_jlong_locked(jlong x) { - GuardUnsafeAccess guard(_thread, _obj); - - MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); - - jlong* p = (jlong*)addr(); - - Atomic::store(normalize_for_write(x), p); } - #endif }; - // Get/PutObject must be special-cased, since it works with handles. - - // We could be accessing the referent field in a reference - // object. If G1 is enabled then we need to register non-null - // referent with the SATB barrier. - - #if INCLUDE_ALL_GCS - static bool is_java_lang_ref_Reference_access(oop o, jlong offset) { - if (offset == java_lang_ref_Reference::referent_offset && o != NULL) { - Klass* k = o->klass(); - if (InstanceKlass::cast(k)->reference_type() != REF_NONE) { - assert(InstanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity"); - return true; - } - } - return false; - } - #endif - - static void ensure_satb_referent_alive(oop o, jlong offset, oop v) { - #if INCLUDE_ALL_GCS - if (UseG1GC && v != NULL && is_java_lang_ref_Reference_access(o, offset)) { - G1SATBCardTableModRefBS::enqueue(v); - } - #endif - } - // These functions allow a null base pointer with an arbitrary address. // But if the base pointer is non-null, the offset should make some sense. // That is, it should be in the range [0, MAX_OBJECT_SIZE]. UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { oop p = JNIHandles::resolve(obj); ! oop v; ! ! if (UseCompressedOops) { ! narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); ! v = oopDesc::decode_heap_oop(n); ! } else { ! v = *(oop*)index_oop_from_field_offset_long(p, offset); ! } ! ! ensure_satb_referent_alive(p, offset, v); ! return JNIHandles::make_local(env, v); } UNSAFE_END UNSAFE_ENTRY(void, Unsafe_PutObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); ! ! if (UseCompressedOops) { ! oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); ! } else { ! oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); ! } } UNSAFE_END UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { oop p = JNIHandles::resolve(obj); ! void* addr = index_oop_from_field_offset_long(p, offset); ! ! volatile oop v; ! ! if (support_IRIW_for_not_multiple_copy_atomic_cpu) { ! OrderAccess::fence(); ! } ! ! if (UseCompressedOops) { ! volatile narrowOop n = *(volatile narrowOop*) addr; ! (void)const_cast<oop&>(v = oopDesc::decode_heap_oop(n)); ! } else { ! (void)const_cast<oop&>(v = *(volatile oop*) addr); ! } ! ! ensure_satb_referent_alive(p, offset, v); ! ! OrderAccess::acquire(); return JNIHandles::make_local(env, v); } UNSAFE_END UNSAFE_ENTRY(void, Unsafe_PutObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); ! void* addr = index_oop_from_field_offset_long(p, offset); ! OrderAccess::release(); ! ! if (UseCompressedOops) { ! oop_store((narrowOop*)addr, x); ! } else { ! oop_store((oop*)addr, x); ! } ! ! OrderAccess::fence(); } UNSAFE_END UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) { oop v = *(oop*) (address) addr; - return JNIHandles::make_local(env, v); } UNSAFE_END - #ifndef SUPPORTS_NATIVE_CX8 - - // VM_Version::supports_cx8() is a surrogate for 'supports atomic long memory ops'. - // - // On platforms which do not support atomic compare-and-swap of jlong (8 byte) - // values we have to use a lock-based scheme to enforce atomicity. This has to be - // applied to all Unsafe operations that set the value of a jlong field. Even so - // the compareAndSwapLong operation will not be atomic with respect to direct stores - // to the field from Java code. It is important therefore that any Java code that - // utilizes these Unsafe jlong operations does not perform direct stores. To permit - // direct loads of the field from Java code we must also use Atomic::store within the - // locked regions. And for good measure, in case there are direct stores, we also - // employ Atomic::load within those regions. Note that the field in question must be - // volatile and so must have atomic load/store accesses applied at the Java level. - // - // The locking scheme could utilize a range of strategies for controlling the locking - // granularity: from a lock per-field through to a single global lock. The latter is - // the simplest and is used for the current implementation. Note that the Java object - // that contains the field, can not, in general, be used for locking. To do so can lead - // to deadlocks as we may introduce locking into what appears to the Java code to be a - // lock-free path. - // - // As all the locked-regions are very short and themselves non-blocking we can treat - // them as leaf routines and elide safepoint checks (ie we don't perform any thread - // state transitions even when blocking for the lock). Note that if we do choose to - // add safepoint checks and thread state transitions, we must ensure that we calculate - // the address of the field _after_ we have acquired the lock, else the object may have - // been moved by the GC - - UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { - if (VM_Version::supports_cx8()) { - return MemoryAccess(thread, obj, offset).get_volatile<jlong>(); - } else { - return MemoryAccess(thread, obj, offset).get_jlong_locked(); - } - } UNSAFE_END - - UNSAFE_ENTRY(void, Unsafe_PutLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) { - if (VM_Version::supports_cx8()) { - MemoryAccess(thread, obj, offset).put_volatile<jlong>(x); - } else { - MemoryAccess(thread, obj, offset).put_jlong_locked(x); - } - } UNSAFE_END - - #endif // not SUPPORTS_NATIVE_CX8 - UNSAFE_LEAF(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) { #ifdef VM_LITTLE_ENDIAN return false; #else return true; --- 139,283 ---- * * Normalizes values and wraps accesses in * JavaThread::doing_unsafe_access() if needed. */ class MemoryAccess : StackObj { ! JavaThread*const _thread; ! const oop _obj; ! const ptrdiff_t _offset; template <typename T> ! T normalize_for_write(T x) const { return x; } ! jboolean normalize_for_write(jboolean x) const { return x & 1; } template <typename T> ! T normalize_for_read(T x) const { return x; } ! jboolean normalize_for_read(jboolean x) const { return x != 0; } /** * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access() + * native/off-heap access which may raise SIGBUS if accessing + * memory mapped file data in a region of the file which has + * been truncated and is now invalid */ class GuardUnsafeAccess { ! JavaThread*const _thread; public: ! GuardUnsafeAccess(JavaThread* thread) : _thread(thread) { _thread->set_doing_unsafe_access(true); } ~GuardUnsafeAccess() { _thread->set_doing_unsafe_access(false); } }; public: MemoryAccess(JavaThread* thread, jobject obj, jlong offset) ! : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) { ! assert_sane_byte_offset(_obj, offset); } ! bool on_heap() const { ! return !oopDesc::is_null(_obj); ! } ! template <typename T> ! T get() const { ! T x; ! if (on_heap()) { ! x = HeapAccess<ACCESS_ON_ANONYMOUS>::load_at(_obj, _offset); ! } else { ! GuardUnsafeAccess guard(_thread); ! x = RawAccess<>::load((T*)_offset); ! } ! return normalize_for_read(x); } template <typename T> void put(T x) { ! x = normalize_for_write(x); ! if (on_heap()) { ! HeapAccess<ACCESS_ON_ANONYMOUS>::store_at(_obj, _offset, x); ! } else { ! GuardUnsafeAccess guard(_thread); ! RawAccess<>::store((T*)_offset, x); ! } } template <typename T> T get_volatile() { ! T x; ! if (on_heap()) { ! x = HeapAccess<ACCESS_ON_ANONYMOUS | MO_SEQ_CST>::load_at(_obj, _offset); ! } else { ! GuardUnsafeAccess guard(_thread); ! x = RawAccess<MO_SEQ_CST>::load((T*)_offset); } return normalize_for_read(x); } template <typename T> void put_volatile(T x) { ! x = normalize_for_write(x); ! if (on_heap()) { ! HeapAccess<ACCESS_ON_ANONYMOUS | MO_SEQ_CST>::store_at(_obj, _offset, x); ! } else { ! GuardUnsafeAccess guard(_thread); ! RawAccess<MO_SEQ_CST>::store((T*)_offset, x); } } }; // These functions allow a null base pointer with an arbitrary address. // But if the base pointer is non-null, the offset should make some sense. // That is, it should be in the range [0, MAX_OBJECT_SIZE]. UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { oop p = JNIHandles::resolve(obj); ! assert_sane_byte_offset(p, offset); ! oop v = HeapAccess<ACCESS_ON_ANONYMOUS>::oop_load_at(p, offset); return JNIHandles::make_local(env, v); } UNSAFE_END UNSAFE_ENTRY(void, Unsafe_PutObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); ! assert_sane_byte_offset(p, offset); ! HeapAccess<ACCESS_ON_ANONYMOUS>::oop_store_at(p, offset, x); } UNSAFE_END UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { oop p = JNIHandles::resolve(obj); ! assert_sane_byte_offset(p, offset); ! oop v = HeapAccess<MO_SEQ_CST | ACCESS_ON_ANONYMOUS>::oop_load_at(p, offset); return JNIHandles::make_local(env, v); } UNSAFE_END UNSAFE_ENTRY(void, Unsafe_PutObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); ! assert_sane_byte_offset(p, offset); ! HeapAccess<MO_SEQ_CST | ACCESS_ON_ANONYMOUS>::oop_store_at(p, offset, x); } UNSAFE_END UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) { oop v = *(oop*) (address) addr; return JNIHandles::make_local(env, v); } UNSAFE_END UNSAFE_LEAF(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) { #ifdef VM_LITTLE_ENDIAN return false; #else return true;
*** 468,484 **** DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) DEFINE_GETSETOOP_VOLATILE(jbyte, Byte) DEFINE_GETSETOOP_VOLATILE(jshort, Short); DEFINE_GETSETOOP_VOLATILE(jchar, Char); DEFINE_GETSETOOP_VOLATILE(jint, Int); DEFINE_GETSETOOP_VOLATILE(jfloat, Float); DEFINE_GETSETOOP_VOLATILE(jdouble, Double); - #ifdef SUPPORTS_NATIVE_CX8 - DEFINE_GETSETOOP_VOLATILE(jlong, Long); - #endif - #undef DEFINE_GETSETOOP_VOLATILE UNSAFE_LEAF(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) { OrderAccess::acquire(); } UNSAFE_END --- 326,339 ---- DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) DEFINE_GETSETOOP_VOLATILE(jbyte, Byte) DEFINE_GETSETOOP_VOLATILE(jshort, Short); DEFINE_GETSETOOP_VOLATILE(jchar, Char); DEFINE_GETSETOOP_VOLATILE(jint, Int); + DEFINE_GETSETOOP_VOLATILE(jlong, Long); DEFINE_GETSETOOP_VOLATILE(jfloat, Float); DEFINE_GETSETOOP_VOLATILE(jdouble, Double); #undef DEFINE_GETSETOOP_VOLATILE UNSAFE_LEAF(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) { OrderAccess::acquire(); } UNSAFE_END
*** 974,1063 **** UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop e = JNIHandles::resolve(e_h); oop p = JNIHandles::resolve(obj); ! HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset); ! oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true); ! if (res == e) { ! update_barrier_set((void*)addr, x); ! } return JNIHandles::make_local(env, res); } UNSAFE_END - UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) { - oop p = JNIHandles::resolve(obj); - jint* addr = (jint *) index_oop_from_field_offset_long(p, offset); - - return (jint)(Atomic::cmpxchg(x, addr, e)); - } UNSAFE_END - - UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) { - Handle p(THREAD, JNIHandles::resolve(obj)); - jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset); - - #ifdef SUPPORTS_NATIVE_CX8 - return (jlong)(Atomic::cmpxchg(x, addr, e)); - #else - if (VM_Version::supports_cx8()) { - return (jlong)(Atomic::cmpxchg(x, addr, e)); - } else { - MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); - - jlong val = Atomic::load(addr); - if (val == e) { - Atomic::store(x, addr); - } - return val; - } - #endif - } UNSAFE_END - UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop e = JNIHandles::resolve(e_h); oop p = JNIHandles::resolve(obj); ! HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset); ! oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true); ! if (res != e) { ! return false; ! } ! ! update_barrier_set((void*)addr, x); ! ! return true; ! } UNSAFE_END ! ! UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) { ! oop p = JNIHandles::resolve(obj); ! jint* addr = (jint *)index_oop_from_field_offset_long(p, offset); ! ! return (jint)(Atomic::cmpxchg(x, addr, e)) == e; } UNSAFE_END ! UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) { ! Handle p(THREAD, JNIHandles::resolve(obj)); ! jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset); ! ! #ifdef SUPPORTS_NATIVE_CX8 ! return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; ! #else ! if (VM_Version::supports_cx8()) { ! return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; ! } else { ! MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); ! ! jlong val = Atomic::load(addr); ! if (val != e) { ! return false; ! } ! Atomic::store(x, addr); ! return true; ! } ! #endif ! } UNSAFE_END UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) { EventThreadPark event; HOTSPOT_THREAD_PARK_BEGIN((uintptr_t) thread->parker(), (int) isAbsolute, time); --- 829,870 ---- UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop e = JNIHandles::resolve(e_h); oop p = JNIHandles::resolve(obj); ! assert_sane_byte_offset(p, offset); ! oop res = HeapAccess<ACCESS_ON_ANONYMOUS | MO_SEQ_CST>::oop_cas_at(x, p, (ptrdiff_t)offset, e); return JNIHandles::make_local(env, res); } UNSAFE_END UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop e = JNIHandles::resolve(e_h); oop p = JNIHandles::resolve(obj); ! assert_sane_byte_offset(p, offset); ! oop res = HeapAccess<ACCESS_ON_ANONYMOUS | MO_SEQ_CST>::oop_cas_at(x, p, (ptrdiff_t)offset, e); ! return res == e; } UNSAFE_END ! #define DEFINE_ATOMICOOP(java_type, Type) \ ! \ ! UNSAFE_ENTRY(java_type, Unsafe_CompareAndExchange##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type e, java_type x)) { \ ! Handle p(THREAD, JNIHandles::resolve(obj)); \ ! assert_sane_byte_offset(p(), offset); \ ! return HeapAccess<ACCESS_ON_ANONYMOUS>::cas_at(x, p(), (ptrdiff_t)offset, e); \ ! } UNSAFE_END \ ! \ ! UNSAFE_ENTRY(java_type, Unsafe_CompareAndSwap##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type e, java_type x)) { \ ! Handle p(THREAD, JNIHandles::resolve(obj)); \ ! assert_sane_byte_offset(p(), offset); \ ! return HeapAccess<ACCESS_ON_ANONYMOUS>::cas_at(x, p(), (ptrdiff_t)offset, e) == e; \ ! } UNSAFE_END \ ! \ ! // END DEFINE_ATOMICOOP. ! DEFINE_ATOMICOOP(jint, Int); ! DEFINE_ATOMICOOP(jlong, Long); UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) { EventThreadPark event; HOTSPOT_THREAD_PARK_BEGIN((uintptr_t) thread->parker(), (int) isAbsolute, time);
< prev index next >