< prev index next >

src/hotspot/share/prims/unsafe.cpp

Print this page

        

*** 29,45 **** --- 29,51 ---- #include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "jfr/jfrEvents.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" + #include "logging/log.hpp" + #include "logging/logStream.hpp" #include "oops/access.inline.hpp" #include "oops/fieldStreams.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" + #include "oops/valueArrayKlass.hpp" + #include "oops/valueArrayOop.hpp" + #include "oops/valueArrayOop.inline.hpp" #include "prims/unsafe.hpp" #include "runtime/atomic.hpp" + #include "runtime/fieldDescriptor.inline.hpp" #include "runtime/globals.hpp" #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/orderAccess.hpp"
*** 143,153 **** } jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { return byte_offset; } - ///// Data read/writes on the Java heap and in native (off-heap) memory /** * Helper class for accessing memory. * --- 149,158 ----
*** 228,242 **** void put(T x) { if (_obj == NULL) { GuardUnsafeAccess guard(_thread); RawAccess<>::store(addr(), normalize_for_write(x)); } else { HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x)); } } - T get_volatile() { if (_obj == NULL) { GuardUnsafeAccess guard(_thread); volatile T ret = RawAccess<MO_SEQ_CST>::load(addr()); return normalize_for_read(ret); --- 233,247 ---- void put(T x) { if (_obj == NULL) { GuardUnsafeAccess guard(_thread); RawAccess<>::store(addr(), normalize_for_write(x)); } else { + assert(!_obj->is_value() || _obj->mark()->is_larval_state(), "must be an object instance or a larval value"); HeapAccess<>::store_at(_obj, _offset, normalize_for_write(x)); } } T get_volatile() { if (_obj == NULL) { GuardUnsafeAccess guard(_thread); volatile T ret = RawAccess<MO_SEQ_CST>::load(addr()); return normalize_for_read(ret);
*** 254,263 **** --- 259,330 ---- HeapAccess<MO_SEQ_CST>::store_at(_obj, _offset, normalize_for_write(x)); } } }; + #ifdef ASSERT + /* + * Get the field descriptor of the field of the given object at the given offset. + */ + static bool get_field_descriptor(oop p, jlong offset, fieldDescriptor* fd) { + bool found = false; + Klass* k = p->klass(); + if (k->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(k); + found = ik->find_field_from_offset((int)offset, false, fd); + if (!found && ik->is_mirror_instance_klass()) { + Klass* k2 = java_lang_Class::as_Klass(p); + if (k2->is_instance_klass()) { + ik = InstanceKlass::cast(k2); + found = ik->find_field_from_offset((int)offset, true, fd); + } + } + } + return found; + } + #endif // ASSERT + + static void assert_and_log_unsafe_value_access(oop p, jlong offset, ValueKlass* vk) { + Klass* k = p->klass(); + #ifdef ASSERT + if (k->is_instance_klass()) { + assert_field_offset_sane(p, offset); + fieldDescriptor fd; + bool found = get_field_descriptor(p, offset, &fd); + if (found) { + assert(found, "value field not found"); + assert(fd.is_flattened(), "field not flat"); + } else { + if (log_is_enabled(Trace, valuetypes)) { + log_trace(valuetypes)("not a field in %s at offset " SIZE_FORMAT_HEX, + p->klass()->external_name(), offset); + } + } + } else if (k->is_valueArray_klass()) { + ValueArrayKlass* vak = ValueArrayKlass::cast(k); + int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size(); + address dest = (address)((valueArrayOop)p)->value_at_addr(index, vak->layout_helper()); + assert(dest == ((address)p) + offset, "invalid offset"); + } else { + ShouldNotReachHere(); + } + #endif // ASSERT + if (log_is_enabled(Trace, valuetypes)) { + if (k->is_valueArray_klass()) { + ValueArrayKlass* vak = ValueArrayKlass::cast(k); + int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size(); + address dest = (address)((valueArrayOop)p)->value_at_addr(index, vak->layout_helper()); + log_trace(valuetypes)("%s array type %s index %d element size %d offset " SIZE_FORMAT_HEX " at " INTPTR_FORMAT, + p->klass()->external_name(), vak->external_name(), + index, vak->element_byte_size(), offset, p2i(dest)); + } else { + log_trace(valuetypes)("%s field type %s at offset " SIZE_FORMAT_HEX, + p->klass()->external_name(), vk->external_name(), offset); + } + } + } + // These functions allow a null base pointer with an arbitrary address. // But if the base pointer is non-null, the offset should make some sense. // That is, it should be in the range [0, MAX_OBJECT_SIZE]. UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { oop p = JNIHandles::resolve(obj);
*** 268,280 **** --- 335,411 ---- UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); assert_field_offset_sane(p, offset); + assert(!p->is_value() || p->mark()->is_larval_state(), "must be an object instance or a larval value"); HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x); } UNSAFE_END + UNSAFE_ENTRY(jlong, Unsafe_ValueHeaderSize(JNIEnv *env, jobject unsafe, jclass c)) { + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c)); + ValueKlass* vk = ValueKlass::cast(k); + return vk->first_field_offset(); + } UNSAFE_END + + UNSAFE_ENTRY(jboolean, Unsafe_IsFlattenedArray(JNIEnv *env, jobject unsafe, jclass c)) { + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c)); + return k->is_valueArray_klass(); + } UNSAFE_END + + UNSAFE_ENTRY(jobject, Unsafe_UninitializedDefaultValue(JNIEnv *env, jobject unsafe, jclass vc)) { + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc)); + ValueKlass* vk = ValueKlass::cast(k); + oop v = vk->default_value(); + return JNIHandles::make_local(env, v); + } UNSAFE_END + + UNSAFE_ENTRY(jobject, Unsafe_GetValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass vc)) { + oop base = JNIHandles::resolve(obj); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc)); + ValueKlass* vk = ValueKlass::cast(k); + assert_and_log_unsafe_value_access(base, offset, vk); + Handle base_h(THREAD, base); + oop v = vk->allocate_instance(CHECK_NULL); // allocate instance + vk->initialize(CHECK_NULL); // If field is a default value, value class might not be initialized yet + vk->value_store(((address)(oopDesc*)base_h()) + offset, + vk->data_for_oop(v), + true, true); + return JNIHandles::make_local(env, v); + } UNSAFE_END + + UNSAFE_ENTRY(void, Unsafe_PutValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass vc, jobject value)) { + oop base = JNIHandles::resolve(obj); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc)); + ValueKlass* vk = ValueKlass::cast(k); + assert(!base->is_value() || base->mark()->is_larval_state(), "must be an object instance or a larval value"); + assert_and_log_unsafe_value_access(base, offset, vk); + oop v = JNIHandles::resolve(value); + vk->value_store(vk->data_for_oop(v), + ((address)(oopDesc*)base) + offset, true, true); + } UNSAFE_END + + UNSAFE_ENTRY(jobject, Unsafe_MakePrivateBuffer(JNIEnv *env, jobject unsafe, jobject value)) { + oop v = JNIHandles::resolve_non_null(value); + assert(v->is_value(), "must be a value instance"); + Handle vh(THREAD, v); + ValueKlass* vk = ValueKlass::cast(v->klass()); + instanceOop new_value = vk->allocate_instance(CHECK_NULL); + vk->value_store(vk->data_for_oop(vh()), vk->data_for_oop(new_value), true, false); + markOop mark = new_value->mark(); + new_value->set_mark(mark->enter_larval_state()); + return JNIHandles::make_local(env, new_value); + } UNSAFE_END + + UNSAFE_ENTRY(jobject, Unsafe_FinishPrivateBuffer(JNIEnv *env, jobject unsafe, jobject value)) { + oop v = JNIHandles::resolve(value); + assert(v->mark()->is_larval_state(), "must be a larval value"); + markOop mark = v->mark(); + v->set_mark(mark->exit_larval_state()); + return JNIHandles::make_local(env, v); + } UNSAFE_END + UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { oop p = JNIHandles::resolve(obj); assert_field_offset_sane(p, offset); oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset); return JNIHandles::make_local(env, v);
*** 552,561 **** --- 683,697 ---- } else if (k->is_typeArray_klass()) { TypeArrayKlass* tak = TypeArrayKlass::cast(k); base = tak->array_header_in_bytes(); assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok"); scale = (1 << tak->log2_element_size()); + } else if (k->is_valueArray_klass()) { + ValueArrayKlass* vak = ValueArrayKlass::cast(k); + ValueKlass* vklass = vak->element_klass(); + base = vak->array_header_in_bytes(); + scale = vak->element_byte_size(); } else { ShouldNotReachHere(); } }
*** 1006,1027 **** #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) #define DECLARE_GETPUTOOP(Type, Desc) \ ! {CC "get" #Type, CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type)}, \ ! {CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type)}, \ ! {CC "get" #Type "Volatile", CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \ ! {CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type##Volatile)} static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { {CC "getReference", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetReference)}, {CC "putReference", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutReference)}, {CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ, FN_PTR(Unsafe_GetReferenceVolatile)}, {CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutReferenceVolatile)}, {CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)}, DECLARE_GETPUTOOP(Boolean, Z), DECLARE_GETPUTOOP(Byte, B), DECLARE_GETPUTOOP(Short, S), --- 1142,1171 ---- #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) #define DECLARE_GETPUTOOP(Type, Desc) \ ! {CC "get" #Type, CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type)}, \ ! {CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type)}, \ ! {CC "get" #Type "Volatile", CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \ ! {CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type##Volatile)} static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { {CC "getReference", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetReference)}, {CC "putReference", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutReference)}, {CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ, FN_PTR(Unsafe_GetReferenceVolatile)}, {CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutReferenceVolatile)}, + {CC "isFlattenedArray", CC "(" CLS ")Z", FN_PTR(Unsafe_IsFlattenedArray)}, + {CC "getValue", CC "(" OBJ "J" CLS ")" OBJ, FN_PTR(Unsafe_GetValue)}, + {CC "putValue", CC "(" OBJ "J" CLS OBJ ")V", FN_PTR(Unsafe_PutValue)}, + {CC "uninitializedDefaultValue", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_UninitializedDefaultValue)}, + {CC "makePrivateBuffer", CC "(" OBJ ")" OBJ, FN_PTR(Unsafe_MakePrivateBuffer)}, + {CC "finishPrivateBuffer", CC "(" OBJ ")" OBJ, FN_PTR(Unsafe_FinishPrivateBuffer)}, + {CC "valueHeaderSize", CC "(" CLS ")J", FN_PTR(Unsafe_ValueHeaderSize)}, + {CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)}, DECLARE_GETPUTOOP(Boolean, Z), DECLARE_GETPUTOOP(Byte, B), DECLARE_GETPUTOOP(Short, S),
< prev index next >