< prev index next >

src/hotspot/share/prims/unsafe.cpp

Print this page

  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  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/classLoader.hpp"
  30 #include "classfile/classLoadInfo.hpp"
  31 #include "classfile/javaClasses.inline.hpp"
  32 #include "classfile/systemDictionary.hpp"
  33 #include "classfile/vmSymbols.hpp"
  34 #include "jfr/jfrEvents.hpp"
  35 #include "memory/allocation.inline.hpp"
  36 #include "memory/resourceArea.hpp"


  37 #include "oops/access.inline.hpp"
  38 #include "oops/fieldStreams.inline.hpp"



  39 #include "oops/instanceKlass.inline.hpp"
  40 #include "oops/klass.inline.hpp"
  41 #include "oops/objArrayOop.inline.hpp"
  42 #include "oops/oop.inline.hpp"
  43 #include "oops/typeArrayOop.inline.hpp"
  44 #include "prims/jvmtiExport.hpp"
  45 #include "prims/unsafe.hpp"

  46 #include "runtime/globals.hpp"
  47 #include "runtime/handles.inline.hpp"
  48 #include "runtime/interfaceSupport.inline.hpp"
  49 #include "runtime/jniHandles.inline.hpp"
  50 #include "runtime/orderAccess.hpp"
  51 #include "runtime/reflection.hpp"
  52 #include "runtime/sharedRuntime.hpp"
  53 #include "runtime/stubRoutines.hpp"
  54 #include "runtime/thread.hpp"
  55 #include "runtime/threadSMR.hpp"
  56 #include "runtime/vmOperations.hpp"
  57 #include "runtime/vm_version.hpp"
  58 #include "services/threadService.hpp"
  59 #include "utilities/align.hpp"
  60 #include "utilities/copy.hpp"
  61 #include "utilities/dtrace.hpp"
  62 #include "utilities/macros.hpp"
  63 
  64 /**
  65  * Implementation of the jdk.internal.misc.Unsafe class

 132 static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
 133   assert_field_offset_sane(p, field_offset);
 134   jlong byte_offset = field_offset_to_byte_offset(field_offset);
 135 
 136   if (sizeof(char*) == sizeof(jint)) {   // (this constant folds!)
 137     return cast_from_oop<address>(p) + (jint) byte_offset;
 138   } else {
 139     return cast_from_oop<address>(p) +        byte_offset;
 140   }
 141 }
 142 
 143 // Externally callable versions:
 144 // (Use these in compiler intrinsics which emulate unsafe primitives.)
 145 jlong Unsafe_field_offset_to_byte_offset(jlong field_offset) {
 146   return field_offset;
 147 }
 148 jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
 149   return byte_offset;
 150 }
 151 
 152 
 153 ///// Data read/writes on the Java heap and in native (off-heap) memory
 154 
 155 /**
 156  * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
 157  */
 158 class GuardUnsafeAccess {
 159   JavaThread* _thread;
 160 
 161 public:
 162   GuardUnsafeAccess(JavaThread* thread) : _thread(thread) {
 163     // native/off-heap access which may raise SIGBUS if accessing
 164     // memory mapped file data in a region of the file which has
 165     // been truncated and is now invalid.
 166     _thread->set_doing_unsafe_access(true);
 167   }
 168 
 169   ~GuardUnsafeAccess() {
 170     _thread->set_doing_unsafe_access(false);
 171   }
 172 };

 208     return x;
 209   }
 210 
 211   jboolean normalize_for_read(jboolean x) {
 212     return x != 0;
 213   }
 214 
 215 public:
 216   MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
 217     : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
 218     assert_field_offset_sane(_obj, offset);
 219   }
 220 
 221   T get() {
 222     GuardUnsafeAccess guard(_thread);
 223     return normalize_for_read(*addr());
 224   }
 225 
 226   void put(T x) {
 227     GuardUnsafeAccess guard(_thread);

 228     *addr() = normalize_for_write(x);
 229   }
 230 
 231 
 232   T get_volatile() {
 233     GuardUnsafeAccess guard(_thread);
 234     volatile T ret = RawAccess<MO_SEQ_CST>::load(addr());
 235     return normalize_for_read(ret);
 236   }
 237 
 238   void put_volatile(T x) {
 239     GuardUnsafeAccess guard(_thread);
 240     RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x));
 241   }
 242 };
 243 






























































 244 // These functions allow a null base pointer with an arbitrary address.
 245 // But if the base pointer is non-null, the offset should make some sense.
 246 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
 247 UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 248   oop p = JNIHandles::resolve(obj);
 249   assert_field_offset_sane(p, offset);
 250   oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 251   return JNIHandles::make_local(THREAD, v);
 252 } UNSAFE_END
 253 
 254 UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 255   oop x = JNIHandles::resolve(x_h);
 256   oop p = JNIHandles::resolve(obj);
 257   assert_field_offset_sane(p, offset);

 258   HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 259 } UNSAFE_END
 260 

































































 261 UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 262   oop p = JNIHandles::resolve(obj);
 263   assert_field_offset_sane(p, offset);
 264   oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 265   return JNIHandles::make_local(THREAD, v);
 266 } UNSAFE_END
 267 
 268 UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 269   oop x = JNIHandles::resolve(x_h);
 270   oop p = JNIHandles::resolve(obj);
 271   assert_field_offset_sane(p, offset);
 272   HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 273 } UNSAFE_END
 274 
 275 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
 276   oop v = *(oop*) (address) addr;
 277   return JNIHandles::make_local(THREAD, v);
 278 } UNSAFE_END
 279 
 280 #define DEFINE_GETSETOOP(java_type, Type) \

 313 // END DEFINE_GETSETOOP_VOLATILE.
 314 
 315 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
 316 DEFINE_GETSETOOP_VOLATILE(jbyte, Byte)
 317 DEFINE_GETSETOOP_VOLATILE(jshort, Short);
 318 DEFINE_GETSETOOP_VOLATILE(jchar, Char);
 319 DEFINE_GETSETOOP_VOLATILE(jint, Int);
 320 DEFINE_GETSETOOP_VOLATILE(jlong, Long);
 321 DEFINE_GETSETOOP_VOLATILE(jfloat, Float);
 322 DEFINE_GETSETOOP_VOLATILE(jdouble, Double);
 323 
 324 #undef DEFINE_GETSETOOP_VOLATILE
 325 
 326 UNSAFE_LEAF(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe)) {
 327   OrderAccess::fence();
 328 } UNSAFE_END
 329 
 330 ////// Allocation requests
 331 
 332 UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) {





 333   JvmtiVMObjectAllocEventCollector oam;
 334   instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(cls), CHECK_NULL);
 335   return JNIHandles::make_local(THREAD, i);
 336 } UNSAFE_END
 337 
 338 UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory0(JNIEnv *env, jobject unsafe, jlong size)) {
 339   size_t sz = (size_t)size;
 340 
 341   assert(is_aligned(sz, HeapWordSize), "sz not aligned");
 342 
 343   void* x = os::malloc(sz, mtOther);
 344 
 345   return addr_to_java(x);
 346 } UNSAFE_END
 347 
 348 UNSAFE_ENTRY(jlong, Unsafe_ReallocateMemory0(JNIEnv *env, jobject unsafe, jlong addr, jlong size)) {
 349   void* p = addr_from_java(addr);
 350   size_t sz = (size_t)size;
 351 
 352   assert(is_aligned(sz, HeapWordSize), "sz not aligned");
 353 
 354   void* x = os::realloc(p, sz, mtOther);

 573   return false;
 574 }
 575 UNSAFE_END
 576 
 577 static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) {
 578   assert(clazz != NULL, "clazz must not be NULL");
 579 
 580   oop mirror = JNIHandles::resolve_non_null(clazz);
 581   Klass* k = java_lang_Class::as_Klass(mirror);
 582 
 583   if (k == NULL || !k->is_array_klass()) {
 584     THROW(vmSymbols::java_lang_InvalidClassException());
 585   } else if (k->is_objArray_klass()) {
 586     base  = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
 587     scale = heapOopSize;
 588   } else if (k->is_typeArray_klass()) {
 589     TypeArrayKlass* tak = TypeArrayKlass::cast(k);
 590     base  = tak->array_header_in_bytes();
 591     assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok");
 592     scale = (1 << tak->log2_element_size());





 593   } else {
 594     ShouldNotReachHere();
 595   }
 596 }
 597 
 598 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) {
 599   int base = 0, scale = 0;
 600   getBaseAndScale(base, scale, clazz, CHECK_0);
 601 
 602   return field_offset_from_byte_offset(base);
 603 } UNSAFE_END
 604 
 605 
 606 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) {
 607   int base = 0, scale = 0;
 608   getBaseAndScale(base, scale, clazz, CHECK_0);
 609 
 610   // This VM packs both fields and array elements down to the byte.
 611   // But watch out:  If this changes, so that array references for
 612   // a given primitive type (say, T_BOOLEAN) use different memory units
 613   // than fields, this method MUST return zero for such arrays.
 614   // For example, the VM used to store sub-word sized fields in full
 615   // words in the object layout, so that accessors like getByte(Object,int)
 616   // did not really do what one might expect for arrays.  Therefore,
 617   // this function used to report a zero scale factor, so that the user
 618   // would know not to attempt to access sub-word array elements.
 619   // // Code for unpacked fields:
 620   // if (scale < wordSize)  return 0;
 621 
 622   // The following allows for a pretty general fieldOffset cookie scheme,
 623   // but requires it to be linear in byte offset.
 624   return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0);
 625 } UNSAFE_END
 626 
 627 






 628 static inline void throw_new(JNIEnv *env, const char *ename) {
 629   jclass cls = env->FindClass(ename);
 630   if (env->ExceptionCheck()) {
 631     env->ExceptionClear();
 632     tty->print_cr("Unsafe: cannot throw %s because FindClass has failed", ename);
 633     return;
 634   }
 635 
 636   env->ThrowNew(cls, NULL);
 637 }
 638 
 639 static jclass Unsafe_DefineClass_impl(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
 640   // Code lifted from JDK 1.3 ClassLoader.c
 641 
 642   jbyte *body;
 643   char *utfName = NULL;
 644   jclass result = 0;
 645   char buf[128];
 646 
 647   assert(data != NULL, "Class bytes must not be NULL");

 827 
 828 
 829 /// JVM_RegisterUnsafeMethods
 830 
 831 #define ADR "J"
 832 
 833 #define LANG "Ljava/lang/"
 834 
 835 #define OBJ LANG "Object;"
 836 #define CLS LANG "Class;"
 837 #define FLD LANG "reflect/Field;"
 838 #define THR LANG "Throwable;"
 839 
 840 #define DC_Args  LANG "String;[BII" LANG "ClassLoader;" "Ljava/security/ProtectionDomain;"
 841 #define DAC_Args CLS "[B[" OBJ
 842 
 843 #define CC (char*)  /*cast a literal from (const char*)*/
 844 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
 845 
 846 #define DECLARE_GETPUTOOP(Type, Desc) \
 847     {CC "get" #Type,      CC "(" OBJ "J)" #Desc,       FN_PTR(Unsafe_Get##Type)}, \
 848     {CC "put" #Type,      CC "(" OBJ "J" #Desc ")V",   FN_PTR(Unsafe_Put##Type)}, \
 849     {CC "get" #Type "Volatile",      CC "(" OBJ "J)" #Desc,       FN_PTR(Unsafe_Get##Type##Volatile)}, \
 850     {CC "put" #Type "Volatile",      CC "(" OBJ "J" #Desc ")V",   FN_PTR(Unsafe_Put##Type##Volatile)}
 851 
 852 
 853 static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
 854     {CC "getReference",         CC "(" OBJ "J)" OBJ "",   FN_PTR(Unsafe_GetReference)},
 855     {CC "putReference",         CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReference)},
 856     {CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ,      FN_PTR(Unsafe_GetReferenceVolatile)},
 857     {CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReferenceVolatile)},
 858 









 859     {CC "getUncompressedObject", CC "(" ADR ")" OBJ,  FN_PTR(Unsafe_GetUncompressedObject)},
 860 
 861     DECLARE_GETPUTOOP(Boolean, Z),
 862     DECLARE_GETPUTOOP(Byte, B),
 863     DECLARE_GETPUTOOP(Short, S),
 864     DECLARE_GETPUTOOP(Char, C),
 865     DECLARE_GETPUTOOP(Int, I),
 866     DECLARE_GETPUTOOP(Long, J),
 867     DECLARE_GETPUTOOP(Float, F),
 868     DECLARE_GETPUTOOP(Double, D),
 869 
 870     {CC "allocateMemory0",    CC "(J)" ADR,              FN_PTR(Unsafe_AllocateMemory0)},
 871     {CC "reallocateMemory0",  CC "(" ADR "J)" ADR,       FN_PTR(Unsafe_ReallocateMemory0)},
 872     {CC "freeMemory0",        CC "(" ADR ")V",           FN_PTR(Unsafe_FreeMemory0)},
 873 
 874     {CC "objectFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_ObjectFieldOffset0)},
 875     {CC "objectFieldOffset1", CC "(" CLS LANG "String;)J", FN_PTR(Unsafe_ObjectFieldOffset1)},
 876     {CC "staticFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_StaticFieldOffset0)},
 877     {CC "staticFieldBase0",   CC "(" FLD ")" OBJ,        FN_PTR(Unsafe_StaticFieldBase0)},
 878     {CC "ensureClassInitialized0", CC "(" CLS ")V",      FN_PTR(Unsafe_EnsureClassInitialized0)},
 879     {CC "arrayBaseOffset0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayBaseOffset0)},
 880     {CC "arrayIndexScale0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayIndexScale0)},

 881 
 882     {CC "defineClass0",       CC "(" DC_Args ")" CLS,    FN_PTR(Unsafe_DefineClass0)},
 883     {CC "allocateInstance",   CC "(" CLS ")" OBJ,        FN_PTR(Unsafe_AllocateInstance)},
 884     {CC "throwException",     CC "(" THR ")V",           FN_PTR(Unsafe_ThrowException)},
 885     {CC "compareAndSetReference",CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSetReference)},
 886     {CC "compareAndSetInt",   CC "(" OBJ "J""I""I"")Z",  FN_PTR(Unsafe_CompareAndSetInt)},
 887     {CC "compareAndSetLong",  CC "(" OBJ "J""J""J"")Z",  FN_PTR(Unsafe_CompareAndSetLong)},
 888     {CC "compareAndExchangeReference", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeReference)},
 889     {CC "compareAndExchangeInt",  CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)},
 890     {CC "compareAndExchangeLong", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)},
 891 
 892     {CC "park",               CC "(ZJ)V",                FN_PTR(Unsafe_Park)},
 893     {CC "unpark",             CC "(" OBJ ")V",           FN_PTR(Unsafe_Unpark)},
 894 
 895     {CC "getLoadAverage0",    CC "([DI)I",               FN_PTR(Unsafe_GetLoadAverage0)},
 896 
 897     {CC "copyMemory0",        CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
 898     {CC "copySwapMemory0",    CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
 899     {CC "writeback0",         CC "(" "J" ")V",           FN_PTR(Unsafe_WriteBack0)},
 900     {CC "writebackPreSync0",  CC "()V",                  FN_PTR(Unsafe_WriteBackPreSync0)},

  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  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/classLoader.hpp"
  30 #include "classfile/classLoadInfo.hpp"
  31 #include "classfile/javaClasses.inline.hpp"
  32 #include "classfile/systemDictionary.hpp"
  33 #include "classfile/vmSymbols.hpp"
  34 #include "jfr/jfrEvents.hpp"
  35 #include "memory/allocation.inline.hpp"
  36 #include "memory/resourceArea.hpp"
  37 #include "logging/log.hpp"
  38 #include "logging/logStream.hpp"
  39 #include "oops/access.inline.hpp"
  40 #include "oops/fieldStreams.inline.hpp"
  41 #include "oops/flatArrayKlass.hpp"
  42 #include "oops/flatArrayOop.inline.hpp"
  43 #include "oops/inlineKlass.inline.hpp"
  44 #include "oops/instanceKlass.inline.hpp"
  45 #include "oops/klass.inline.hpp"
  46 #include "oops/objArrayOop.inline.hpp"
  47 #include "oops/oop.inline.hpp"
  48 #include "oops/typeArrayOop.inline.hpp"
  49 #include "prims/jvmtiExport.hpp"
  50 #include "prims/unsafe.hpp"
  51 #include "runtime/fieldDescriptor.inline.hpp"
  52 #include "runtime/globals.hpp"
  53 #include "runtime/handles.inline.hpp"
  54 #include "runtime/interfaceSupport.inline.hpp"
  55 #include "runtime/jniHandles.inline.hpp"
  56 #include "runtime/orderAccess.hpp"
  57 #include "runtime/reflection.hpp"
  58 #include "runtime/sharedRuntime.hpp"
  59 #include "runtime/stubRoutines.hpp"
  60 #include "runtime/thread.hpp"
  61 #include "runtime/threadSMR.hpp"
  62 #include "runtime/vmOperations.hpp"
  63 #include "runtime/vm_version.hpp"
  64 #include "services/threadService.hpp"
  65 #include "utilities/align.hpp"
  66 #include "utilities/copy.hpp"
  67 #include "utilities/dtrace.hpp"
  68 #include "utilities/macros.hpp"
  69 
  70 /**
  71  * Implementation of the jdk.internal.misc.Unsafe class

 138 static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
 139   assert_field_offset_sane(p, field_offset);
 140   jlong byte_offset = field_offset_to_byte_offset(field_offset);
 141 
 142   if (sizeof(char*) == sizeof(jint)) {   // (this constant folds!)
 143     return cast_from_oop<address>(p) + (jint) byte_offset;
 144   } else {
 145     return cast_from_oop<address>(p) +        byte_offset;
 146   }
 147 }
 148 
 149 // Externally callable versions:
 150 // (Use these in compiler intrinsics which emulate unsafe primitives.)
 151 jlong Unsafe_field_offset_to_byte_offset(jlong field_offset) {
 152   return field_offset;
 153 }
 154 jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
 155   return byte_offset;
 156 }
 157 

 158 ///// Data read/writes on the Java heap and in native (off-heap) memory
 159 
 160 /**
 161  * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
 162  */
 163 class GuardUnsafeAccess {
 164   JavaThread* _thread;
 165 
 166 public:
 167   GuardUnsafeAccess(JavaThread* thread) : _thread(thread) {
 168     // native/off-heap access which may raise SIGBUS if accessing
 169     // memory mapped file data in a region of the file which has
 170     // been truncated and is now invalid.
 171     _thread->set_doing_unsafe_access(true);
 172   }
 173 
 174   ~GuardUnsafeAccess() {
 175     _thread->set_doing_unsafe_access(false);
 176   }
 177 };

 213     return x;
 214   }
 215 
 216   jboolean normalize_for_read(jboolean x) {
 217     return x != 0;
 218   }
 219 
 220 public:
 221   MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
 222     : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
 223     assert_field_offset_sane(_obj, offset);
 224   }
 225 
 226   T get() {
 227     GuardUnsafeAccess guard(_thread);
 228     return normalize_for_read(*addr());
 229   }
 230 
 231   void put(T x) {
 232     GuardUnsafeAccess guard(_thread);
 233     assert(_obj == NULL || !_obj->is_inline_type() || _obj->mark().is_larval_state(), "must be an object instance or a larval inline type");
 234     *addr() = normalize_for_write(x);
 235   }
 236 

 237   T get_volatile() {
 238     GuardUnsafeAccess guard(_thread);
 239     volatile T ret = RawAccess<MO_SEQ_CST>::load(addr());
 240     return normalize_for_read(ret);
 241   }
 242 
 243   void put_volatile(T x) {
 244     GuardUnsafeAccess guard(_thread);
 245     RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x));
 246   }
 247 };
 248 
 249 #ifdef ASSERT
 250 /*
 251  * Get the field descriptor of the field of the given object at the given offset.
 252  */
 253 static bool get_field_descriptor(oop p, jlong offset, fieldDescriptor* fd) {
 254   bool found = false;
 255   Klass* k = p->klass();
 256   if (k->is_instance_klass()) {
 257     InstanceKlass* ik = InstanceKlass::cast(k);
 258     found = ik->find_field_from_offset((int)offset, false, fd);
 259     if (!found && ik->is_mirror_instance_klass()) {
 260       Klass* k2 = java_lang_Class::as_Klass(p);
 261       if (k2->is_instance_klass()) {
 262         ik = InstanceKlass::cast(k2);
 263         found = ik->find_field_from_offset((int)offset, true, fd);
 264       }
 265     }
 266   }
 267   return found;
 268 }
 269 #endif // ASSERT
 270 
 271 static void assert_and_log_unsafe_value_access(oop p, jlong offset, InlineKlass* vk) {
 272   Klass* k = p->klass();
 273 #ifdef ASSERT
 274   if (k->is_instance_klass()) {
 275     assert_field_offset_sane(p, offset);
 276     fieldDescriptor fd;
 277     bool found = get_field_descriptor(p, offset, &fd);
 278     if (found) {
 279       assert(found, "value field not found");
 280       assert(fd.is_inlined(), "field not flat");
 281     } else {
 282       if (log_is_enabled(Trace, valuetypes)) {
 283         log_trace(valuetypes)("not a field in %s at offset " UINT64_FORMAT_X,
 284                               p->klass()->external_name(), (uint64_t)offset);
 285       }
 286     }
 287   } else if (k->is_flatArray_klass()) {
 288     FlatArrayKlass* vak = FlatArrayKlass::cast(k);
 289     int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size();
 290     address dest = (address)((flatArrayOop)p)->value_at_addr(index, vak->layout_helper());
 291     assert(dest == (cast_from_oop<address>(p) + offset), "invalid offset");
 292   } else {
 293     ShouldNotReachHere();
 294   }
 295 #endif // ASSERT
 296   if (log_is_enabled(Trace, valuetypes)) {
 297     if (k->is_flatArray_klass()) {
 298       FlatArrayKlass* vak = FlatArrayKlass::cast(k);
 299       int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size();
 300       address dest = (address)((flatArrayOop)p)->value_at_addr(index, vak->layout_helper());
 301       log_trace(valuetypes)("%s array type %s index %d element size %d offset " UINT64_FORMAT_X " at " INTPTR_FORMAT,
 302                             p->klass()->external_name(), vak->external_name(),
 303                             index, vak->element_byte_size(), (uint64_t)offset, p2i(dest));
 304     } else {
 305       log_trace(valuetypes)("%s field type %s at offset " UINT64_FORMAT_X,
 306                             p->klass()->external_name(), vk->external_name(), (uint64_t)offset);
 307     }
 308   }
 309 }
 310 
 311 // These functions allow a null base pointer with an arbitrary address.
 312 // But if the base pointer is non-null, the offset should make some sense.
 313 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
 314 UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 315   oop p = JNIHandles::resolve(obj);
 316   assert_field_offset_sane(p, offset);
 317   oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 318   return JNIHandles::make_local(THREAD, v);
 319 } UNSAFE_END
 320 
 321 UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 322   oop x = JNIHandles::resolve(x_h);
 323   oop p = JNIHandles::resolve(obj);
 324   assert_field_offset_sane(p, offset);
 325   assert(!p->is_inline_type() || p->mark().is_larval_state(), "must be an object instance or a larval inline type");
 326   HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 327 } UNSAFE_END
 328 
 329 UNSAFE_ENTRY(jlong, Unsafe_ValueHeaderSize(JNIEnv *env, jobject unsafe, jclass c)) {
 330   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 331   InlineKlass* vk = InlineKlass::cast(k);
 332   return vk->first_field_offset();
 333 } UNSAFE_END
 334 
 335 UNSAFE_ENTRY(jboolean, Unsafe_IsFlattenedField(JNIEnv *env, jobject unsafe, jobject o)) {
 336   oop f = JNIHandles::resolve_non_null(o);
 337   Klass* k = java_lang_Class::as_Klass(java_lang_reflect_Field::clazz(f));
 338   int slot = java_lang_reflect_Field::slot(f);
 339   return InstanceKlass::cast(k)->field_is_inlined(slot);
 340 } UNSAFE_END
 341 
 342 UNSAFE_ENTRY(jboolean, Unsafe_IsFlattenedArray(JNIEnv *env, jobject unsafe, jclass c)) {
 343   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 344   return k->is_flatArray_klass();
 345 } UNSAFE_END
 346 
 347 UNSAFE_ENTRY(jobject, Unsafe_UninitializedDefaultValue(JNIEnv *env, jobject unsafe, jclass vc)) {
 348   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc));
 349   InlineKlass* vk = InlineKlass::cast(k);
 350   oop v = vk->default_value();
 351   return JNIHandles::make_local(THREAD, v);
 352 } UNSAFE_END
 353 
 354 UNSAFE_ENTRY(jobject, Unsafe_GetValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass vc)) {
 355   oop base = JNIHandles::resolve(obj);
 356   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc));
 357   InlineKlass* vk = InlineKlass::cast(k);
 358   assert_and_log_unsafe_value_access(base, offset, vk);
 359   Handle base_h(THREAD, base);
 360   oop v = vk->read_inlined_field(base_h(), offset, CHECK_NULL);
 361   return JNIHandles::make_local(THREAD, v);
 362 } UNSAFE_END
 363 
 364 UNSAFE_ENTRY(void, Unsafe_PutValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass vc, jobject value)) {
 365   oop base = JNIHandles::resolve(obj);
 366   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc));
 367   InlineKlass* vk = InlineKlass::cast(k);
 368   assert(!base->is_inline_type() || base->mark().is_larval_state(), "must be an object instance or a larval inline type");
 369   assert_and_log_unsafe_value_access(base, offset, vk);
 370   oop v = JNIHandles::resolve(value);
 371   vk->write_inlined_field(base, offset, v, CHECK);
 372 } UNSAFE_END
 373 
 374 UNSAFE_ENTRY(jobject, Unsafe_MakePrivateBuffer(JNIEnv *env, jobject unsafe, jobject value)) {
 375   oop v = JNIHandles::resolve_non_null(value);
 376   assert(v->is_inline_type(), "must be an inline type instance");
 377   Handle vh(THREAD, v);
 378   InlineKlass* vk = InlineKlass::cast(v->klass());
 379   instanceOop new_value = vk->allocate_instance_buffer(CHECK_NULL);
 380   vk->inline_copy_oop_to_new_oop(vh(),  new_value);
 381   markWord mark = new_value->mark();
 382   new_value->set_mark(mark.enter_larval_state());
 383   return JNIHandles::make_local(THREAD, new_value);
 384 } UNSAFE_END
 385 
 386 UNSAFE_ENTRY(jobject, Unsafe_FinishPrivateBuffer(JNIEnv *env, jobject unsafe, jobject value)) {
 387   oop v = JNIHandles::resolve(value);
 388   assert(v->mark().is_larval_state(), "must be a larval value");
 389   markWord mark = v->mark();
 390   v->set_mark(mark.exit_larval_state());
 391   return JNIHandles::make_local(THREAD, v);
 392 } UNSAFE_END
 393 
 394 UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 395   oop p = JNIHandles::resolve(obj);
 396   assert_field_offset_sane(p, offset);
 397   oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 398   return JNIHandles::make_local(THREAD, v);
 399 } UNSAFE_END
 400 
 401 UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 402   oop x = JNIHandles::resolve(x_h);
 403   oop p = JNIHandles::resolve(obj);
 404   assert_field_offset_sane(p, offset);
 405   HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 406 } UNSAFE_END
 407 
 408 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
 409   oop v = *(oop*) (address) addr;
 410   return JNIHandles::make_local(THREAD, v);
 411 } UNSAFE_END
 412 
 413 #define DEFINE_GETSETOOP(java_type, Type) \

 446 // END DEFINE_GETSETOOP_VOLATILE.
 447 
 448 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
 449 DEFINE_GETSETOOP_VOLATILE(jbyte, Byte)
 450 DEFINE_GETSETOOP_VOLATILE(jshort, Short);
 451 DEFINE_GETSETOOP_VOLATILE(jchar, Char);
 452 DEFINE_GETSETOOP_VOLATILE(jint, Int);
 453 DEFINE_GETSETOOP_VOLATILE(jlong, Long);
 454 DEFINE_GETSETOOP_VOLATILE(jfloat, Float);
 455 DEFINE_GETSETOOP_VOLATILE(jdouble, Double);
 456 
 457 #undef DEFINE_GETSETOOP_VOLATILE
 458 
 459 UNSAFE_LEAF(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe)) {
 460   OrderAccess::fence();
 461 } UNSAFE_END
 462 
 463 ////// Allocation requests
 464 
 465 UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) {
 466   oop mirror = JNIHandles::resolve_non_null(cls);
 467   InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(mirror));
 468   if (k == vmClasses::Object_klass() && vmClasses::Object_klass()->is_abstract()) {
 469     k = vmClasses::Identity_klass();
 470   }
 471   JvmtiVMObjectAllocEventCollector oam;
 472   instanceOop i = InstanceKlass::allocate_instance(k->java_mirror(), CHECK_NULL);
 473   return JNIHandles::make_local(THREAD, i);
 474 } UNSAFE_END
 475 
 476 UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory0(JNIEnv *env, jobject unsafe, jlong size)) {
 477   size_t sz = (size_t)size;
 478 
 479   assert(is_aligned(sz, HeapWordSize), "sz not aligned");
 480 
 481   void* x = os::malloc(sz, mtOther);
 482 
 483   return addr_to_java(x);
 484 } UNSAFE_END
 485 
 486 UNSAFE_ENTRY(jlong, Unsafe_ReallocateMemory0(JNIEnv *env, jobject unsafe, jlong addr, jlong size)) {
 487   void* p = addr_from_java(addr);
 488   size_t sz = (size_t)size;
 489 
 490   assert(is_aligned(sz, HeapWordSize), "sz not aligned");
 491 
 492   void* x = os::realloc(p, sz, mtOther);

 711   return false;
 712 }
 713 UNSAFE_END
 714 
 715 static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) {
 716   assert(clazz != NULL, "clazz must not be NULL");
 717 
 718   oop mirror = JNIHandles::resolve_non_null(clazz);
 719   Klass* k = java_lang_Class::as_Klass(mirror);
 720 
 721   if (k == NULL || !k->is_array_klass()) {
 722     THROW(vmSymbols::java_lang_InvalidClassException());
 723   } else if (k->is_objArray_klass()) {
 724     base  = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
 725     scale = heapOopSize;
 726   } else if (k->is_typeArray_klass()) {
 727     TypeArrayKlass* tak = TypeArrayKlass::cast(k);
 728     base  = tak->array_header_in_bytes();
 729     assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok");
 730     scale = (1 << tak->log2_element_size());
 731   } else if (k->is_flatArray_klass()) {
 732     FlatArrayKlass* vak = FlatArrayKlass::cast(k);
 733     InlineKlass* vklass = vak->element_klass();
 734     base = vak->array_header_in_bytes();
 735     scale = vak->element_byte_size();
 736   } else {
 737     ShouldNotReachHere();
 738   }
 739 }
 740 
 741 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) {
 742   int base = 0, scale = 0;
 743   getBaseAndScale(base, scale, clazz, CHECK_0);
 744 
 745   return field_offset_from_byte_offset(base);
 746 } UNSAFE_END
 747 
 748 
 749 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) {
 750   int base = 0, scale = 0;
 751   getBaseAndScale(base, scale, clazz, CHECK_0);
 752 
 753   // This VM packs both fields and array elements down to the byte.
 754   // But watch out:  If this changes, so that array references for
 755   // a given primitive type (say, T_BOOLEAN) use different memory units
 756   // than fields, this method MUST return zero for such arrays.
 757   // For example, the VM used to store sub-word sized fields in full
 758   // words in the object layout, so that accessors like getByte(Object,int)
 759   // did not really do what one might expect for arrays.  Therefore,
 760   // this function used to report a zero scale factor, so that the user
 761   // would know not to attempt to access sub-word array elements.
 762   // // Code for unpacked fields:
 763   // if (scale < wordSize)  return 0;
 764 
 765   // The following allows for a pretty general fieldOffset cookie scheme,
 766   // but requires it to be linear in byte offset.
 767   return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0);
 768 } UNSAFE_END
 769 
 770 
 771 UNSAFE_ENTRY(jlong, Unsafe_GetObjectSize0(JNIEnv* env, jobject o, jobject obj))
 772   oop p = JNIHandles::resolve(obj);
 773   return p->size() * HeapWordSize;
 774 UNSAFE_END
 775 
 776 
 777 static inline void throw_new(JNIEnv *env, const char *ename) {
 778   jclass cls = env->FindClass(ename);
 779   if (env->ExceptionCheck()) {
 780     env->ExceptionClear();
 781     tty->print_cr("Unsafe: cannot throw %s because FindClass has failed", ename);
 782     return;
 783   }
 784 
 785   env->ThrowNew(cls, NULL);
 786 }
 787 
 788 static jclass Unsafe_DefineClass_impl(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
 789   // Code lifted from JDK 1.3 ClassLoader.c
 790 
 791   jbyte *body;
 792   char *utfName = NULL;
 793   jclass result = 0;
 794   char buf[128];
 795 
 796   assert(data != NULL, "Class bytes must not be NULL");

 976 
 977 
 978 /// JVM_RegisterUnsafeMethods
 979 
 980 #define ADR "J"
 981 
 982 #define LANG "Ljava/lang/"
 983 
 984 #define OBJ LANG "Object;"
 985 #define CLS LANG "Class;"
 986 #define FLD LANG "reflect/Field;"
 987 #define THR LANG "Throwable;"
 988 
 989 #define DC_Args  LANG "String;[BII" LANG "ClassLoader;" "Ljava/security/ProtectionDomain;"
 990 #define DAC_Args CLS "[B[" OBJ
 991 
 992 #define CC (char*)  /*cast a literal from (const char*)*/
 993 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
 994 
 995 #define DECLARE_GETPUTOOP(Type, Desc) \
 996     {CC "get"  #Type,      CC "(" OBJ "J)" #Desc,                 FN_PTR(Unsafe_Get##Type)}, \
 997     {CC "put"  #Type,      CC "(" OBJ "J" #Desc ")V",             FN_PTR(Unsafe_Put##Type)}, \
 998     {CC "get"  #Type "Volatile",      CC "(" OBJ "J)" #Desc,      FN_PTR(Unsafe_Get##Type##Volatile)}, \
 999     {CC "put"  #Type "Volatile",      CC "(" OBJ "J" #Desc ")V",  FN_PTR(Unsafe_Put##Type##Volatile)}
1000 
1001 
1002 static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
1003     {CC "getReference",         CC "(" OBJ "J)" OBJ "",   FN_PTR(Unsafe_GetReference)},
1004     {CC "putReference",         CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReference)},
1005     {CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ,      FN_PTR(Unsafe_GetReferenceVolatile)},
1006     {CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReferenceVolatile)},
1007 
1008     {CC "isFlattenedArray", CC "(" CLS ")Z",                     FN_PTR(Unsafe_IsFlattenedArray)},
1009     {CC "isFlattenedField0", CC "(" OBJ ")Z",                    FN_PTR(Unsafe_IsFlattenedField)},
1010     {CC "getValue",         CC "(" OBJ "J" CLS ")" OBJ,          FN_PTR(Unsafe_GetValue)},
1011     {CC "putValue",         CC "(" OBJ "J" CLS OBJ ")V",         FN_PTR(Unsafe_PutValue)},
1012     {CC "uninitializedDefaultValue", CC "(" CLS ")" OBJ,         FN_PTR(Unsafe_UninitializedDefaultValue)},
1013     {CC "makePrivateBuffer",     CC "(" OBJ ")" OBJ,             FN_PTR(Unsafe_MakePrivateBuffer)},
1014     {CC "finishPrivateBuffer",   CC "(" OBJ ")" OBJ,             FN_PTR(Unsafe_FinishPrivateBuffer)},
1015     {CC "valueHeaderSize",       CC "(" CLS ")J",                FN_PTR(Unsafe_ValueHeaderSize)},
1016 
1017     {CC "getUncompressedObject", CC "(" ADR ")" OBJ,  FN_PTR(Unsafe_GetUncompressedObject)},
1018 
1019     DECLARE_GETPUTOOP(Boolean, Z),
1020     DECLARE_GETPUTOOP(Byte, B),
1021     DECLARE_GETPUTOOP(Short, S),
1022     DECLARE_GETPUTOOP(Char, C),
1023     DECLARE_GETPUTOOP(Int, I),
1024     DECLARE_GETPUTOOP(Long, J),
1025     DECLARE_GETPUTOOP(Float, F),
1026     DECLARE_GETPUTOOP(Double, D),
1027 
1028     {CC "allocateMemory0",    CC "(J)" ADR,              FN_PTR(Unsafe_AllocateMemory0)},
1029     {CC "reallocateMemory0",  CC "(" ADR "J)" ADR,       FN_PTR(Unsafe_ReallocateMemory0)},
1030     {CC "freeMemory0",        CC "(" ADR ")V",           FN_PTR(Unsafe_FreeMemory0)},
1031 
1032     {CC "objectFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_ObjectFieldOffset0)},
1033     {CC "objectFieldOffset1", CC "(" CLS LANG "String;)J", FN_PTR(Unsafe_ObjectFieldOffset1)},
1034     {CC "staticFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_StaticFieldOffset0)},
1035     {CC "staticFieldBase0",   CC "(" FLD ")" OBJ,        FN_PTR(Unsafe_StaticFieldBase0)},
1036     {CC "ensureClassInitialized0", CC "(" CLS ")V",      FN_PTR(Unsafe_EnsureClassInitialized0)},
1037     {CC "arrayBaseOffset0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayBaseOffset0)},
1038     {CC "arrayIndexScale0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayIndexScale0)},
1039     {CC "getObjectSize0",     CC "(Ljava/lang/Object;)J", FN_PTR(Unsafe_GetObjectSize0)},
1040 
1041     {CC "defineClass0",       CC "(" DC_Args ")" CLS,    FN_PTR(Unsafe_DefineClass0)},
1042     {CC "allocateInstance",   CC "(" CLS ")" OBJ,        FN_PTR(Unsafe_AllocateInstance)},
1043     {CC "throwException",     CC "(" THR ")V",           FN_PTR(Unsafe_ThrowException)},
1044     {CC "compareAndSetReference",CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSetReference)},
1045     {CC "compareAndSetInt",   CC "(" OBJ "J""I""I"")Z",  FN_PTR(Unsafe_CompareAndSetInt)},
1046     {CC "compareAndSetLong",  CC "(" OBJ "J""J""J"")Z",  FN_PTR(Unsafe_CompareAndSetLong)},
1047     {CC "compareAndExchangeReference", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeReference)},
1048     {CC "compareAndExchangeInt",  CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)},
1049     {CC "compareAndExchangeLong", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)},
1050 
1051     {CC "park",               CC "(ZJ)V",                FN_PTR(Unsafe_Park)},
1052     {CC "unpark",             CC "(" OBJ ")V",           FN_PTR(Unsafe_Unpark)},
1053 
1054     {CC "getLoadAverage0",    CC "([DI)I",               FN_PTR(Unsafe_GetLoadAverage0)},
1055 
1056     {CC "copyMemory0",        CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
1057     {CC "copySwapMemory0",    CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
1058     {CC "writeback0",         CC "(" "J" ")V",           FN_PTR(Unsafe_WriteBack0)},
1059     {CC "writebackPreSync0",  CC "()V",                  FN_PTR(Unsafe_WriteBackPreSync0)},
< prev index next >