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) { |
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)}, |