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)},
|