src/hotspot/share/prims/unsafe.cpp
changeset 55490 3f3dc00a69a5
parent 54629 9ebb614d293d
child 57804 9b7b9f16dfd9
equal deleted inserted replaced
55489:c749ecf599c0 55490:3f3dc00a69a5
   147 
   147 
   148 
   148 
   149 ///// Data read/writes on the Java heap and in native (off-heap) memory
   149 ///// Data read/writes on the Java heap and in native (off-heap) memory
   150 
   150 
   151 /**
   151 /**
       
   152  * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
       
   153  */
       
   154 class GuardUnsafeAccess {
       
   155   JavaThread* _thread;
       
   156 
       
   157 public:
       
   158   GuardUnsafeAccess(JavaThread* thread) : _thread(thread) {
       
   159     // native/off-heap access which may raise SIGBUS if accessing
       
   160     // memory mapped file data in a region of the file which has
       
   161     // been truncated and is now invalid.
       
   162     _thread->set_doing_unsafe_access(true);
       
   163   }
       
   164 
       
   165   ~GuardUnsafeAccess() {
       
   166     _thread->set_doing_unsafe_access(false);
       
   167   }
       
   168 };
       
   169 
       
   170 /**
   152  * Helper class for accessing memory.
   171  * Helper class for accessing memory.
   153  *
   172  *
   154  * Normalizes values and wraps accesses in
   173  * Normalizes values and wraps accesses in
   155  * JavaThread::doing_unsafe_access() if needed.
   174  * JavaThread::doing_unsafe_access() if needed.
   156  */
   175  */
   186   }
   205   }
   187 
   206 
   188   jboolean normalize_for_read(jboolean x) {
   207   jboolean normalize_for_read(jboolean x) {
   189     return x != 0;
   208     return x != 0;
   190   }
   209   }
   191 
       
   192   /**
       
   193    * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
       
   194    */
       
   195   class GuardUnsafeAccess {
       
   196     JavaThread* _thread;
       
   197 
       
   198   public:
       
   199     GuardUnsafeAccess(JavaThread* thread) : _thread(thread) {
       
   200       // native/off-heap access which may raise SIGBUS if accessing
       
   201       // memory mapped file data in a region of the file which has
       
   202       // been truncated and is now invalid
       
   203       _thread->set_doing_unsafe_access(true);
       
   204     }
       
   205 
       
   206     ~GuardUnsafeAccess() {
       
   207       _thread->set_doing_unsafe_access(false);
       
   208     }
       
   209   };
       
   210 
   210 
   211 public:
   211 public:
   212   MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
   212   MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
   213     : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
   213     : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
   214     assert_field_offset_sane(_obj, offset);
   214     assert_field_offset_sane(_obj, offset);
   397   oop srcp = JNIHandles::resolve(srcObj);
   397   oop srcp = JNIHandles::resolve(srcObj);
   398   oop dstp = JNIHandles::resolve(dstObj);
   398   oop dstp = JNIHandles::resolve(dstObj);
   399 
   399 
   400   void* src = index_oop_from_field_offset_long(srcp, srcOffset);
   400   void* src = index_oop_from_field_offset_long(srcp, srcOffset);
   401   void* dst = index_oop_from_field_offset_long(dstp, dstOffset);
   401   void* dst = index_oop_from_field_offset_long(dstp, dstOffset);
   402 
   402   {
   403   Copy::conjoint_memory_atomic(src, dst, sz);
   403     GuardUnsafeAccess guard(thread);
       
   404     if (StubRoutines::unsafe_arraycopy() != NULL) {
       
   405       StubRoutines::UnsafeArrayCopy_stub()(src, dst, sz);
       
   406     } else {
       
   407       Copy::conjoint_memory_atomic(src, dst, sz);
       
   408     }
       
   409   }
   404 } UNSAFE_END
   410 } UNSAFE_END
   405 
   411 
   406 // This function is a leaf since if the source and destination are both in native memory
   412 // This function is a leaf since if the source and destination are both in native memory
   407 // the copy may potentially be very large, and we don't want to disable GC if we can avoid it.
   413 // the copy may potentially be very large, and we don't want to disable GC if we can avoid it.
   408 // If either source or destination (or both) are on the heap, the function will enter VM using
   414 // If either source or destination (or both) are on the heap, the function will enter VM using
   414   if (srcObj == NULL && dstObj == NULL) {
   420   if (srcObj == NULL && dstObj == NULL) {
   415     // Both src & dst are in native memory
   421     // Both src & dst are in native memory
   416     address src = (address)srcOffset;
   422     address src = (address)srcOffset;
   417     address dst = (address)dstOffset;
   423     address dst = (address)dstOffset;
   418 
   424 
   419     Copy::conjoint_swap(src, dst, sz, esz);
   425     {
       
   426       JavaThread* thread = JavaThread::thread_from_jni_environment(env);
       
   427       GuardUnsafeAccess guard(thread);
       
   428       Copy::conjoint_swap(src, dst, sz, esz);
       
   429     }
   420   } else {
   430   } else {
   421     // At least one of src/dst are on heap, transition to VM to access raw pointers
   431     // At least one of src/dst are on heap, transition to VM to access raw pointers
   422 
   432 
   423     JVM_ENTRY_FROM_LEAF(env, void, Unsafe_CopySwapMemory0) {
   433     JVM_ENTRY_FROM_LEAF(env, void, Unsafe_CopySwapMemory0) {
   424       oop srcp = JNIHandles::resolve(srcObj);
   434       oop srcp = JNIHandles::resolve(srcObj);
   425       oop dstp = JNIHandles::resolve(dstObj);
   435       oop dstp = JNIHandles::resolve(dstObj);
   426 
   436 
   427       address src = (address)index_oop_from_field_offset_long(srcp, srcOffset);
   437       address src = (address)index_oop_from_field_offset_long(srcp, srcOffset);
   428       address dst = (address)index_oop_from_field_offset_long(dstp, dstOffset);
   438       address dst = (address)index_oop_from_field_offset_long(dstp, dstOffset);
   429 
   439 
   430       Copy::conjoint_swap(src, dst, sz, esz);
   440       {
       
   441         GuardUnsafeAccess guard(thread);
       
   442         Copy::conjoint_swap(src, dst, sz, esz);
       
   443       }
   431     } JVM_END
   444     } JVM_END
   432   }
   445   }
   433 } UNSAFE_END
   446 } UNSAFE_END
   434 
   447 
   435 ////// Random queries
   448 ////// Random queries