18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "jni.h" 27 #include "jvm.h" 28 #include "classfile/classFileStream.hpp" 29 #include "classfile/vmSymbols.hpp" 30 #include "jfr/jfrEvents.hpp" 31 #include "memory/allocation.inline.hpp" 32 #include "memory/resourceArea.hpp" 33 #include "oops/access.inline.hpp" 34 #include "oops/fieldStreams.hpp" 35 #include "oops/objArrayOop.inline.hpp" 36 #include "oops/oop.inline.hpp" 37 #include "oops/typeArrayOop.inline.hpp" 38 #include "prims/unsafe.hpp" 39 #include "runtime/atomic.hpp" 40 #include "runtime/globals.hpp" 41 #include "runtime/interfaceSupport.inline.hpp" 42 #include "runtime/jniHandles.inline.hpp" 43 #include "runtime/orderAccess.inline.hpp" 44 #include "runtime/reflection.hpp" 45 #include "runtime/thread.hpp" 46 #include "runtime/threadSMR.hpp" 47 #include "runtime/vm_version.hpp" 48 #include "services/threadService.hpp" 49 #include "utilities/align.hpp" 50 #include "utilities/copy.hpp" 51 #include "utilities/dtrace.hpp" 52 #include "utilities/macros.hpp" 53 54 /** 55 * Implementation of the jdk.internal.misc.Unsafe class 56 */ 57 206 } 207 }; 208 209 public: 210 MemoryAccess(JavaThread* thread, jobject obj, jlong offset) 211 : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) { 212 assert_field_offset_sane(_obj, offset); 213 } 214 215 T get() { 216 if (_obj == NULL) { 217 GuardUnsafeAccess guard(_thread); 218 T ret = RawAccess<>::load(addr()); 219 return normalize_for_read(ret); 220 } else { 221 T ret = HeapAccess<>::load_at(_obj, _offset); 222 return normalize_for_read(ret); 223 } 224 } 225 226 void put(T x) { 227 if (_obj == NULL) { 228 GuardUnsafeAccess guard(_thread); 229 RawAccess<>::store(addr(), normalize_for_write(x)); 230 } else { 231 HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x)); 232 } 233 } 234 235 236 T get_volatile() { 237 if (_obj == NULL) { 238 GuardUnsafeAccess guard(_thread); 239 volatile T ret = RawAccess<MO_SEQ_CST>::load(addr()); 240 return normalize_for_read(ret); 241 } else { 242 T ret = HeapAccess<MO_SEQ_CST>::load_at(_obj, _offset); 243 return normalize_for_read(ret); 244 } 245 } 246 247 void put_volatile(T x) { 248 if (_obj == NULL) { 249 GuardUnsafeAccess guard(_thread); 250 RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x)); 251 } else { 252 HeapAccess<MO_SEQ_CST>::store_at(_obj, _offset, normalize_for_write(x)); 253 } 254 } 255 }; 256 257 // These functions allow a null base pointer with an arbitrary address. 258 // But if the base pointer is non-null, the offset should make some sense. 259 // That is, it should be in the range [0, MAX_OBJECT_SIZE]. 260 UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { 261 oop p = JNIHandles::resolve(obj); 262 assert_field_offset_sane(p, offset); 263 oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset); 264 return JNIHandles::make_local(env, v); 265 } UNSAFE_END 266 267 UNSAFE_ENTRY(void, Unsafe_PutObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { 268 oop x = JNIHandles::resolve(x_h); 269 oop p = JNIHandles::resolve(obj); 270 assert_field_offset_sane(p, offset); 271 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x); 272 } UNSAFE_END 273 274 UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { 275 oop p = JNIHandles::resolve(obj); 276 assert_field_offset_sane(p, offset); 277 oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset); 278 return JNIHandles::make_local(env, v); 279 } UNSAFE_END 280 281 UNSAFE_ENTRY(void, Unsafe_PutObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { 282 oop x = JNIHandles::resolve(x_h); 283 oop p = JNIHandles::resolve(obj); 284 assert_field_offset_sane(p, offset); 285 HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x); 286 } UNSAFE_END 287 288 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) { 289 oop v = *(oop*) (address) addr; 290 return JNIHandles::make_local(env, v); 291 } UNSAFE_END 292 293 UNSAFE_LEAF(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) { 294 #ifdef VM_LITTLE_ENDIAN 295 return false; 296 #else 297 return true; 298 #endif 299 } UNSAFE_END 300 301 UNSAFE_LEAF(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) { 302 return UseUnalignedAccesses; 303 } UNSAFE_END 304 305 #define DEFINE_GETSETOOP(java_type, Type) \ 306 \ 307 UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \ 308 return MemoryAccess<java_type>(thread, obj, offset).get(); \ 309 } UNSAFE_END \ 310 \ 311 UNSAFE_ENTRY(void, Unsafe_Put##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \ 312 MemoryAccess<java_type>(thread, obj, offset).put(x); \ 313 } UNSAFE_END \ 314 \ 315 // END DEFINE_GETSETOOP. 316 317 DEFINE_GETSETOOP(jboolean, Boolean) 318 DEFINE_GETSETOOP(jbyte, Byte) 319 DEFINE_GETSETOOP(jshort, Short); 320 DEFINE_GETSETOOP(jchar, Char); 321 DEFINE_GETSETOOP(jint, Int); 322 DEFINE_GETSETOOP(jlong, Long); 323 DEFINE_GETSETOOP(jfloat, Float); 324 DEFINE_GETSETOOP(jdouble, Double); 325 326 #undef DEFINE_GETSETOOP 327 328 #define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \ 329 \ 330 UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \ 331 return MemoryAccess<java_type>(thread, obj, offset).get_volatile(); \ 332 } UNSAFE_END \ 333 \ 334 UNSAFE_ENTRY(void, Unsafe_Put##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \ 335 MemoryAccess<java_type>(thread, obj, offset).put_volatile(x); \ 336 } UNSAFE_END \ 337 \ 338 // END DEFINE_GETSETOOP_VOLATILE. 339 340 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) 341 DEFINE_GETSETOOP_VOLATILE(jbyte, Byte) 342 DEFINE_GETSETOOP_VOLATILE(jshort, Short); 343 DEFINE_GETSETOOP_VOLATILE(jchar, Char); 344 DEFINE_GETSETOOP_VOLATILE(jint, Int); 345 DEFINE_GETSETOOP_VOLATILE(jlong, Long); 346 DEFINE_GETSETOOP_VOLATILE(jfloat, Float); 347 DEFINE_GETSETOOP_VOLATILE(jdouble, Double); 348 349 #undef DEFINE_GETSETOOP_VOLATILE 350 351 UNSAFE_LEAF(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) { 352 OrderAccess::acquire(); 353 } UNSAFE_END 354 355 UNSAFE_LEAF(void, Unsafe_StoreFence(JNIEnv *env, jobject unsafe)) { 555 return false; 556 } 557 UNSAFE_END 558 559 static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) { 560 assert(clazz != NULL, "clazz must not be NULL"); 561 562 oop mirror = JNIHandles::resolve_non_null(clazz); 563 Klass* k = java_lang_Class::as_Klass(mirror); 564 565 if (k == NULL || !k->is_array_klass()) { 566 THROW(vmSymbols::java_lang_InvalidClassException()); 567 } else if (k->is_objArray_klass()) { 568 base = arrayOopDesc::base_offset_in_bytes(T_OBJECT); 569 scale = heapOopSize; 570 } else if (k->is_typeArray_klass()) { 571 TypeArrayKlass* tak = TypeArrayKlass::cast(k); 572 base = tak->array_header_in_bytes(); 573 assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok"); 574 scale = (1 << tak->log2_element_size()); 575 } else { 576 ShouldNotReachHere(); 577 } 578 } 579 580 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) { 581 int base = 0, scale = 0; 582 getBaseAndScale(base, scale, clazz, CHECK_0); 583 584 return field_offset_from_byte_offset(base); 585 } UNSAFE_END 586 587 588 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) { 589 int base = 0, scale = 0; 590 getBaseAndScale(base, scale, clazz, CHECK_0); 591 592 // This VM packs both fields and array elements down to the byte. 593 // But watch out: If this changes, so that array references for 594 // a given primitive type (say, T_BOOLEAN) use different memory units | 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "jni.h" 27 #include "jvm.h" 28 #include "classfile/classFileStream.hpp" 29 #include "classfile/vmSymbols.hpp" 30 #include "jfr/jfrEvents.hpp" 31 #include "memory/allocation.inline.hpp" 32 #include "memory/resourceArea.hpp" 33 #include "oops/access.inline.hpp" 34 #include "oops/fieldStreams.hpp" 35 #include "oops/objArrayOop.inline.hpp" 36 #include "oops/oop.inline.hpp" 37 #include "oops/typeArrayOop.inline.hpp" 38 #include "oops/valueArrayKlass.hpp" 39 #include "oops/valueArrayOop.hpp" 40 #include "oops/valueArrayOop.inline.hpp" 41 #include "prims/unsafe.hpp" 42 #include "runtime/atomic.hpp" 43 #include "runtime/globals.hpp" 44 #include "runtime/interfaceSupport.inline.hpp" 45 #include "runtime/jniHandles.inline.hpp" 46 #include "runtime/orderAccess.inline.hpp" 47 #include "runtime/reflection.hpp" 48 #include "runtime/thread.hpp" 49 #include "runtime/threadSMR.hpp" 50 #include "runtime/vm_version.hpp" 51 #include "services/threadService.hpp" 52 #include "utilities/align.hpp" 53 #include "utilities/copy.hpp" 54 #include "utilities/dtrace.hpp" 55 #include "utilities/macros.hpp" 56 57 /** 58 * Implementation of the jdk.internal.misc.Unsafe class 59 */ 60 209 } 210 }; 211 212 public: 213 MemoryAccess(JavaThread* thread, jobject obj, jlong offset) 214 : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) { 215 assert_field_offset_sane(_obj, offset); 216 } 217 218 T get() { 219 if (_obj == NULL) { 220 GuardUnsafeAccess guard(_thread); 221 T ret = RawAccess<>::load(addr()); 222 return normalize_for_read(ret); 223 } else { 224 T ret = HeapAccess<>::load_at(_obj, _offset); 225 return normalize_for_read(ret); 226 } 227 } 228 229 void put(T x, TRAPS) { 230 if (_obj == NULL) { 231 GuardUnsafeAccess guard(_thread); 232 RawAccess<>::store(addr(), normalize_for_write(x)); 233 } else { 234 if (EnableValhalla) { 235 if (_obj->klass()->is_value()) { 236 THROW(vmSymbols::java_lang_IllegalAccessError()); 237 } 238 } 239 HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x)); 240 } 241 } 242 243 244 T get_volatile() { 245 if (_obj == NULL) { 246 GuardUnsafeAccess guard(_thread); 247 volatile T ret = RawAccess<MO_SEQ_CST>::load(addr()); 248 return normalize_for_read(ret); 249 } else { 250 T ret = HeapAccess<MO_SEQ_CST>::load_at(_obj, _offset); 251 return normalize_for_read(ret); 252 } 253 } 254 255 void put_volatile(T x, TRAPS) { 256 if (_obj == NULL) { 257 GuardUnsafeAccess guard(_thread); 258 RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x)); 259 } else { 260 if (EnableValhalla) { 261 if (_obj->klass()->is_value()) { 262 THROW(vmSymbols::java_lang_IllegalAccessError()); 263 } 264 } 265 HeapAccess<MO_SEQ_CST>::store_at(_obj, _offset, normalize_for_write(x)); 266 } 267 } 268 }; 269 270 oop read_reference_field(jobject obj, jlong offset, bool is_volatile, TRAPS) { 271 oop p = JNIHandles::resolve(obj); 272 assert_field_offset_sane(p, offset); 273 oop v; 274 bool read = false; 275 if (EnableValhalla && p != NULL) { 276 Klass* k = p->klass(); 277 if (k->is_instance_klass()) { 278 InstanceKlass* ik = InstanceKlass::cast(k); 279 fieldDescriptor fd; 280 bool found = ik->find_field_from_offset((int)offset, false, &fd); 281 if (found) { 282 if (fd.is_flattened()) { 283 ValueKlass* vk = ValueKlass::cast(ik->get_value_field_klass(fd.index())); 284 bool in_heap; 285 Handle p_h(THREAD, p); 286 vk->initialize(CHECK_NULL); // If field is a default value, value class might not be initialized yet 287 // allocate instance 288 v = vk->allocate_buffered_or_heap_instance(&in_heap, CHECK_NULL); 289 // copy value 290 vk->value_store(((char*)(oopDesc*)p_h()) + ik->field_offset(fd.index()), 291 vk->data_for_oop(v), in_heap, true); 292 read = true; 293 } 294 } else { 295 if (ik->is_mirror_instance_klass()) { 296 Klass* k2 = java_lang_Class::as_Klass(p); 297 if (k2->is_instance_klass()) { 298 InstanceKlass* ik2 = InstanceKlass::cast(k2); 299 bool found = ik2->find_field_from_offset((int)offset, true, &fd); 300 if (found) { 301 if (fd.is_flattened()) { 302 ValueKlass* vk = ValueKlass::cast(ik2->get_value_field_klass(fd.index())); 303 bool in_heap; 304 Handle p_h(THREAD, p); 305 vk->initialize(CHECK_NULL); // If field is a default value, value class might not be initialized yet 306 // allocate instance 307 v = vk->allocate_buffered_or_heap_instance(&in_heap, CHECK_NULL); 308 // copy value 309 vk->value_store(((char*)(oopDesc*)p_h()) + ik2->field_offset(fd.index()), 310 vk->data_for_oop(v), in_heap, true); 311 read = true; 312 } else if(fd.is_flattenable()) { 313 if (is_volatile) { 314 v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset); 315 } else { 316 v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset); 317 } 318 if (v == NULL) { 319 // Uninitialized static flattenable field 320 ValueKlass* vk = ValueKlass::cast(ik2->get_value_field_klass(fd.index())); 321 vk->initialize(CHECK_NULL); 322 v = vk->default_value(); 323 read = true; 324 } 325 } 326 } 327 } 328 } 329 } 330 } else if (k->is_valueArray_klass()) { 331 ValueArrayKlass* vak = ValueArrayKlass::cast(k); 332 int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size(); 333 assert(index >= 0 && index < ((arrayOop)p)->length() , "Sanity check"); 334 ValueKlass* vklass = vak->element_klass(); 335 arrayHandle ah(THREAD, (arrayOop)p); 336 bool in_heap; 337 v = vklass->allocate_buffered_or_heap_instance(&in_heap, CHECK_NULL); 338 void* src = ((valueArrayOop)ah())->value_at_addr(index, vak->layout_helper()); 339 vklass->value_store(src, vklass->data_for_oop(v), 340 vak->element_byte_size(), in_heap, false); 341 read = true; 342 } 343 } 344 if (!read) { 345 if (is_volatile) { 346 v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset); 347 } else { 348 v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset); 349 } 350 } 351 return v; 352 } 353 354 void write_reference_field(jobject obj, jlong offset, jobject new_val, bool is_volatile, TRAPS) { 355 oop p = JNIHandles::resolve(obj); 356 assert_field_offset_sane(p, offset); 357 oop v; 358 bool written = false; 359 if (EnableValhalla && p != NULL) { 360 Klass* k = p->klass(); 361 if (k->is_instance_klass()) { 362 if (k->is_value()) { 363 THROW(vmSymbols::java_lang_IllegalAccessError()); 364 } 365 InstanceKlass* ik = InstanceKlass::cast(k); 366 fieldDescriptor fd; 367 bool found = ik->find_field_from_offset((int)offset, false, &fd); 368 if (found) { 369 oop nv = JNIHandles::resolve(new_val); 370 if (fd.is_flattenable() && nv == NULL) { 371 THROW(vmSymbols::java_lang_NullPointerException()); 372 } 373 if (fd.is_flattened()) { 374 ValueKlass* vk = ValueKlass::cast(ik->get_value_field_klass(fd.index())); 375 // copy value 376 vk->value_store(vk->data_for_oop(nv), 377 ((char*)(oopDesc*)p) + ik->field_offset(fd.index()), true, true); 378 written = true; 379 } 380 } else { 381 if (ik->is_mirror_instance_klass()) { 382 Klass* k2 = java_lang_Class::as_Klass(p); 383 if (k2->is_instance_klass()) { 384 InstanceKlass* ik2 = InstanceKlass::cast(k2); 385 bool found = ik2->find_field_from_offset((int)offset, true, &fd); 386 if (found) { 387 oop nv = JNIHandles::resolve(new_val); 388 if (fd.is_flattenable() && nv == NULL) { 389 THROW(vmSymbols::java_lang_NullPointerException()); 390 } 391 if (fd.is_flattened()) { 392 ValueKlass* vk = ValueKlass::cast(ik2->get_value_field_klass(fd.index())); 393 // copy value 394 vk->value_store(vk->data_for_oop(v), 395 ((char*)(oopDesc*)p) + ik2->field_offset(fd.index()), 396 true, true); 397 written = true; 398 } 399 } 400 } 401 } 402 } 403 } else if (k->is_valueArray_klass()) { 404 oop nv = JNIHandles::resolve(new_val); 405 if (nv == NULL) { 406 THROW(vmSymbols::java_lang_NullPointerException()); 407 } 408 ValueArrayKlass* vak = ValueArrayKlass::cast(k); 409 int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size(); 410 assert(index >= 0 && index < ((arrayOop)p)->length() , "Sanity check"); 411 ValueKlass* vklass = vak->element_klass(); 412 void* dest = ((valueArrayOop)p)->value_at_addr(index, vak->layout_helper()); 413 vklass->value_store(vklass->data_for_oop(nv), dest, 414 vak->element_byte_size(), true, false); 415 written = true; 416 } else if (k->is_objArray_klass()) { 417 ObjArrayKlass* oak = ObjArrayKlass::cast(k); 418 oop nv = JNIHandles::resolve(new_val); 419 if (oak->element_klass()->is_value() && nv == NULL) { 420 THROW(vmSymbols::java_lang_NullPointerException()); 421 } 422 } 423 } 424 if (!written) { 425 oop x = JNIHandles::resolve(new_val); 426 if (is_volatile) { 427 HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x); 428 } else { 429 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x); 430 } 431 } 432 } 433 434 // These functions allow a null base pointer with an arbitrary address. 435 // But if the base pointer is non-null, the offset should make some sense. 436 // That is, it should be in the range [0, MAX_OBJECT_SIZE]. 437 UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { 438 oop v = read_reference_field(obj, offset, false, CHECK_NULL); 439 return JNIHandles::make_local(env, v); 440 } UNSAFE_END 441 442 UNSAFE_ENTRY(void, Unsafe_PutObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { 443 write_reference_field(obj, offset, x_h, false, CHECK); 444 } UNSAFE_END 445 446 UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { 447 oop v = read_reference_field(obj, offset, true, CHECK_NULL); 448 return JNIHandles::make_local(env, v); 449 } UNSAFE_END 450 451 UNSAFE_ENTRY(void, Unsafe_PutObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { 452 write_reference_field(obj, offset, x_h, false, CHECK); 453 } UNSAFE_END 454 455 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) { 456 oop v = *(oop*) (address) addr; 457 return JNIHandles::make_local(env, v); 458 } UNSAFE_END 459 460 UNSAFE_LEAF(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) { 461 #ifdef VM_LITTLE_ENDIAN 462 return false; 463 #else 464 return true; 465 #endif 466 } UNSAFE_END 467 468 UNSAFE_LEAF(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) { 469 return UseUnalignedAccesses; 470 } UNSAFE_END 471 472 #define DEFINE_GETSETOOP(java_type, Type) \ 473 \ 474 UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \ 475 return MemoryAccess<java_type>(thread, obj, offset).get(); \ 476 } UNSAFE_END \ 477 \ 478 UNSAFE_ENTRY(void, Unsafe_Put##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \ 479 MemoryAccess<java_type>(thread, obj, offset).put(x, CHECK); \ 480 } UNSAFE_END \ 481 \ 482 // END DEFINE_GETSETOOP. 483 484 DEFINE_GETSETOOP(jboolean, Boolean) 485 DEFINE_GETSETOOP(jbyte, Byte) 486 DEFINE_GETSETOOP(jshort, Short); 487 DEFINE_GETSETOOP(jchar, Char); 488 DEFINE_GETSETOOP(jint, Int); 489 DEFINE_GETSETOOP(jlong, Long); 490 DEFINE_GETSETOOP(jfloat, Float); 491 DEFINE_GETSETOOP(jdouble, Double); 492 493 #undef DEFINE_GETSETOOP 494 495 #define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \ 496 \ 497 UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \ 498 return MemoryAccess<java_type>(thread, obj, offset).get_volatile(); \ 499 } UNSAFE_END \ 500 \ 501 UNSAFE_ENTRY(void, Unsafe_Put##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \ 502 MemoryAccess<java_type>(thread, obj, offset).put_volatile(x, CHECK); \ 503 } UNSAFE_END \ 504 \ 505 // END DEFINE_GETSETOOP_VOLATILE. 506 507 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) 508 DEFINE_GETSETOOP_VOLATILE(jbyte, Byte) 509 DEFINE_GETSETOOP_VOLATILE(jshort, Short); 510 DEFINE_GETSETOOP_VOLATILE(jchar, Char); 511 DEFINE_GETSETOOP_VOLATILE(jint, Int); 512 DEFINE_GETSETOOP_VOLATILE(jlong, Long); 513 DEFINE_GETSETOOP_VOLATILE(jfloat, Float); 514 DEFINE_GETSETOOP_VOLATILE(jdouble, Double); 515 516 #undef DEFINE_GETSETOOP_VOLATILE 517 518 UNSAFE_LEAF(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) { 519 OrderAccess::acquire(); 520 } UNSAFE_END 521 522 UNSAFE_LEAF(void, Unsafe_StoreFence(JNIEnv *env, jobject unsafe)) { 722 return false; 723 } 724 UNSAFE_END 725 726 static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) { 727 assert(clazz != NULL, "clazz must not be NULL"); 728 729 oop mirror = JNIHandles::resolve_non_null(clazz); 730 Klass* k = java_lang_Class::as_Klass(mirror); 731 732 if (k == NULL || !k->is_array_klass()) { 733 THROW(vmSymbols::java_lang_InvalidClassException()); 734 } else if (k->is_objArray_klass()) { 735 base = arrayOopDesc::base_offset_in_bytes(T_OBJECT); 736 scale = heapOopSize; 737 } else if (k->is_typeArray_klass()) { 738 TypeArrayKlass* tak = TypeArrayKlass::cast(k); 739 base = tak->array_header_in_bytes(); 740 assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok"); 741 scale = (1 << tak->log2_element_size()); 742 } else if (k->is_valueArray_klass()) { 743 ValueArrayKlass* vak = ValueArrayKlass::cast(k); 744 base = vak->array_header_in_bytes(); 745 scale = vak->element_byte_size(); 746 } else { 747 ShouldNotReachHere(); 748 } 749 } 750 751 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) { 752 int base = 0, scale = 0; 753 getBaseAndScale(base, scale, clazz, CHECK_0); 754 755 return field_offset_from_byte_offset(base); 756 } UNSAFE_END 757 758 759 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) { 760 int base = 0, scale = 0; 761 getBaseAndScale(base, scale, clazz, CHECK_0); 762 763 // This VM packs both fields and array elements down to the byte. 764 // But watch out: If this changes, so that array references for 765 // a given primitive type (say, T_BOOLEAN) use different memory units |