< prev index next >

src/hotspot/share/prims/unsafe.cpp

Print this page




  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  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/vmSymbols.hpp"
  30 #include "jfr/jfrEvents.hpp"
  31 #include "memory/allocation.inline.hpp"
  32 #include "memory/resourceArea.hpp"
  33 #include "logging/log.hpp"

  34 #include "oops/access.inline.hpp"
  35 #include "oops/fieldStreams.hpp"
  36 #include "oops/objArrayOop.inline.hpp"
  37 #include "oops/oop.inline.hpp"
  38 #include "oops/typeArrayOop.inline.hpp"
  39 #include "oops/valueArrayKlass.hpp"
  40 #include "oops/valueArrayOop.hpp"
  41 #include "oops/valueArrayOop.inline.hpp"
  42 #include "prims/unsafe.hpp"
  43 #include "runtime/atomic.hpp"
  44 #include "runtime/fieldDescriptor.inline.hpp"
  45 #include "runtime/globals.hpp"
  46 #include "runtime/interfaceSupport.inline.hpp"
  47 #include "runtime/jniHandles.inline.hpp"
  48 #include "runtime/orderAccess.hpp"
  49 #include "runtime/reflection.hpp"
  50 #include "runtime/thread.hpp"
  51 #include "runtime/threadSMR.hpp"
  52 #include "runtime/vm_version.hpp"
  53 #include "services/threadService.hpp"


 131   if (p != NULL) {
 132     p = Access<>::resolve(p);
 133   }
 134 
 135   if (sizeof(char*) == sizeof(jint)) {   // (this constant folds!)
 136     return (address)p + (jint) byte_offset;
 137   } else {
 138     return (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 for accessing memory.
 156  *
 157  * Normalizes values and wraps accesses in
 158  * JavaThread::doing_unsafe_access() if needed.
 159  */
 160 template <typename T>
 161 class MemoryAccess : StackObj {
 162   JavaThread* _thread;
 163   oop _obj;
 164   ptrdiff_t _offset;
 165 
 166   // Resolves and returns the address of the memory access.
 167   // This raw memory access may fault, so we make sure it happens within the
 168   // guarded scope by making the access volatile at least. Since the store
 169   // of Thread::set_doing_unsafe_access() is also volatile, these accesses
 170   // can not be reordered by the compiler. Therefore, if the access triggers
 171   // a fault, we will know that Thread::doing_unsafe_access() returns true.


 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 };


 264  * Get the field descriptor of the field of the given object at the given offset.
 265  */
 266 static bool get_field_descriptor(oop p, jlong offset, fieldDescriptor* fd) {
 267   bool found = false;
 268   Klass* k = p->klass();
 269   if (k->is_instance_klass()) {
 270     InstanceKlass* ik = InstanceKlass::cast(k);
 271     found = ik->find_field_from_offset((int)offset, false, fd);
 272     if (!found && ik->is_mirror_instance_klass()) {
 273       Klass* k2 = java_lang_Class::as_Klass(p);
 274       if (k2->is_instance_klass()) {
 275         ik = InstanceKlass::cast(k2);
 276         found = ik->find_field_from_offset((int)offset, true, fd);
 277       }
 278     }
 279   }
 280   return found;
 281 }
 282 #endif // ASSERT
 283 
 284 static void assert_and_log_unsafe_value_type_access(oop p, jlong offset, ValueKlass* vk) {
 285   Klass* k = p->klass();
 286 
 287 #ifdef ASSERT
 288   if (k->is_instance_klass()) {
 289     assert_field_offset_sane(p, offset);
 290     fieldDescriptor fd;
 291     bool found = get_field_descriptor(p, offset, &fd);

 292     assert(found, "value field not found");
 293     assert(fd.is_flattened(), "field not flat");






 294   } else if (k->is_valueArray_klass()) {
 295     ValueArrayKlass* vak = ValueArrayKlass::cast(k);
 296     int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size();
 297     address dest = (address)((valueArrayOop)p)->value_at_addr(index, vak->layout_helper());
 298     assert(dest == ((address)p) + offset, "invalid offset");
 299   } else {
 300     ShouldNotReachHere();
 301   }
 302 #endif // ASSERT
 303 
 304   if (log_is_enabled(Trace, valuetypes)) {
 305     if (k->is_valueArray_klass()) {
 306       ValueArrayKlass* vak = ValueArrayKlass::cast(k);
 307       int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size();
 308       address dest = (address)((valueArrayOop)p)->value_at_addr(index, vak->layout_helper());
 309       log_trace(valuetypes)("array type %s index %d element size %d offset " SIZE_FORMAT_HEX " at " INTPTR_FORMAT,
 310                             vak->external_name(), index, vak->element_byte_size(), offset, p2i(dest));

 311     } else {
 312       log_trace(valuetypes)("field type %s at offset " SIZE_FORMAT_HEX,
 313                             vk->external_name(), offset);
 314     }
 315   }
 316 }
 317 
 318 // These functions allow a null base pointer with an arbitrary address.
 319 // But if the base pointer is non-null, the offset should make some sense.
 320 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
 321 UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 322   oop p = JNIHandles::resolve(obj);
 323   assert_field_offset_sane(p, offset);
 324   oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 325   return JNIHandles::make_local(env, v);
 326 } UNSAFE_END
 327 
 328 UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 329   oop x = JNIHandles::resolve(x_h);
 330   oop p = JNIHandles::resolve(obj);
 331   assert_field_offset_sane(p, offset);

 332   HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 333 } UNSAFE_END
 334 






 335 UNSAFE_ENTRY(jboolean, Unsafe_IsFlattenedArray(JNIEnv *env, jobject unsafe, jclass c)) {
 336   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 337   return k->is_valueArray_klass();
 338 } UNSAFE_END
 339 
 340 UNSAFE_ENTRY(jobject, Unsafe_GetValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass c)) {
 341   oop p = JNIHandles::resolve(obj);
 342   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 343   ValueKlass* vk = ValueKlass::cast(k);
 344   assert_and_log_unsafe_value_type_access(p, offset, vk);
 345   Handle p_h(THREAD, p);
 346   oop v = vk->allocate_instance(CHECK_NULL); // allocate instance
 347   vk->initialize(CHECK_NULL); // If field is a default value, value class might not be initialized yet
 348   vk->value_store(((char*)(oopDesc*)p_h()) + offset,
 349                   vk->data_for_oop(v),
 350                   true, true);
 351   return JNIHandles::make_local(env, v);
 352 } UNSAFE_END
 353 
 354 UNSAFE_ENTRY(void, Unsafe_PutValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass c, jobject value)) {
 355   oop v = JNIHandles::resolve(value);
 356   oop p = JNIHandles::resolve(obj);
 357   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 358   ValueKlass* vk = ValueKlass::cast(k);
 359   assert_and_log_unsafe_value_type_access(p, offset, vk);


 360   vk->value_store(vk->data_for_oop(v),
 361                  ((char*)(oopDesc*)p) + offset, true, true);




















 362 } UNSAFE_END
 363 
 364 UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 365   oop p = JNIHandles::resolve(obj);
 366   assert_field_offset_sane(p, offset);
 367   oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 368   return JNIHandles::make_local(env, v);
 369 } UNSAFE_END
 370 
 371 UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 372   oop x = JNIHandles::resolve(x_h);
 373   oop p = JNIHandles::resolve(obj);
 374   assert_field_offset_sane(p, offset);
 375   HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 376 } UNSAFE_END
 377 
 378 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
 379   oop v = *(oop*) (address) addr;
 380   return JNIHandles::make_local(env, v);
 381 } UNSAFE_END


1118 #define DC_Args  LANG "String;[BII" LANG "ClassLoader;" "Ljava/security/ProtectionDomain;"
1119 #define DAC_Args CLS "[B[" OBJ
1120 
1121 #define CC (char*)  /*cast a literal from (const char*)*/
1122 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
1123 
1124 #define DECLARE_GETPUTOOP(Type, Desc) \
1125     {CC "get" #Type,      CC "(" OBJ "J)" #Desc,       FN_PTR(Unsafe_Get##Type)}, \
1126     {CC "put" #Type,      CC "(" OBJ "J" #Desc ")V",   FN_PTR(Unsafe_Put##Type)}, \
1127     {CC "get" #Type "Volatile",      CC "(" OBJ "J)" #Desc,       FN_PTR(Unsafe_Get##Type##Volatile)}, \
1128     {CC "put" #Type "Volatile",      CC "(" OBJ "J" #Desc ")V",   FN_PTR(Unsafe_Put##Type##Volatile)}
1129 
1130 
1131 static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
1132     {CC "getReference",         CC "(" OBJ "J)" OBJ "",   FN_PTR(Unsafe_GetReference)},
1133     {CC "putReference",         CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReference)},
1134     {CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ,      FN_PTR(Unsafe_GetReferenceVolatile)},
1135     {CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReferenceVolatile)},
1136 
1137     {CC "isFlattenedArray", CC "(" CLS ")Z",               FN_PTR(Unsafe_IsFlattenedArray)},
1138     {CC "getValue",         CC "(" OBJ "J" CLS ")" OBJ "", FN_PTR(Unsafe_GetValue)},
1139     {CC "putValue",         CC "(" OBJ "J" CLS OBJ ")V",   FN_PTR(Unsafe_PutValue)},



1140 
1141     {CC "getUncompressedObject", CC "(" ADR ")" OBJ,  FN_PTR(Unsafe_GetUncompressedObject)},
1142 
1143     DECLARE_GETPUTOOP(Boolean, Z),
1144     DECLARE_GETPUTOOP(Byte, B),
1145     DECLARE_GETPUTOOP(Short, S),
1146     DECLARE_GETPUTOOP(Char, C),
1147     DECLARE_GETPUTOOP(Int, I),
1148     DECLARE_GETPUTOOP(Long, J),
1149     DECLARE_GETPUTOOP(Float, F),
1150     DECLARE_GETPUTOOP(Double, D),
1151 
1152     {CC "allocateMemory0",    CC "(J)" ADR,              FN_PTR(Unsafe_AllocateMemory0)},
1153     {CC "reallocateMemory0",  CC "(" ADR "J)" ADR,       FN_PTR(Unsafe_ReallocateMemory0)},
1154     {CC "freeMemory0",        CC "(" ADR ")V",           FN_PTR(Unsafe_FreeMemory0)},
1155 
1156     {CC "objectFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_ObjectFieldOffset0)},
1157     {CC "objectFieldOffset1", CC "(" CLS LANG "String;)J", FN_PTR(Unsafe_ObjectFieldOffset1)},
1158     {CC "staticFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_StaticFieldOffset0)},
1159     {CC "staticFieldBase0",   CC "(" FLD ")" OBJ,        FN_PTR(Unsafe_StaticFieldBase0)},




  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  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/vmSymbols.hpp"
  30 #include "jfr/jfrEvents.hpp"
  31 #include "memory/allocation.inline.hpp"
  32 #include "memory/resourceArea.hpp"
  33 #include "logging/log.hpp"
  34 #include "logging/logStream.hpp"
  35 #include "oops/access.inline.hpp"
  36 #include "oops/fieldStreams.hpp"
  37 #include "oops/objArrayOop.inline.hpp"
  38 #include "oops/oop.inline.hpp"
  39 #include "oops/typeArrayOop.inline.hpp"
  40 #include "oops/valueArrayKlass.hpp"
  41 #include "oops/valueArrayOop.hpp"
  42 #include "oops/valueArrayOop.inline.hpp"
  43 #include "prims/unsafe.hpp"
  44 #include "runtime/atomic.hpp"
  45 #include "runtime/fieldDescriptor.inline.hpp"
  46 #include "runtime/globals.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/thread.hpp"
  52 #include "runtime/threadSMR.hpp"
  53 #include "runtime/vm_version.hpp"
  54 #include "services/threadService.hpp"


 132   if (p != NULL) {
 133     p = Access<>::resolve(p);
 134   }
 135 
 136   if (sizeof(char*) == sizeof(jint)) {   // (this constant folds!)
 137     return (address)p + (jint) byte_offset;
 138   } else {
 139     return (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 ///// Data read/writes on the Java heap and in native (off-heap) memory
 153 
 154 /**
 155  * Helper class for accessing memory.
 156  *
 157  * Normalizes values and wraps accesses in
 158  * JavaThread::doing_unsafe_access() if needed.
 159  */
 160 template <typename T>
 161 class MemoryAccess : StackObj {
 162   JavaThread* _thread;
 163   oop _obj;
 164   ptrdiff_t _offset;
 165 
 166   // Resolves and returns the address of the memory access.
 167   // This raw memory access may fault, so we make sure it happens within the
 168   // guarded scope by making the access volatile at least. Since the store
 169   // of Thread::set_doing_unsafe_access() is also volatile, these accesses
 170   // can not be reordered by the compiler. Therefore, if the access triggers
 171   // a fault, we will know that Thread::doing_unsafe_access() returns true.


 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       assert(!_obj->is_value() || _obj->mark()->is_larval_state(), "must be an object instance or a larval value");
 237       HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x));
 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 };


 264  * Get the field descriptor of the field of the given object at the given offset.
 265  */
 266 static bool get_field_descriptor(oop p, jlong offset, fieldDescriptor* fd) {
 267   bool found = false;
 268   Klass* k = p->klass();
 269   if (k->is_instance_klass()) {
 270     InstanceKlass* ik = InstanceKlass::cast(k);
 271     found = ik->find_field_from_offset((int)offset, false, fd);
 272     if (!found && ik->is_mirror_instance_klass()) {
 273       Klass* k2 = java_lang_Class::as_Klass(p);
 274       if (k2->is_instance_klass()) {
 275         ik = InstanceKlass::cast(k2);
 276         found = ik->find_field_from_offset((int)offset, true, fd);
 277       }
 278     }
 279   }
 280   return found;
 281 }
 282 #endif // ASSERT
 283 
 284 static void assert_and_log_unsafe_value_access(oop p, jlong offset, ValueKlass* vk) {
 285   Klass* k = p->klass();

 286 #ifdef ASSERT
 287   if (k->is_instance_klass()) {
 288     assert_field_offset_sane(p, offset);
 289     fieldDescriptor fd;
 290     bool found = get_field_descriptor(p, offset, &fd);
 291     if (found) {
 292       assert(found, "value field not found");
 293       assert(fd.is_flattened(), "field not flat");
 294     } else {
 295       if (log_is_enabled(Trace, valuetypes)) {
 296         log_trace(valuetypes)("not a field in %s at offset " SIZE_FORMAT_HEX,
 297                               p->klass()->external_name(), offset);
 298       }
 299     }
 300   } else if (k->is_valueArray_klass()) {
 301     ValueArrayKlass* vak = ValueArrayKlass::cast(k);
 302     int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size();
 303     address dest = (address)((valueArrayOop)p)->value_at_addr(index, vak->layout_helper());
 304     assert(dest == ((address)p) + offset, "invalid offset");
 305   } else {
 306     ShouldNotReachHere();
 307   }
 308 #endif // ASSERT

 309   if (log_is_enabled(Trace, valuetypes)) {
 310     if (k->is_valueArray_klass()) {
 311       ValueArrayKlass* vak = ValueArrayKlass::cast(k);
 312       int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size();
 313       address dest = (address)((valueArrayOop)p)->value_at_addr(index, vak->layout_helper());
 314       log_trace(valuetypes)("%s array type %s index %d element size %d offset " SIZE_FORMAT_HEX " at " INTPTR_FORMAT,
 315                             p->klass()->external_name(), vak->external_name(),
 316                             index, vak->element_byte_size(), offset, p2i(dest));
 317     } else {
 318       log_trace(valuetypes)("%s field type %s at offset " SIZE_FORMAT_HEX,
 319                             p->klass()->external_name(), vk->external_name(), offset);
 320     }
 321   }
 322 }
 323 
 324 // These functions allow a null base pointer with an arbitrary address.
 325 // But if the base pointer is non-null, the offset should make some sense.
 326 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
 327 UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 328   oop p = JNIHandles::resolve(obj);
 329   assert_field_offset_sane(p, offset);
 330   oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 331   return JNIHandles::make_local(env, v);
 332 } UNSAFE_END
 333 
 334 UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 335   oop x = JNIHandles::resolve(x_h);
 336   oop p = JNIHandles::resolve(obj);
 337   assert_field_offset_sane(p, offset);
 338   assert(!p->is_value() || p->mark()->is_larval_state(), "must be an object instance or a larval value");
 339   HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 340 } UNSAFE_END
 341 
 342 UNSAFE_ENTRY(jlong, Unsafe_ValueHeaderSize(JNIEnv *env, jobject unsafe, jclass c)) {
 343   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 344   ValueKlass* vk = ValueKlass::cast(k);
 345   return vk->first_field_offset();
 346 } UNSAFE_END
 347 
 348 UNSAFE_ENTRY(jboolean, Unsafe_IsFlattenedArray(JNIEnv *env, jobject unsafe, jclass c)) {
 349   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 350   return k->is_valueArray_klass();
 351 } UNSAFE_END
 352 
 353 UNSAFE_ENTRY(jobject, Unsafe_GetValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass vc)) {
 354   oop base = JNIHandles::resolve(obj);
 355   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc));
 356   ValueKlass* vk = ValueKlass::cast(k);
 357   assert_and_log_unsafe_value_access(base, offset, vk);
 358   Handle base_h(THREAD, base);
 359   oop v = vk->allocate_instance(CHECK_NULL); // allocate instance
 360   vk->initialize(CHECK_NULL); // If field is a default value, value class might not be initialized yet
 361   vk->value_store(((address)(oopDesc*)base_h()) + offset,
 362                   vk->data_for_oop(v),
 363                   true, true);
 364   return JNIHandles::make_local(env, v);
 365 } UNSAFE_END
 366 
 367 UNSAFE_ENTRY(void, Unsafe_PutValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass vc, jobject value)) {
 368   oop base = JNIHandles::resolve(obj);
 369   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc));

 370   ValueKlass* vk = ValueKlass::cast(k);
 371   assert(!base->is_value() || base->mark()->is_larval_state(), "must be an object instance or a larval value");
 372   assert_and_log_unsafe_value_access(base, offset, vk);
 373   oop v = JNIHandles::resolve(value);
 374   vk->value_store(vk->data_for_oop(v),
 375                  ((address)(oopDesc*)base) + offset, true, true);
 376 } UNSAFE_END
 377 
 378 UNSAFE_ENTRY(jobject, Unsafe_MakePrivateBuffer(JNIEnv *env, jobject unsafe, jobject value)) {
 379   oop v = JNIHandles::resolve_non_null(value);
 380   assert(v->is_value(), "must be a value instance");
 381   Handle vh(THREAD, v);
 382   ValueKlass* vk = ValueKlass::cast(v->klass());
 383   instanceOop new_value = vk->allocate_instance(CHECK_NULL);
 384   vk->value_store(vk->data_for_oop(vh()), vk->data_for_oop(new_value), true, false);
 385   markOop mark = new_value->mark();
 386   new_value->set_mark(mark->enter_larval_state());
 387   return JNIHandles::make_local(env, new_value);
 388 } UNSAFE_END
 389 
 390 UNSAFE_ENTRY(jobject, Unsafe_FinishPrivateBuffer(JNIEnv *env, jobject unsafe, jobject value)) {
 391   oop v = JNIHandles::resolve(value);
 392   assert(v->mark()->is_larval_state(), "must be a larval value");
 393   markOop mark = v->mark();
 394   v->set_mark(mark->exit_larval_state());
 395   return JNIHandles::make_local(env, v);
 396 } UNSAFE_END
 397 
 398 UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 399   oop p = JNIHandles::resolve(obj);
 400   assert_field_offset_sane(p, offset);
 401   oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 402   return JNIHandles::make_local(env, v);
 403 } UNSAFE_END
 404 
 405 UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 406   oop x = JNIHandles::resolve(x_h);
 407   oop p = JNIHandles::resolve(obj);
 408   assert_field_offset_sane(p, offset);
 409   HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 410 } UNSAFE_END
 411 
 412 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
 413   oop v = *(oop*) (address) addr;
 414   return JNIHandles::make_local(env, v);
 415 } UNSAFE_END


1152 #define DC_Args  LANG "String;[BII" LANG "ClassLoader;" "Ljava/security/ProtectionDomain;"
1153 #define DAC_Args CLS "[B[" OBJ
1154 
1155 #define CC (char*)  /*cast a literal from (const char*)*/
1156 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
1157 
1158 #define DECLARE_GETPUTOOP(Type, Desc) \
1159     {CC "get"  #Type,      CC "(" OBJ "J)" #Desc,                 FN_PTR(Unsafe_Get##Type)}, \
1160     {CC "put"  #Type,      CC "(" OBJ "J" #Desc ")V",             FN_PTR(Unsafe_Put##Type)}, \
1161     {CC "get"  #Type "Volatile",      CC "(" OBJ "J)" #Desc,      FN_PTR(Unsafe_Get##Type##Volatile)}, \
1162     {CC "put"  #Type "Volatile",      CC "(" OBJ "J" #Desc ")V",  FN_PTR(Unsafe_Put##Type##Volatile)}
1163 
1164 
1165 static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
1166     {CC "getReference",         CC "(" OBJ "J)" OBJ "",   FN_PTR(Unsafe_GetReference)},
1167     {CC "putReference",         CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReference)},
1168     {CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ,      FN_PTR(Unsafe_GetReferenceVolatile)},
1169     {CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutReferenceVolatile)},
1170 
1171     {CC "isFlattenedArray", CC "(" CLS ")Z",                     FN_PTR(Unsafe_IsFlattenedArray)},
1172     {CC "getValue",         CC "(" OBJ "J" CLS ")" OBJ,          FN_PTR(Unsafe_GetValue)},
1173     {CC "putValue",         CC "(" OBJ "J" CLS OBJ ")V",         FN_PTR(Unsafe_PutValue)},
1174     {CC "makePrivateBuffer",     CC "(" OBJ ")" OBJ,             FN_PTR(Unsafe_MakePrivateBuffer)},
1175     {CC "finishPrivateBuffer",   CC "(" OBJ ")" OBJ,             FN_PTR(Unsafe_FinishPrivateBuffer)},
1176     {CC "valueHeaderSize",       CC "(" CLS ")J",                FN_PTR(Unsafe_ValueHeaderSize)},
1177 
1178     {CC "getUncompressedObject", CC "(" ADR ")" OBJ,  FN_PTR(Unsafe_GetUncompressedObject)},
1179 
1180     DECLARE_GETPUTOOP(Boolean, Z),
1181     DECLARE_GETPUTOOP(Byte, B),
1182     DECLARE_GETPUTOOP(Short, S),
1183     DECLARE_GETPUTOOP(Char, C),
1184     DECLARE_GETPUTOOP(Int, I),
1185     DECLARE_GETPUTOOP(Long, J),
1186     DECLARE_GETPUTOOP(Float, F),
1187     DECLARE_GETPUTOOP(Double, D),
1188 
1189     {CC "allocateMemory0",    CC "(J)" ADR,              FN_PTR(Unsafe_AllocateMemory0)},
1190     {CC "reallocateMemory0",  CC "(" ADR "J)" ADR,       FN_PTR(Unsafe_ReallocateMemory0)},
1191     {CC "freeMemory0",        CC "(" ADR ")V",           FN_PTR(Unsafe_FreeMemory0)},
1192 
1193     {CC "objectFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_ObjectFieldOffset0)},
1194     {CC "objectFieldOffset1", CC "(" CLS LANG "String;)J", FN_PTR(Unsafe_ObjectFieldOffset1)},
1195     {CC "staticFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_StaticFieldOffset0)},
1196     {CC "staticFieldBase0",   CC "(" FLD ")" OBJ,        FN_PTR(Unsafe_StaticFieldBase0)},


< prev index next >