src/hotspot/share/prims/unsafe.cpp
changeset 48169 9289fcb41aae
parent 48105 8d15b1369c7a
child 49036 bc92debe57e4
equal deleted inserted replaced
48168:cb5d2d4453d0 48169:9289fcb41aae
   144  * Helper class for accessing memory.
   144  * Helper class for accessing memory.
   145  *
   145  *
   146  * Normalizes values and wraps accesses in
   146  * Normalizes values and wraps accesses in
   147  * JavaThread::doing_unsafe_access() if needed.
   147  * JavaThread::doing_unsafe_access() if needed.
   148  */
   148  */
       
   149 template <typename T>
   149 class MemoryAccess : StackObj {
   150 class MemoryAccess : StackObj {
   150   JavaThread* _thread;
   151   JavaThread* _thread;
   151   oop _obj;
   152   oop _obj;
   152   ptrdiff_t _offset;
   153   ptrdiff_t _offset;
   153 
   154 
   154   // Resolves and returns the address of the memory access
   155   // Resolves and returns the address of the memory access.
   155   void* addr() {
   156   // This raw memory access may fault, so we make sure it happens within the
   156     return index_oop_from_field_offset_long(_obj, _offset);
   157   // guarded scope by making the access volatile at least. Since the store
   157   }
   158   // of Thread::set_doing_unsafe_access() is also volatile, these accesses
   158 
   159   // can not be reordered by the compiler. Therefore, if the access triggers
   159   template <typename T>
   160   // a fault, we will know that Thread::doing_unsafe_access() returns true.
   160   T normalize_for_write(T x) {
   161   volatile T* addr() {
       
   162     void* addr = index_oop_from_field_offset_long(_obj, _offset);
       
   163     return static_cast<volatile T*>(addr);
       
   164   }
       
   165 
       
   166   template <typename U>
       
   167   U normalize_for_write(U x) {
   161     return x;
   168     return x;
   162   }
   169   }
   163 
   170 
   164   jboolean normalize_for_write(jboolean x) {
   171   jboolean normalize_for_write(jboolean x) {
   165     return x & 1;
   172     return x & 1;
   166   }
   173   }
   167 
   174 
   168   template <typename T>
   175   template <typename U>
   169   T normalize_for_read(T x) {
   176   U normalize_for_read(U x) {
   170     return x;
   177     return x;
   171   }
   178   }
   172 
   179 
   173   jboolean normalize_for_read(jboolean x) {
   180   jboolean normalize_for_read(jboolean x) {
   174     return x != 0;
   181     return x != 0;
   197   MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
   204   MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
   198     : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
   205     : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
   199     assert_field_offset_sane(_obj, offset);
   206     assert_field_offset_sane(_obj, offset);
   200   }
   207   }
   201 
   208 
   202   template <typename T>
       
   203   T get() {
   209   T get() {
   204     if (oopDesc::is_null(_obj)) {
   210     if (oopDesc::is_null(_obj)) {
   205       GuardUnsafeAccess guard(_thread);
   211       GuardUnsafeAccess guard(_thread);
   206       T ret = RawAccess<>::load((T*)addr());
   212       T ret = RawAccess<>::load(addr());
   207       return normalize_for_read(ret);
   213       return normalize_for_read(ret);
   208     } else {
   214     } else {
   209       T ret = HeapAccess<>::load_at(_obj, _offset);
   215       T ret = HeapAccess<>::load_at(_obj, _offset);
   210       return normalize_for_read(ret);
   216       return normalize_for_read(ret);
   211     }
   217     }
   212   }
   218   }
   213 
   219 
   214   template <typename T>
       
   215   void put(T x) {
   220   void put(T x) {
   216     if (oopDesc::is_null(_obj)) {
   221     if (oopDesc::is_null(_obj)) {
   217       GuardUnsafeAccess guard(_thread);
   222       GuardUnsafeAccess guard(_thread);
   218       RawAccess<>::store((T*)addr(), normalize_for_write(x));
   223       RawAccess<>::store(addr(), normalize_for_write(x));
   219     } else {
   224     } else {
   220       HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x));
   225       HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x));
   221     }
   226     }
   222   }
   227   }
   223 
   228 
   224 
   229 
   225   template <typename T>
       
   226   T get_volatile() {
   230   T get_volatile() {
   227     if (oopDesc::is_null(_obj)) {
   231     if (oopDesc::is_null(_obj)) {
   228       GuardUnsafeAccess guard(_thread);
   232       GuardUnsafeAccess guard(_thread);
   229       volatile T ret = RawAccess<MO_SEQ_CST>::load((volatile T*)addr());
   233       volatile T ret = RawAccess<MO_SEQ_CST>::load(addr());
   230       return normalize_for_read(ret);
   234       return normalize_for_read(ret);
   231     } else {
   235     } else {
   232       T ret = HeapAccess<MO_SEQ_CST>::load_at(_obj, _offset);
   236       T ret = HeapAccess<MO_SEQ_CST>::load_at(_obj, _offset);
   233       return normalize_for_read(ret);
   237       return normalize_for_read(ret);
   234     }
   238     }
   235   }
   239   }
   236 
   240 
   237   template <typename T>
       
   238   void put_volatile(T x) {
   241   void put_volatile(T x) {
   239     if (oopDesc::is_null(_obj)) {
   242     if (oopDesc::is_null(_obj)) {
   240       GuardUnsafeAccess guard(_thread);
   243       GuardUnsafeAccess guard(_thread);
   241       RawAccess<MO_SEQ_CST>::store((volatile T*)addr(), normalize_for_write(x));
   244       RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x));
   242     } else {
   245     } else {
   243       HeapAccess<MO_SEQ_CST>::store_at(_obj, _offset, normalize_for_write(x));
   246       HeapAccess<MO_SEQ_CST>::store_at(_obj, _offset, normalize_for_write(x));
   244     }
   247     }
   245   }
   248   }
   246 };
   249 };
   294 } UNSAFE_END
   297 } UNSAFE_END
   295 
   298 
   296 #define DEFINE_GETSETOOP(java_type, Type) \
   299 #define DEFINE_GETSETOOP(java_type, Type) \
   297  \
   300  \
   298 UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
   301 UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
   299   return MemoryAccess(thread, obj, offset).get<java_type>(); \
   302   return MemoryAccess<java_type>(thread, obj, offset).get(); \
   300 } UNSAFE_END \
   303 } UNSAFE_END \
   301  \
   304  \
   302 UNSAFE_ENTRY(void, Unsafe_Put##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
   305 UNSAFE_ENTRY(void, Unsafe_Put##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
   303   MemoryAccess(thread, obj, offset).put<java_type>(x); \
   306   MemoryAccess<java_type>(thread, obj, offset).put(x); \
   304 } UNSAFE_END \
   307 } UNSAFE_END \
   305  \
   308  \
   306 // END DEFINE_GETSETOOP.
   309 // END DEFINE_GETSETOOP.
   307 
   310 
   308 DEFINE_GETSETOOP(jboolean, Boolean)
   311 DEFINE_GETSETOOP(jboolean, Boolean)
   317 #undef DEFINE_GETSETOOP
   320 #undef DEFINE_GETSETOOP
   318 
   321 
   319 #define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \
   322 #define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \
   320  \
   323  \
   321 UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
   324 UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
   322   return MemoryAccess(thread, obj, offset).get_volatile<java_type>(); \
   325   return MemoryAccess<java_type>(thread, obj, offset).get_volatile(); \
   323 } UNSAFE_END \
   326 } UNSAFE_END \
   324  \
   327  \
   325 UNSAFE_ENTRY(void, Unsafe_Put##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
   328 UNSAFE_ENTRY(void, Unsafe_Put##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
   326   MemoryAccess(thread, obj, offset).put_volatile<java_type>(x); \
   329   MemoryAccess<java_type>(thread, obj, offset).put_volatile(x); \
   327 } UNSAFE_END \
   330 } UNSAFE_END \
   328  \
   331  \
   329 // END DEFINE_GETSETOOP_VOLATILE.
   332 // END DEFINE_GETSETOOP_VOLATILE.
   330 
   333 
   331 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
   334 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)