src/hotspot/share/prims/unsafe.cpp
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54629 9ebb614d293d
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
    42 #include "runtime/handles.inline.hpp"
    42 #include "runtime/handles.inline.hpp"
    43 #include "runtime/interfaceSupport.inline.hpp"
    43 #include "runtime/interfaceSupport.inline.hpp"
    44 #include "runtime/jniHandles.inline.hpp"
    44 #include "runtime/jniHandles.inline.hpp"
    45 #include "runtime/orderAccess.hpp"
    45 #include "runtime/orderAccess.hpp"
    46 #include "runtime/reflection.hpp"
    46 #include "runtime/reflection.hpp"
       
    47 #include "runtime/sharedRuntime.hpp"
    47 #include "runtime/thread.hpp"
    48 #include "runtime/thread.hpp"
    48 #include "runtime/threadSMR.hpp"
    49 #include "runtime/threadSMR.hpp"
    49 #include "runtime/vm_version.hpp"
    50 #include "runtime/vm_version.hpp"
    50 #include "services/threadService.hpp"
    51 #include "services/threadService.hpp"
    51 #include "utilities/align.hpp"
    52 #include "utilities/align.hpp"
   145   return byte_offset;
   146   return byte_offset;
   146 }
   147 }
   147 
   148 
   148 
   149 
   149 ///// Data read/writes on the Java heap and in native (off-heap) memory
   150 ///// Data read/writes on the Java heap and in native (off-heap) memory
       
   151 
       
   152 /**
       
   153  * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
       
   154  */
       
   155 class GuardUnsafeAccess {
       
   156   JavaThread* _thread;
       
   157 
       
   158 public:
       
   159   GuardUnsafeAccess(JavaThread* thread) : _thread(thread) {
       
   160     // native/off-heap access which may raise SIGBUS if accessing
       
   161     // memory mapped file data in a region of the file which has
       
   162     // been truncated and is now invalid.
       
   163     _thread->set_doing_unsafe_access(true);
       
   164   }
       
   165 
       
   166   ~GuardUnsafeAccess() {
       
   167     _thread->set_doing_unsafe_access(false);
       
   168   }
       
   169 };
   150 
   170 
   151 /**
   171 /**
   152  * Helper class for accessing memory.
   172  * Helper class for accessing memory.
   153  *
   173  *
   154  * Normalizes values and wraps accesses in
   174  * Normalizes values and wraps accesses in
   187 
   207 
   188   jboolean normalize_for_read(jboolean x) {
   208   jboolean normalize_for_read(jboolean x) {
   189     return x != 0;
   209     return x != 0;
   190   }
   210   }
   191 
   211 
   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 
       
   211 public:
   212 public:
   212   MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
   213   MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
   213     : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
   214     : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
   214     assert_field_offset_sane(_obj, offset);
   215     assert_field_offset_sane(_obj, offset);
   215   }
   216   }
   397   oop srcp = JNIHandles::resolve(srcObj);
   398   oop srcp = JNIHandles::resolve(srcObj);
   398   oop dstp = JNIHandles::resolve(dstObj);
   399   oop dstp = JNIHandles::resolve(dstObj);
   399 
   400 
   400   void* src = index_oop_from_field_offset_long(srcp, srcOffset);
   401   void* src = index_oop_from_field_offset_long(srcp, srcOffset);
   401   void* dst = index_oop_from_field_offset_long(dstp, dstOffset);
   402   void* dst = index_oop_from_field_offset_long(dstp, dstOffset);
   402 
   403   {
   403   Copy::conjoint_memory_atomic(src, dst, sz);
   404     GuardUnsafeAccess guard(thread);
       
   405     if (StubRoutines::unsafe_arraycopy() != NULL) {
       
   406       StubRoutines::UnsafeArrayCopy_stub()(src, dst, sz);
       
   407     } else {
       
   408       Copy::conjoint_memory_atomic(src, dst, sz);
       
   409     }
       
   410   }
   404 } UNSAFE_END
   411 } UNSAFE_END
   405 
   412 
   406 // This function is a leaf since if the source and destination are both in native memory
   413 // 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.
   414 // 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
   415 // If either source or destination (or both) are on the heap, the function will enter VM using
   414   if (srcObj == NULL && dstObj == NULL) {
   421   if (srcObj == NULL && dstObj == NULL) {
   415     // Both src & dst are in native memory
   422     // Both src & dst are in native memory
   416     address src = (address)srcOffset;
   423     address src = (address)srcOffset;
   417     address dst = (address)dstOffset;
   424     address dst = (address)dstOffset;
   418 
   425 
   419     Copy::conjoint_swap(src, dst, sz, esz);
   426     {
       
   427       JavaThread* thread = JavaThread::thread_from_jni_environment(env);
       
   428       GuardUnsafeAccess guard(thread);
       
   429       Copy::conjoint_swap(src, dst, sz, esz);
       
   430     }
   420   } else {
   431   } else {
   421     // At least one of src/dst are on heap, transition to VM to access raw pointers
   432     // At least one of src/dst are on heap, transition to VM to access raw pointers
   422 
   433 
   423     JVM_ENTRY_FROM_LEAF(env, void, Unsafe_CopySwapMemory0) {
   434     JVM_ENTRY_FROM_LEAF(env, void, Unsafe_CopySwapMemory0) {
   424       oop srcp = JNIHandles::resolve(srcObj);
   435       oop srcp = JNIHandles::resolve(srcObj);
   425       oop dstp = JNIHandles::resolve(dstObj);
   436       oop dstp = JNIHandles::resolve(dstObj);
   426 
   437 
   427       address src = (address)index_oop_from_field_offset_long(srcp, srcOffset);
   438       address src = (address)index_oop_from_field_offset_long(srcp, srcOffset);
   428       address dst = (address)index_oop_from_field_offset_long(dstp, dstOffset);
   439       address dst = (address)index_oop_from_field_offset_long(dstp, dstOffset);
   429 
   440 
   430       Copy::conjoint_swap(src, dst, sz, esz);
   441       {
       
   442         GuardUnsafeAccess guard(thread);
       
   443         Copy::conjoint_swap(src, dst, sz, esz);
       
   444       }
   431     } JVM_END
   445     } JVM_END
   432   }
   446   }
       
   447 } UNSAFE_END
       
   448 
       
   449 UNSAFE_LEAF (void, Unsafe_WriteBack0(JNIEnv *env, jobject unsafe, jlong line)) {
       
   450   assert(VM_Version::supports_data_cache_line_flush(), "should not get here");
       
   451 #ifdef ASSERT
       
   452   if (TraceMemoryWriteback) {
       
   453     tty->print_cr("Unsafe: writeback 0x%p", addr_from_java(line));
       
   454   }
       
   455 #endif
       
   456 
       
   457   assert(StubRoutines::data_cache_writeback() != NULL, "sanity");
       
   458   (StubRoutines::DataCacheWriteback_stub())(addr_from_java(line));
       
   459 } UNSAFE_END
       
   460 
       
   461 static void doWriteBackSync0(bool is_pre)
       
   462 {
       
   463   assert(StubRoutines::data_cache_writeback_sync() != NULL, "sanity");
       
   464   (StubRoutines::DataCacheWritebackSync_stub())(is_pre);
       
   465 }
       
   466 
       
   467 UNSAFE_LEAF (void, Unsafe_WriteBackPreSync0(JNIEnv *env, jobject unsafe)) {
       
   468   assert(VM_Version::supports_data_cache_line_flush(), "should not get here");
       
   469 #ifdef ASSERT
       
   470   if (TraceMemoryWriteback) {
       
   471       tty->print_cr("Unsafe: writeback pre-sync");
       
   472   }
       
   473 #endif
       
   474 
       
   475   doWriteBackSync0(true);
       
   476 } UNSAFE_END
       
   477 
       
   478 UNSAFE_LEAF (void, Unsafe_WriteBackPostSync0(JNIEnv *env, jobject unsafe)) {
       
   479   assert(VM_Version::supports_data_cache_line_flush(), "should not get here");
       
   480 #ifdef ASSERT
       
   481   if (TraceMemoryWriteback) {
       
   482     tty->print_cr("Unsafe: writeback pre-sync");
       
   483   }
       
   484 #endif
       
   485 
       
   486   doWriteBackSync0(false);
   433 } UNSAFE_END
   487 } UNSAFE_END
   434 
   488 
   435 ////// Random queries
   489 ////// Random queries
   436 
   490 
   437 static jlong find_field_offset(jclass clazz, jstring name, TRAPS) {
   491 static jlong find_field_offset(jclass clazz, jstring name, TRAPS) {
   613 
   667 
   614   if (UsePerfData) {
   668   if (UsePerfData) {
   615     ClassLoader::unsafe_defineClassCallCounter()->inc();
   669     ClassLoader::unsafe_defineClassCallCounter()->inc();
   616   }
   670   }
   617 
   671 
   618   body = NEW_C_HEAP_ARRAY(jbyte, length, mtInternal);
   672   body = NEW_C_HEAP_ARRAY_RETURN_NULL(jbyte, length, mtInternal);
   619   if (body == NULL) {
   673   if (body == NULL) {
   620     throw_new(env, "java/lang/OutOfMemoryError");
   674     throw_new(env, "java/lang/OutOfMemoryError");
   621     return 0;
   675     return 0;
   622   }
   676   }
   623 
   677 
   629   if (name != NULL) {
   683   if (name != NULL) {
   630     uint len = env->GetStringUTFLength(name);
   684     uint len = env->GetStringUTFLength(name);
   631     int unicode_len = env->GetStringLength(name);
   685     int unicode_len = env->GetStringLength(name);
   632 
   686 
   633     if (len >= sizeof(buf)) {
   687     if (len >= sizeof(buf)) {
   634       utfName = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
   688       utfName = NEW_C_HEAP_ARRAY_RETURN_NULL(char, len + 1, mtInternal);
   635       if (utfName == NULL) {
   689       if (utfName == NULL) {
   636         throw_new(env, "java/lang/OutOfMemoryError");
   690         throw_new(env, "java/lang/OutOfMemoryError");
   637         goto free_body;
   691         goto free_body;
   638       }
   692       }
   639     } else {
   693     } else {
   734   jint length = typeArrayOop(JNIHandles::resolve_non_null(data))->length();
   788   jint length = typeArrayOop(JNIHandles::resolve_non_null(data))->length();
   735   assert(length >= 0, "class_bytes_length must not be negative: %d", length);
   789   assert(length >= 0, "class_bytes_length must not be negative: %d", length);
   736 
   790 
   737   int class_bytes_length = (int) length;
   791   int class_bytes_length = (int) length;
   738 
   792 
   739   u1* class_bytes = NEW_C_HEAP_ARRAY(u1, length, mtInternal);
   793   u1* class_bytes = NEW_C_HEAP_ARRAY_RETURN_NULL(u1, length, mtInternal);
   740   if (class_bytes == NULL) {
   794   if (class_bytes == NULL) {
   741     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   795     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   742   }
   796   }
   743 
   797 
   744   // caller responsible to free it:
   798   // caller responsible to free it:
   819   if (anon_klass != NULL) {
   873   if (anon_klass != NULL) {
   820     res_jh = JNIHandles::make_local(env, anon_klass->java_mirror());
   874     res_jh = JNIHandles::make_local(env, anon_klass->java_mirror());
   821   }
   875   }
   822 
   876 
   823   // try/finally clause:
   877   // try/finally clause:
   824   if (temp_alloc != NULL) {
   878   FREE_C_HEAP_ARRAY(u1, temp_alloc);
   825     FREE_C_HEAP_ARRAY(u1, temp_alloc);
       
   826   }
       
   827 
   879 
   828   // The anonymous class loader data has been artificially been kept alive to
   880   // The anonymous class loader data has been artificially been kept alive to
   829   // this point.   The mirror and any instances of this class have to keep
   881   // this point.   The mirror and any instances of this class have to keep
   830   // it alive afterwards.
   882   // it alive afterwards.
   831   if (anon_klass != NULL) {
   883   if (anon_klass != NULL) {
   881   oop x = JNIHandles::resolve(x_h);
   933   oop x = JNIHandles::resolve(x_h);
   882   oop e = JNIHandles::resolve(e_h);
   934   oop e = JNIHandles::resolve(e_h);
   883   oop p = JNIHandles::resolve(obj);
   935   oop p = JNIHandles::resolve(obj);
   884   assert_field_offset_sane(p, offset);
   936   assert_field_offset_sane(p, offset);
   885   oop ret = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_atomic_cmpxchg_at(x, p, (ptrdiff_t)offset, e);
   937   oop ret = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_atomic_cmpxchg_at(x, p, (ptrdiff_t)offset, e);
   886   return oopDesc::equals(ret, e);
   938   return ret == e;
   887 } UNSAFE_END
   939 } UNSAFE_END
   888 
   940 
   889 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
   941 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
   890   oop p = JNIHandles::resolve(obj);
   942   oop p = JNIHandles::resolve(obj);
   891   if (p == NULL) {
   943   if (p == NULL) {
  1058 
  1110 
  1059     {CC "getLoadAverage0",    CC "([DI)I",               FN_PTR(Unsafe_GetLoadAverage0)},
  1111     {CC "getLoadAverage0",    CC "([DI)I",               FN_PTR(Unsafe_GetLoadAverage0)},
  1060 
  1112 
  1061     {CC "copyMemory0",        CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
  1113     {CC "copyMemory0",        CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
  1062     {CC "copySwapMemory0",    CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
  1114     {CC "copySwapMemory0",    CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
       
  1115     {CC "writeback0",         CC "(" "J" ")V",           FN_PTR(Unsafe_WriteBack0)},
       
  1116     {CC "writebackPreSync0",  CC "()V",                  FN_PTR(Unsafe_WriteBackPreSync0)},
       
  1117     {CC "writebackPostSync0", CC "()V",                  FN_PTR(Unsafe_WriteBackPostSync0)},
  1063     {CC "setMemory0",         CC "(" OBJ "JJB)V",        FN_PTR(Unsafe_SetMemory0)},
  1118     {CC "setMemory0",         CC "(" OBJ "JJB)V",        FN_PTR(Unsafe_SetMemory0)},
  1064 
  1119 
  1065     {CC "defineAnonymousClass0", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass0)},
  1120     {CC "defineAnonymousClass0", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass0)},
  1066 
  1121 
  1067     {CC "shouldBeInitialized0", CC "(" CLS ")Z",         FN_PTR(Unsafe_ShouldBeInitialized0)},
  1122     {CC "shouldBeInitialized0", CC "(" CLS ")Z",         FN_PTR(Unsafe_ShouldBeInitialized0)},