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 |