< prev index next >

src/hotspot/share/prims/unsafe.cpp

Print this page




  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


< prev index next >