< 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/unsafe.hpp"

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

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

 216     : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
 217     assert_field_offset_sane(_obj, offset);
 218   }
 219 
 220   T get() {
 221     if (_obj == NULL) {
 222       GuardUnsafeAccess guard(_thread);
 223       T ret = RawAccess<>::load(addr());
 224       return normalize_for_read(ret);
 225     } else {
 226       T ret = HeapAccess<>::load_at(_obj, _offset);
 227       return normalize_for_read(ret);
 228     }
 229   }
 230 
 231   void put(T x) {
 232     if (_obj == NULL) {
 233       GuardUnsafeAccess guard(_thread);
 234       RawAccess<>::store(addr(), normalize_for_write(x));
 235     } else {

 236       HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x));
 237     }
 238   }
 239 
 240 
 241   T get_volatile() {
 242     if (_obj == NULL) {
 243       GuardUnsafeAccess guard(_thread);
 244       volatile T ret = RawAccess<MO_SEQ_CST>::load(addr());
 245       return normalize_for_read(ret);
 246     } else {
 247       T ret = HeapAccess<MO_SEQ_CST>::load_at(_obj, _offset);
 248       return normalize_for_read(ret);
 249     }
 250   }
 251 
 252   void put_volatile(T x) {
 253     if (_obj == NULL) {
 254       GuardUnsafeAccess guard(_thread);
 255       RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x));
 256     } else {
 257       HeapAccess<MO_SEQ_CST>::store_at(_obj, _offset, normalize_for_write(x));
 258     }
 259   }
 260 };
 261 






























































 262 // These functions allow a null base pointer with an arbitrary address.
 263 // But if the base pointer is non-null, the offset should make some sense.
 264 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
 265 UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 266   oop p = JNIHandles::resolve(obj);
 267   assert_field_offset_sane(p, offset);
 268   oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 269   return JNIHandles::make_local(THREAD, v);
 270 } UNSAFE_END
 271 
 272 UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 273   oop x = JNIHandles::resolve(x_h);
 274   oop p = JNIHandles::resolve(obj);
 275   assert_field_offset_sane(p, offset);

 276   HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 277 } UNSAFE_END
 278 


























































 279 UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 280   oop p = JNIHandles::resolve(obj);
 281   assert_field_offset_sane(p, offset);
 282   oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 283   return JNIHandles::make_local(THREAD, v);
 284 } UNSAFE_END
 285 
 286 UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 287   oop x = JNIHandles::resolve(x_h);
 288   oop p = JNIHandles::resolve(obj);
 289   assert_field_offset_sane(p, offset);
 290   HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 291 } UNSAFE_END
 292 
 293 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
 294   oop v = *(oop*) (address) addr;
 295   return JNIHandles::make_local(THREAD, v);
 296 } UNSAFE_END
 297 
 298 #define DEFINE_GETSETOOP(java_type, Type) \

 598   return false;
 599 }
 600 UNSAFE_END
 601 
 602 static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) {
 603   assert(clazz != NULL, "clazz must not be NULL");
 604 
 605   oop mirror = JNIHandles::resolve_non_null(clazz);
 606   Klass* k = java_lang_Class::as_Klass(mirror);
 607 
 608   if (k == NULL || !k->is_array_klass()) {
 609     THROW(vmSymbols::java_lang_InvalidClassException());
 610   } else if (k->is_objArray_klass()) {
 611     base  = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
 612     scale = heapOopSize;
 613   } else if (k->is_typeArray_klass()) {
 614     TypeArrayKlass* tak = TypeArrayKlass::cast(k);
 615     base  = tak->array_header_in_bytes();
 616     assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok");
 617     scale = (1 << tak->log2_element_size());





 618   } else {
 619     ShouldNotReachHere();
 620   }
 621 }
 622 
 623 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) {
 624   int base = 0, scale = 0;
 625   getBaseAndScale(base, scale, clazz, CHECK_0);
 626 
 627   return field_offset_from_byte_offset(base);
 628 } UNSAFE_END
 629 
 630 
 631 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) {
 632   int base = 0, scale = 0;
 633   getBaseAndScale(base, scale, clazz, CHECK_0);
 634 
 635   // This VM packs both fields and array elements down to the byte.
 636   // But watch out:  If this changes, so that array references for
 637   // a given primitive type (say, T_BOOLEAN) use different memory units
 638   // than fields, this method MUST return zero for such arrays.
 639   // For example, the VM used to store sub-word sized fields in full
 640   // words in the object layout, so that accessors like getByte(Object,int)
 641   // did not really do what one might expect for arrays.  Therefore,
 642   // this function used to report a zero scale factor, so that the user
 643   // would know not to attempt to access sub-word array elements.
 644   // // Code for unpacked fields:
 645   // if (scale < wordSize)  return 0;
 646 
 647   // The following allows for a pretty general fieldOffset cookie scheme,
 648   // but requires it to be linear in byte offset.
 649   return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0);
 650 } UNSAFE_END
 651 
 652 






 653 static inline void throw_new(JNIEnv *env, const char *ename) {
 654   jclass cls = env->FindClass(ename);
 655   if (env->ExceptionCheck()) {
 656     env->ExceptionClear();
 657     tty->print_cr("Unsafe: cannot throw %s because FindClass has failed", ename);
 658     return;
 659   }
 660 
 661   env->ThrowNew(cls, NULL);
 662 }
 663 
 664 static jclass Unsafe_DefineClass_impl(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
 665   // Code lifted from JDK 1.3 ClassLoader.c
 666 
 667   jbyte *body;
 668   char *utfName = NULL;
 669   jclass result = 0;
 670   char buf[128];
 671 
 672   assert(data != NULL, "Class bytes must not be NULL");

 872 
 873 
 874 /// JVM_RegisterUnsafeMethods
 875 
 876 #define ADR "J"
 877 
 878 #define LANG "Ljava/lang/"
 879 
 880 #define OBJ LANG "Object;"
 881 #define CLS LANG "Class;"
 882 #define FLD LANG "reflect/Field;"
 883 #define THR LANG "Throwable;"
 884 
 885 #define DC_Args  LANG "String;[BII" LANG "ClassLoader;" "Ljava/security/ProtectionDomain;"
 886 #define DAC_Args CLS "[B[" OBJ
 887 
 888 #define CC (char*)  /*cast a literal from (const char*)*/
 889 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
 890 
 891 #define DECLARE_GETPUTOOP(Type, Desc) \
 892     {CC "get" #Type,      CC "(" OBJ "J)" #Desc,       FN_PTR(Unsafe_Get##Type)}, \
 893     {CC "put" #Type,      CC "(" OBJ "J" #Desc ")V",   FN_PTR(Unsafe_Put##Type)}, \
 894     {CC "get" #Type "Volatile",      CC "(" OBJ "J)" #Desc,       FN_PTR(Unsafe_Get##Type##Volatile)}, \
 895     {CC "put" #Type "Volatile",      CC "(" OBJ "J" #Desc ")V",   FN_PTR(Unsafe_Put##Type##Volatile)}
 896 
 897 
 898 static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
 899     {CC "getReference",         CC "(" OBJ "J)" OBJ "",   FN_PTR(Unsafe_GetReference)},
 900     {CC "putReference",         CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReference)},
 901     {CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ,      FN_PTR(Unsafe_GetReferenceVolatile)},
 902     {CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReferenceVolatile)},
 903 








 904     {CC "getUncompressedObject", CC "(" ADR ")" OBJ,  FN_PTR(Unsafe_GetUncompressedObject)},
 905 
 906     DECLARE_GETPUTOOP(Boolean, Z),
 907     DECLARE_GETPUTOOP(Byte, B),
 908     DECLARE_GETPUTOOP(Short, S),
 909     DECLARE_GETPUTOOP(Char, C),
 910     DECLARE_GETPUTOOP(Int, I),
 911     DECLARE_GETPUTOOP(Long, J),
 912     DECLARE_GETPUTOOP(Float, F),
 913     DECLARE_GETPUTOOP(Double, D),
 914 
 915     {CC "allocateMemory0",    CC "(J)" ADR,              FN_PTR(Unsafe_AllocateMemory0)},
 916     {CC "reallocateMemory0",  CC "(" ADR "J)" ADR,       FN_PTR(Unsafe_ReallocateMemory0)},
 917     {CC "freeMemory0",        CC "(" ADR ")V",           FN_PTR(Unsafe_FreeMemory0)},
 918 
 919     {CC "objectFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_ObjectFieldOffset0)},
 920     {CC "objectFieldOffset1", CC "(" CLS LANG "String;)J", FN_PTR(Unsafe_ObjectFieldOffset1)},
 921     {CC "staticFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_StaticFieldOffset0)},
 922     {CC "staticFieldBase0",   CC "(" FLD ")" OBJ,        FN_PTR(Unsafe_StaticFieldBase0)},
 923     {CC "ensureClassInitialized0", CC "(" CLS ")V",      FN_PTR(Unsafe_EnsureClassInitialized0)},
 924     {CC "arrayBaseOffset0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayBaseOffset0)},
 925     {CC "arrayIndexScale0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayIndexScale0)},

 926 
 927     {CC "defineClass0",       CC "(" DC_Args ")" CLS,    FN_PTR(Unsafe_DefineClass0)},
 928     {CC "allocateInstance",   CC "(" CLS ")" OBJ,        FN_PTR(Unsafe_AllocateInstance)},
 929     {CC "throwException",     CC "(" THR ")V",           FN_PTR(Unsafe_ThrowException)},
 930     {CC "compareAndSetReference",CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSetReference)},
 931     {CC "compareAndSetInt",   CC "(" OBJ "J""I""I"")Z",  FN_PTR(Unsafe_CompareAndSetInt)},
 932     {CC "compareAndSetLong",  CC "(" OBJ "J""J""J"")Z",  FN_PTR(Unsafe_CompareAndSetLong)},
 933     {CC "compareAndExchangeReference", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeReference)},
 934     {CC "compareAndExchangeInt",  CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)},
 935     {CC "compareAndExchangeLong", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)},
 936 
 937     {CC "park",               CC "(ZJ)V",                FN_PTR(Unsafe_Park)},
 938     {CC "unpark",             CC "(" OBJ ")V",           FN_PTR(Unsafe_Unpark)},
 939 
 940     {CC "getLoadAverage0",    CC "([DI)I",               FN_PTR(Unsafe_GetLoadAverage0)},
 941 
 942     {CC "copyMemory0",        CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
 943     {CC "copySwapMemory0",    CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
 944     {CC "writeback0",         CC "(" "J" ")V",           FN_PTR(Unsafe_WriteBack0)},
 945     {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/unsafe.hpp"
  50 #include "runtime/fieldDescriptor.inline.hpp"
  51 #include "runtime/globals.hpp"
  52 #include "runtime/handles.inline.hpp"
  53 #include "runtime/interfaceSupport.inline.hpp"
  54 #include "runtime/jniHandles.inline.hpp"
  55 #include "runtime/orderAccess.hpp"
  56 #include "runtime/reflection.hpp"
  57 #include "runtime/sharedRuntime.hpp"
  58 #include "runtime/stubRoutines.hpp"
  59 #include "runtime/thread.hpp"
  60 #include "runtime/threadSMR.hpp"
  61 #include "runtime/vmOperations.hpp"
  62 #include "runtime/vm_version.hpp"
  63 #include "services/threadService.hpp"
  64 #include "utilities/align.hpp"
  65 #include "utilities/copy.hpp"
  66 #include "utilities/dtrace.hpp"
  67 #include "utilities/macros.hpp"
  68 
  69 /**
  70  * Implementation of the jdk.internal.misc.Unsafe class

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

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

 221     : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
 222     assert_field_offset_sane(_obj, offset);
 223   }
 224 
 225   T get() {
 226     if (_obj == NULL) {
 227       GuardUnsafeAccess guard(_thread);
 228       T ret = RawAccess<>::load(addr());
 229       return normalize_for_read(ret);
 230     } else {
 231       T ret = HeapAccess<>::load_at(_obj, _offset);
 232       return normalize_for_read(ret);
 233     }
 234   }
 235 
 236   void put(T x) {
 237     if (_obj == NULL) {
 238       GuardUnsafeAccess guard(_thread);
 239       RawAccess<>::store(addr(), normalize_for_write(x));
 240     } else {
 241       assert(!_obj->is_inline_type() || _obj->mark().is_larval_state(), "must be an object instance or a larval inline type");
 242       HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x));
 243     }
 244   }
 245 

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

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

1009 
1010 
1011 /// JVM_RegisterUnsafeMethods
1012 
1013 #define ADR "J"
1014 
1015 #define LANG "Ljava/lang/"
1016 
1017 #define OBJ LANG "Object;"
1018 #define CLS LANG "Class;"
1019 #define FLD LANG "reflect/Field;"
1020 #define THR LANG "Throwable;"
1021 
1022 #define DC_Args  LANG "String;[BII" LANG "ClassLoader;" "Ljava/security/ProtectionDomain;"
1023 #define DAC_Args CLS "[B[" OBJ
1024 
1025 #define CC (char*)  /*cast a literal from (const char*)*/
1026 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
1027 
1028 #define DECLARE_GETPUTOOP(Type, Desc) \
1029     {CC "get"  #Type,      CC "(" OBJ "J)" #Desc,                 FN_PTR(Unsafe_Get##Type)}, \
1030     {CC "put"  #Type,      CC "(" OBJ "J" #Desc ")V",             FN_PTR(Unsafe_Put##Type)}, \
1031     {CC "get"  #Type "Volatile",      CC "(" OBJ "J)" #Desc,      FN_PTR(Unsafe_Get##Type##Volatile)}, \
1032     {CC "put"  #Type "Volatile",      CC "(" OBJ "J" #Desc ")V",  FN_PTR(Unsafe_Put##Type##Volatile)}
1033 
1034 
1035 static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
1036     {CC "getReference",         CC "(" OBJ "J)" OBJ "",   FN_PTR(Unsafe_GetReference)},
1037     {CC "putReference",         CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReference)},
1038     {CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ,      FN_PTR(Unsafe_GetReferenceVolatile)},
1039     {CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReferenceVolatile)},
1040 
1041     {CC "isFlattenedArray", CC "(" CLS ")Z",                     FN_PTR(Unsafe_IsFlattenedArray)},
1042     {CC "getValue",         CC "(" OBJ "J" CLS ")" OBJ,          FN_PTR(Unsafe_GetValue)},
1043     {CC "putValue",         CC "(" OBJ "J" CLS OBJ ")V",         FN_PTR(Unsafe_PutValue)},
1044     {CC "uninitializedDefaultValue", CC "(" CLS ")" OBJ,         FN_PTR(Unsafe_UninitializedDefaultValue)},
1045     {CC "makePrivateBuffer",     CC "(" OBJ ")" OBJ,             FN_PTR(Unsafe_MakePrivateBuffer)},
1046     {CC "finishPrivateBuffer",   CC "(" OBJ ")" OBJ,             FN_PTR(Unsafe_FinishPrivateBuffer)},
1047     {CC "valueHeaderSize",       CC "(" CLS ")J",                FN_PTR(Unsafe_ValueHeaderSize)},
1048 
1049     {CC "getUncompressedObject", CC "(" ADR ")" OBJ,  FN_PTR(Unsafe_GetUncompressedObject)},
1050 
1051     DECLARE_GETPUTOOP(Boolean, Z),
1052     DECLARE_GETPUTOOP(Byte, B),
1053     DECLARE_GETPUTOOP(Short, S),
1054     DECLARE_GETPUTOOP(Char, C),
1055     DECLARE_GETPUTOOP(Int, I),
1056     DECLARE_GETPUTOOP(Long, J),
1057     DECLARE_GETPUTOOP(Float, F),
1058     DECLARE_GETPUTOOP(Double, D),
1059 
1060     {CC "allocateMemory0",    CC "(J)" ADR,              FN_PTR(Unsafe_AllocateMemory0)},
1061     {CC "reallocateMemory0",  CC "(" ADR "J)" ADR,       FN_PTR(Unsafe_ReallocateMemory0)},
1062     {CC "freeMemory0",        CC "(" ADR ")V",           FN_PTR(Unsafe_FreeMemory0)},
1063 
1064     {CC "objectFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_ObjectFieldOffset0)},
1065     {CC "objectFieldOffset1", CC "(" CLS LANG "String;)J", FN_PTR(Unsafe_ObjectFieldOffset1)},
1066     {CC "staticFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_StaticFieldOffset0)},
1067     {CC "staticFieldBase0",   CC "(" FLD ")" OBJ,        FN_PTR(Unsafe_StaticFieldBase0)},
1068     {CC "ensureClassInitialized0", CC "(" CLS ")V",      FN_PTR(Unsafe_EnsureClassInitialized0)},
1069     {CC "arrayBaseOffset0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayBaseOffset0)},
1070     {CC "arrayIndexScale0",   CC "(" CLS ")I",           FN_PTR(Unsafe_ArrayIndexScale0)},
1071     {CC "getObjectSize0",     CC "(Ljava/lang/Object;)J", FN_PTR(Unsafe_GetObjectSize0)},
1072 
1073     {CC "defineClass0",       CC "(" DC_Args ")" CLS,    FN_PTR(Unsafe_DefineClass0)},
1074     {CC "allocateInstance",   CC "(" CLS ")" OBJ,        FN_PTR(Unsafe_AllocateInstance)},
1075     {CC "throwException",     CC "(" THR ")V",           FN_PTR(Unsafe_ThrowException)},
1076     {CC "compareAndSetReference",CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSetReference)},
1077     {CC "compareAndSetInt",   CC "(" OBJ "J""I""I"")Z",  FN_PTR(Unsafe_CompareAndSetInt)},
1078     {CC "compareAndSetLong",  CC "(" OBJ "J""J""J"")Z",  FN_PTR(Unsafe_CompareAndSetLong)},
1079     {CC "compareAndExchangeReference", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeReference)},
1080     {CC "compareAndExchangeInt",  CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)},
1081     {CC "compareAndExchangeLong", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)},
1082 
1083     {CC "park",               CC "(ZJ)V",                FN_PTR(Unsafe_Park)},
1084     {CC "unpark",             CC "(" OBJ ")V",           FN_PTR(Unsafe_Unpark)},
1085 
1086     {CC "getLoadAverage0",    CC "([DI)I",               FN_PTR(Unsafe_GetLoadAverage0)},
1087 
1088     {CC "copyMemory0",        CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
1089     {CC "copySwapMemory0",    CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
1090     {CC "writeback0",         CC "(" "J" ")V",           FN_PTR(Unsafe_WriteBack0)},
1091     {CC "writebackPreSync0",  CC "()V",                  FN_PTR(Unsafe_WriteBackPreSync0)},
< prev index next >