< prev index next >

src/hotspot/share/prims/unsafe.cpp

Print this page




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


































 283 // These functions allow a null base pointer with an arbitrary address.
 284 // But if the base pointer is non-null, the offset should make some sense.
 285 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
 286 UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 287   oop p = JNIHandles::resolve(obj);
 288   assert_field_offset_sane(p, offset);
 289   oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 290   return JNIHandles::make_local(env, v);
 291 } UNSAFE_END
 292 
 293 UNSAFE_ENTRY(void, Unsafe_PutObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 294   oop x = JNIHandles::resolve(x_h);
 295   oop p = JNIHandles::resolve(obj);
 296   assert_field_offset_sane(p, offset);
 297   HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 298 } UNSAFE_END
 299 





 300 UNSAFE_ENTRY(jobject, Unsafe_GetValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass c)) {
 301   oop p = JNIHandles::resolve(obj);
 302   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 303   ValueKlass* vk = ValueKlass::cast(k);
 304 
 305 #ifdef ASSERT
 306   assert_field_offset_sane(p, offset);
 307   fieldDescriptor fd;
 308   bool found = get_field_descriptor(p, offset, &fd);
 309   assert(found, "value field not found");
 310   assert(fd.is_flattened(), "field not flat");
 311 #endif // ASSERT
 312 
 313   if (log_is_enabled(Trace, valuetypes)) {
 314     log_trace(valuetypes)("getValue: field type %s at offset " SIZE_FORMAT_HEX,
 315                           vk->external_name(), offset);
 316   }
 317 
 318   Handle p_h(THREAD, p);
 319   bool in_heap;
 320   oop v = vk->allocate_buffered_or_heap_instance(&in_heap, CHECK_NULL); // allocate instance
 321   vk->initialize(CHECK_NULL); // If field is a default value, value class might not be initialized yet
 322   vk->value_store(((char*)(oopDesc*)p_h()) + offset,
 323                   vk->data_for_oop(v),
 324                   in_heap, true);                  
 325   return JNIHandles::make_local(env, v);
 326 } UNSAFE_END
 327 
 328 UNSAFE_ENTRY(void, Unsafe_PutValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass c, jobject value)) {
 329   oop v = JNIHandles::resolve(value);
 330   oop p = JNIHandles::resolve(obj);
 331   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 332   ValueKlass* vk = ValueKlass::cast(k);
 333 
 334 #ifdef ASSERT
 335   assert_field_offset_sane(p, offset);
 336   fieldDescriptor fd;
 337   bool found = get_field_descriptor(p, offset, &fd);
 338   assert(found, "value field not found");
 339   assert(fd.is_flattened(), "field not flat");
 340 #endif  // ASSERT
 341 
 342   if (log_is_enabled(Trace, valuetypes)) {
 343     log_trace(valuetypes)("putValue: field type %s at offset " SIZE_FORMAT_HEX,
 344                           vk->external_name(), offset);
 345   }
 346   vk->value_store(vk->data_for_oop(v),
 347                  ((char*)(oopDesc*)p) + offset, true, true);
 348 } UNSAFE_END
 349 
 350 UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 351   oop p = JNIHandles::resolve(obj);
 352   assert_field_offset_sane(p, offset);
 353   oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 354   return JNIHandles::make_local(env, v);
 355 } UNSAFE_END
 356 
 357 UNSAFE_ENTRY(void, Unsafe_PutObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 358   oop x = JNIHandles::resolve(x_h);
 359   oop p = JNIHandles::resolve(obj);
 360   assert_field_offset_sane(p, offset);
 361   HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 362 } UNSAFE_END
 363 
 364 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
 365   oop v = *(oop*) (address) addr;


 631   return false;
 632 }
 633 UNSAFE_END
 634 
 635 static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) {
 636   assert(clazz != NULL, "clazz must not be NULL");
 637 
 638   oop mirror = JNIHandles::resolve_non_null(clazz);
 639   Klass* k = java_lang_Class::as_Klass(mirror);
 640 
 641   if (k == NULL || !k->is_array_klass()) {
 642     THROW(vmSymbols::java_lang_InvalidClassException());
 643   } else if (k->is_objArray_klass()) {
 644     base  = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
 645     scale = heapOopSize;
 646   } else if (k->is_typeArray_klass()) {
 647     TypeArrayKlass* tak = TypeArrayKlass::cast(k);
 648     base  = tak->array_header_in_bytes();
 649     assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok");
 650     scale = (1 << tak->log2_element_size());





 651   } else {
 652     ShouldNotReachHere();
 653   }
 654 }
 655 
 656 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) {
 657   int base = 0, scale = 0;
 658   getBaseAndScale(base, scale, clazz, CHECK_0);
 659 
 660   return field_offset_from_byte_offset(base);
 661 } UNSAFE_END
 662 
 663 
 664 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) {
 665   int base = 0, scale = 0;
 666   getBaseAndScale(base, scale, clazz, CHECK_0);
 667 
 668   // This VM packs both fields and array elements down to the byte.
 669   // But watch out:  If this changes, so that array references for
 670   // a given primitive type (say, T_BOOLEAN) use different memory units


1098 
1099 #define DC_Args  LANG "String;[BII" LANG "ClassLoader;" "Ljava/security/ProtectionDomain;"
1100 #define DAC_Args CLS "[B[" OBJ
1101 
1102 #define CC (char*)  /*cast a literal from (const char*)*/
1103 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
1104 
1105 #define DECLARE_GETPUTOOP(Type, Desc) \
1106     {CC "get" #Type,      CC "(" OBJ "J)" #Desc,       FN_PTR(Unsafe_Get##Type)}, \
1107     {CC "put" #Type,      CC "(" OBJ "J" #Desc ")V",   FN_PTR(Unsafe_Put##Type)}, \
1108     {CC "get" #Type "Volatile",      CC "(" OBJ "J)" #Desc,       FN_PTR(Unsafe_Get##Type##Volatile)}, \
1109     {CC "put" #Type "Volatile",      CC "(" OBJ "J" #Desc ")V",   FN_PTR(Unsafe_Put##Type##Volatile)}
1110 
1111 
1112 static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
1113     {CC "getObject",        CC "(" OBJ "J)" OBJ "",   FN_PTR(Unsafe_GetObject)},
1114     {CC "putObject",        CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutObject)},
1115     {CC "getObjectVolatile",CC "(" OBJ "J)" OBJ "",   FN_PTR(Unsafe_GetObjectVolatile)},
1116     {CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutObjectVolatile)},
1117 

1118     {CC "getValue",         CC "(" OBJ "J" CLS ")" OBJ "", FN_PTR(Unsafe_GetValue)},
1119     {CC "putValue",         CC "(" OBJ "J" CLS OBJ ")V",   FN_PTR(Unsafe_PutValue)},
1120 
1121     {CC "getUncompressedObject", CC "(" ADR ")" OBJ,  FN_PTR(Unsafe_GetUncompressedObject)},
1122 
1123     DECLARE_GETPUTOOP(Boolean, Z),
1124     DECLARE_GETPUTOOP(Byte, B),
1125     DECLARE_GETPUTOOP(Short, S),
1126     DECLARE_GETPUTOOP(Char, C),
1127     DECLARE_GETPUTOOP(Int, I),
1128     DECLARE_GETPUTOOP(Long, J),
1129     DECLARE_GETPUTOOP(Float, F),
1130     DECLARE_GETPUTOOP(Double, D),
1131 
1132     {CC "allocateMemory0",    CC "(J)" ADR,              FN_PTR(Unsafe_AllocateMemory0)},
1133     {CC "reallocateMemory0",  CC "(" ADR "J)" ADR,       FN_PTR(Unsafe_ReallocateMemory0)},
1134     {CC "freeMemory0",        CC "(" ADR ")V",           FN_PTR(Unsafe_FreeMemory0)},
1135 
1136     {CC "objectFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_ObjectFieldOffset0)},
1137     {CC "objectFieldOffset1", CC "(" CLS LANG "String;)J", FN_PTR(Unsafe_ObjectFieldOffset1)},




 263  * Get the field descriptor of the field of the given object at the given offset.
 264  */
 265 static bool get_field_descriptor(oop p, jlong offset, fieldDescriptor* fd) {
 266   bool found = false;
 267   Klass* k = p->klass();
 268   if (k->is_instance_klass()) {
 269     InstanceKlass* ik = InstanceKlass::cast(k);
 270     found = ik->find_field_from_offset((int)offset, false, fd);
 271     if (!found && ik->is_mirror_instance_klass()) {
 272       Klass* k2 = java_lang_Class::as_Klass(p);
 273       if (k2->is_instance_klass()) {
 274         ik = InstanceKlass::cast(k2);
 275         found = ik->find_field_from_offset((int)offset, true, fd);
 276       }
 277     }
 278   }
 279   return found;
 280 }
 281 #endif // ASSERT
 282 
 283 static void assert_and_log_unsafe_value_type_access(oop p, jlong offset, ValueKlass* vk) {
 284   Klass* k = p->klass();
 285 
 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     assert(found, "value field not found");
 292     assert(fd.is_flattened(), "field not flat");
 293   } else if (k->is_valueArray_klass()) {
 294     ValueArrayKlass* vak = ValueArrayKlass::cast(k);
 295     int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size();
 296     address dest = (address)((valueArrayOop)p)->value_at_addr(index, vak->layout_helper());
 297     assert(dest == ((address)p) + offset, "invalid offset");
 298   } else {
 299     ShouldNotReachHere();
 300   }
 301 #endif // ASSERT
 302 
 303   if (log_is_enabled(Trace, valuetypes)) {
 304     if (k->is_valueArray_klass()) {
 305       ValueArrayKlass* vak = ValueArrayKlass::cast(k);
 306       int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size();
 307       address dest = (address)((valueArrayOop)p)->value_at_addr(index, vak->layout_helper());
 308       log_trace(valuetypes)("array type %s index %d element size %d offset " SIZE_FORMAT_HEX " at " INTPTR_FORMAT,
 309                             vak->external_name(), index, vak->element_byte_size(), offset, p2i(dest));
 310     } else {
 311       log_trace(valuetypes)("field type %s at offset " SIZE_FORMAT_HEX,
 312                             vk->external_name(), offset);
 313     }
 314   }
 315 }
 316 
 317 // These functions allow a null base pointer with an arbitrary address.
 318 // But if the base pointer is non-null, the offset should make some sense.
 319 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
 320 UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
 321   oop p = JNIHandles::resolve(obj);
 322   assert_field_offset_sane(p, offset);
 323   oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
 324   return JNIHandles::make_local(env, v);
 325 } UNSAFE_END
 326 
 327 UNSAFE_ENTRY(void, Unsafe_PutObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
 328   oop x = JNIHandles::resolve(x_h);
 329   oop p = JNIHandles::resolve(obj);
 330   assert_field_offset_sane(p, offset);
 331   HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
 332 } UNSAFE_END
 333 
 334 UNSAFE_ENTRY(jboolean, Unsafe_IsFlattenedArray(JNIEnv *env, jobject unsafe, jclass c)) {
 335   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 336   return k->is_valueArray_klass();
 337 } UNSAFE_END
 338 
 339 UNSAFE_ENTRY(jobject, Unsafe_GetValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass c)) {
 340   oop p = JNIHandles::resolve(obj);
 341   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
 342   ValueKlass* vk = ValueKlass::cast(k);
 343   assert_and_log_unsafe_value_type_access(p, offset, vk);













 344   Handle p_h(THREAD, p);
 345   bool in_heap;
 346   oop v = vk->allocate_buffered_or_heap_instance(&in_heap, 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                   in_heap, 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_GetObjectVolatile(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_PutObjectVolatile(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;


 645   return false;
 646 }
 647 UNSAFE_END
 648 
 649 static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) {
 650   assert(clazz != NULL, "clazz must not be NULL");
 651 
 652   oop mirror = JNIHandles::resolve_non_null(clazz);
 653   Klass* k = java_lang_Class::as_Klass(mirror);
 654 
 655   if (k == NULL || !k->is_array_klass()) {
 656     THROW(vmSymbols::java_lang_InvalidClassException());
 657   } else if (k->is_objArray_klass()) {
 658     base  = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
 659     scale = heapOopSize;
 660   } else if (k->is_typeArray_klass()) {
 661     TypeArrayKlass* tak = TypeArrayKlass::cast(k);
 662     base  = tak->array_header_in_bytes();
 663     assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok");
 664     scale = (1 << tak->log2_element_size());
 665   } else if (k->is_valueArray_klass()) {
 666     ValueArrayKlass* vak = ValueArrayKlass::cast(k);
 667     ValueKlass* vklass = vak->element_klass();
 668     base = vak->array_header_in_bytes();
 669     scale = vak->element_byte_size();
 670   } else {
 671     ShouldNotReachHere();
 672   }
 673 }
 674 
 675 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) {
 676   int base = 0, scale = 0;
 677   getBaseAndScale(base, scale, clazz, CHECK_0);
 678 
 679   return field_offset_from_byte_offset(base);
 680 } UNSAFE_END
 681 
 682 
 683 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) {
 684   int base = 0, scale = 0;
 685   getBaseAndScale(base, scale, clazz, CHECK_0);
 686 
 687   // This VM packs both fields and array elements down to the byte.
 688   // But watch out:  If this changes, so that array references for
 689   // a given primitive type (say, T_BOOLEAN) use different memory units


1117 
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 "getObject",        CC "(" OBJ "J)" OBJ "",   FN_PTR(Unsafe_GetObject)},
1133     {CC "putObject",        CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutObject)},
1134     {CC "getObjectVolatile",CC "(" OBJ "J)" OBJ "",   FN_PTR(Unsafe_GetObjectVolatile)},
1135     {CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V",  FN_PTR(Unsafe_PutObjectVolatile)},
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)},


< prev index next >