< prev index next >
src/hotspot/share/prims/unsafe.cpp
Print this page
*** 28,44 ****
--- 28,50 ----
#include "classfile/classFileStream.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"
*** 142,152 ****
}
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.
*
--- 148,157 ----
*** 227,241 ****
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);
--- 232,246 ----
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);
*** 253,262 ****
--- 258,329 ----
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);
*** 267,279 ****
--- 334,410 ----
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);
*** 571,580 ****
--- 702,716 ----
} 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();
}
}
*** 1048,1057 ****
--- 1184,1201 ----
{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 >