8258625: [JVMCI] refactor and unify JVMCI readFieldValue path
Reviewed-by: kvn
This commit is contained in:
parent
b5c6351315
commit
852a41d718
src
hotspot/share/jvmci
jdk.internal.vm.ci/share/classes
jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot
CompilerToVM.javaHotSpotConstantReflectionProvider.javaHotSpotJDKReflection.javaHotSpotJVMCIReflection.javaHotSpotMemoryAccessProviderImpl.javaHotSpotObjectConstantImpl.javaHotSpotResolvedObjectTypeImpl.javaHotSpotResolvedPrimitiveType.javaSharedLibraryJVMCIReflection.java
jdk.vm.ci.meta/src/jdk/vm/ci/meta
test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test
@ -44,6 +44,7 @@
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
#include "oops/constantPool.inline.hpp"
|
||||
#include "oops/instanceMirrorKlass.hpp"
|
||||
#include "oops/instanceKlass.inline.hpp"
|
||||
#include "oops/method.inline.hpp"
|
||||
#include "oops/typeArrayOop.inline.hpp"
|
||||
@ -249,18 +250,6 @@ C2V_VMENTRY_NULL(jobject, getFlagValue, (JNIEnv* env, jobject c2vm, jobject name
|
||||
#undef RETURN_BOXED_DOUBLE
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY_NULL(jobject, getObjectAtAddress, (JNIEnv* env, jobject c2vm, jlong oop_address))
|
||||
requireInHotSpot("getObjectAtAddress", JVMCI_CHECK_NULL);
|
||||
if (oop_address == 0) {
|
||||
JVMCI_THROW_MSG_NULL(InternalError, "Handle must be non-zero");
|
||||
}
|
||||
oop obj = *((oopDesc**) oop_address);
|
||||
if (obj != NULL) {
|
||||
oopDesc::verify(obj);
|
||||
}
|
||||
return JNIHandles::make_local(THREAD, obj);
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY_NULL(jbyteArray, getBytecode, (JNIEnv* env, jobject, jobject jvmci_method))
|
||||
methodHandle method(THREAD, JVMCIENV->asMethod(jvmci_method));
|
||||
|
||||
@ -640,29 +629,22 @@ C2V_VMENTRY_NULL(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv* env, job
|
||||
// Convert standard box (e.g. java.lang.Integer) to JVMCI box (e.g. jdk.vm.ci.meta.PrimitiveConstant)
|
||||
jvalue value;
|
||||
jlong raw_value;
|
||||
JVMCIObject kind;
|
||||
BasicType bt2 = java_lang_boxing_object::get_value(obj, &value);
|
||||
assert(bt2 == bt, "");
|
||||
switch (bt2) {
|
||||
case T_BOOLEAN: raw_value = value.z; break;
|
||||
case T_BYTE: raw_value = value.b; break;
|
||||
case T_SHORT: raw_value = value.s; break;
|
||||
case T_CHAR: raw_value = value.c; break;
|
||||
case T_INT: raw_value = value.i; break;
|
||||
case T_LONG: raw_value = value.j; break;
|
||||
case T_FLOAT: {
|
||||
JVMCIObject result = JVMCIENV->call_JavaConstant_forFloat(value.f, JVMCI_CHECK_NULL);
|
||||
return JVMCIENV->get_jobject(result);
|
||||
}
|
||||
case T_DOUBLE: {
|
||||
JVMCIObject result = JVMCIENV->call_JavaConstant_forDouble(value.d, JVMCI_CHECK_NULL);
|
||||
return JVMCIENV->get_jobject(result);
|
||||
}
|
||||
default: {
|
||||
return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_ILLEGAL());
|
||||
}
|
||||
case T_LONG: kind = JVMCIENV->get_JavaKind_Long(); raw_value = value.j; break;
|
||||
case T_DOUBLE: kind = JVMCIENV->get_JavaKind_Double(); raw_value = value.j; break;
|
||||
case T_FLOAT: kind = JVMCIENV->get_JavaKind_Float(); raw_value = value.i; break;
|
||||
case T_INT: kind = JVMCIENV->get_JavaKind_Int(); raw_value = value.i; break;
|
||||
case T_SHORT: kind = JVMCIENV->get_JavaKind_Short(); raw_value = value.s; break;
|
||||
case T_BYTE: kind = JVMCIENV->get_JavaKind_Byte(); raw_value = value.b; break;
|
||||
case T_CHAR: kind = JVMCIENV->get_JavaKind_Char(); raw_value = value.c; break;
|
||||
case T_BOOLEAN: kind = JVMCIENV->get_JavaKind_Boolean(); raw_value = value.z; break;
|
||||
default: return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_ILLEGAL());
|
||||
}
|
||||
|
||||
JVMCIObject result = JVMCIENV->call_PrimitiveConstant_forTypeChar(type2char(bt2), raw_value, JVMCI_CHECK_NULL);
|
||||
JVMCIObject result = JVMCIENV->call_JavaConstant_forPrimitive(kind, raw_value, JVMCI_CHECK_NULL);
|
||||
return JVMCIENV->get_jobject(result);
|
||||
}
|
||||
}
|
||||
@ -1191,11 +1173,6 @@ C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nm
|
||||
JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, JVMCI_CHECK);
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY_NULL(jobject, readUncompressedOop, (JNIEnv* env, jobject, jlong addr))
|
||||
oop ret = RawAccess<>::oop_load((oop*)(address)addr);
|
||||
return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(ret));
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject))
|
||||
// Returns a zero length array if counters aren't enabled
|
||||
JVMCIPrimitiveArray array = JVMCIENV->new_longArray(JVMCICounterSize, JVMCI_CHECK_NULL);
|
||||
@ -1949,79 +1926,130 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, jobjec
|
||||
return JVMCIENV->get_jobjectArray(methods);
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY_NULL(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, jobject field, jboolean is_volatile))
|
||||
if (object == NULL || field == NULL) {
|
||||
C2V_VMENTRY_NULL(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, jobject expected_type, long displacement, jboolean is_volatile, jobject kind_object))
|
||||
if (object == NULL || kind_object == NULL) {
|
||||
JVMCI_THROW_0(NullPointerException);
|
||||
}
|
||||
JVMCIObject field_object = JVMCIENV->wrap(field);
|
||||
JVMCIObject java_type = JVMCIENV->get_HotSpotResolvedJavaFieldImpl_type(field_object);
|
||||
int modifiers = JVMCIENV->get_HotSpotResolvedJavaFieldImpl_modifiers(field_object);
|
||||
Klass* holder = JVMCIENV->asKlass(JVMCIENV->get_HotSpotResolvedJavaFieldImpl_holder(field_object));
|
||||
if (!holder->is_instance_klass()) {
|
||||
JVMCI_THROW_MSG_0(InternalError, err_msg("Holder %s must be instance klass", holder->external_name()));
|
||||
}
|
||||
InstanceKlass* ik = InstanceKlass::cast(holder);
|
||||
BasicType constant_type;
|
||||
if (JVMCIENV->isa_HotSpotResolvedPrimitiveType(java_type)) {
|
||||
constant_type = JVMCIENV->kindToBasicType(JVMCIENV->get_HotSpotResolvedPrimitiveType_kind(java_type), JVMCI_CHECK_NULL);
|
||||
} else {
|
||||
constant_type = T_OBJECT;
|
||||
}
|
||||
int displacement = JVMCIENV->get_HotSpotResolvedJavaFieldImpl_offset(field_object);
|
||||
fieldDescriptor fd;
|
||||
if (!ik->find_local_field_from_offset(displacement, (modifiers & JVM_ACC_STATIC) != 0, &fd)) {
|
||||
JVMCI_THROW_MSG_0(InternalError, err_msg("Can't find field with displacement %d", displacement));
|
||||
}
|
||||
JVMCIObject base = JVMCIENV->wrap(object);
|
||||
Handle obj;
|
||||
if (JVMCIENV->isa_HotSpotObjectConstantImpl(base)) {
|
||||
obj = JVMCIENV->asConstant(base, JVMCI_CHECK_NULL);
|
||||
} else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base)) {
|
||||
Klass* klass = JVMCIENV->asKlass(base);
|
||||
obj = Handle(THREAD, klass->java_mirror());
|
||||
} else {
|
||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException,
|
||||
err_msg("Unexpected type: %s", JVMCIENV->klass_name(base)));
|
||||
|
||||
JVMCIObject kind = JVMCIENV->wrap(kind_object);
|
||||
BasicType basic_type = JVMCIENV->kindToBasicType(kind, JVMCI_CHECK_NULL);
|
||||
|
||||
InstanceKlass* holder = NULL;
|
||||
if (expected_type != NULL) {
|
||||
holder = InstanceKlass::cast(JVMCIENV->asKlass(JVMCIENV->wrap(expected_type)));
|
||||
}
|
||||
|
||||
if (displacement == java_lang_Class::component_mirror_offset() && java_lang_Class::is_instance(obj()) &&
|
||||
!java_lang_Class::as_Klass(obj())->is_array_klass()) {
|
||||
// Class.componentType for non-array classes can transiently contain an int[] that's
|
||||
// used for locking so always return null to mimic Class.getComponentType()
|
||||
return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_NULL_POINTER());
|
||||
bool is_static = false;
|
||||
Handle obj;
|
||||
JVMCIObject base = JVMCIENV->wrap(object);
|
||||
if (JVMCIENV->isa_HotSpotObjectConstantImpl(base)) {
|
||||
obj = JVMCIENV->asConstant(base, JVMCI_CHECK_NULL);
|
||||
// asConstant will throw an NPE if a constant contains NULL
|
||||
|
||||
if (holder != NULL && !obj->is_a(holder)) {
|
||||
// Not a subtype of field holder
|
||||
return NULL;
|
||||
}
|
||||
is_static = false;
|
||||
if (holder == NULL && java_lang_Class::is_instance(obj()) && displacement >= InstanceMirrorKlass::offset_of_static_fields()) {
|
||||
is_static = true;
|
||||
}
|
||||
} else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base)) {
|
||||
is_static = true;
|
||||
Klass* klass = JVMCIENV->asKlass(base);
|
||||
if (holder != NULL && holder != klass) {
|
||||
return NULL;
|
||||
}
|
||||
obj = Handle(THREAD, klass->java_mirror());
|
||||
} else {
|
||||
// The Java code is expected to guard against this path
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
if (displacement < 0 || ((long) displacement + type2aelembytes(basic_type) > HeapWordSize * obj->size())) {
|
||||
// Reading outside of the object bounds
|
||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "reading outside object bounds");
|
||||
}
|
||||
|
||||
// Perform basic sanity checks on the read. Primitive reads are permitted to read outside the
|
||||
// bounds of their fields but object reads must map exactly onto the underlying oop slot.
|
||||
if (basic_type == T_OBJECT) {
|
||||
if (obj->is_objArray()) {
|
||||
if (displacement < arrayOopDesc::base_offset_in_bytes(T_OBJECT)) {
|
||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "reading from array header");
|
||||
}
|
||||
if (displacement + heapOopSize > arrayOopDesc::base_offset_in_bytes(T_OBJECT) + arrayOop(obj())->length() * heapOopSize) {
|
||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "reading after last array element");
|
||||
}
|
||||
if (((displacement - arrayOopDesc::base_offset_in_bytes(T_OBJECT)) % heapOopSize) != 0) {
|
||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "misaligned object read from array");
|
||||
}
|
||||
} else if (obj->is_instance()) {
|
||||
InstanceKlass* klass = InstanceKlass::cast(is_static ? java_lang_Class::as_Klass(obj()) : obj->klass());
|
||||
fieldDescriptor fd;
|
||||
if (!klass->find_field_from_offset(displacement, is_static, &fd)) {
|
||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Can't find field at displacement %d in object of type %s", (int) displacement, klass->external_name()));
|
||||
}
|
||||
if (fd.field_type() != T_OBJECT && fd.field_type() != T_ARRAY) {
|
||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Field at displacement %d in object of type %s is %s but expected %s", (int) displacement,
|
||||
klass->external_name(), type2name(fd.field_type()), type2name(basic_type)));
|
||||
}
|
||||
} else if (obj->is_typeArray()) {
|
||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "Can't read objects from primitive array");
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
} else {
|
||||
if (obj->is_objArray()) {
|
||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "Reading primitive from object array");
|
||||
} else if (obj->is_typeArray()) {
|
||||
if (displacement < arrayOopDesc::base_offset_in_bytes(ArrayKlass::cast(obj->klass())->element_type())) {
|
||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "reading from array header");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jlong value = 0;
|
||||
JVMCIObject kind;
|
||||
switch (constant_type) {
|
||||
switch (basic_type) {
|
||||
case T_BOOLEAN: value = is_volatile ? obj->bool_field_acquire(displacement) : obj->bool_field(displacement); break;
|
||||
case T_BYTE: value = is_volatile ? obj->byte_field_acquire(displacement) : obj->byte_field(displacement); break;
|
||||
case T_SHORT: value = is_volatile ? obj->short_field_acquire(displacement) : obj->short_field(displacement); break;
|
||||
case T_CHAR: value = is_volatile ? obj->char_field_acquire(displacement) : obj->char_field(displacement); break;
|
||||
case T_FLOAT:
|
||||
case T_INT: value = is_volatile ? obj->int_field_acquire(displacement) : obj->int_field(displacement); break;
|
||||
case T_DOUBLE:
|
||||
case T_LONG: value = is_volatile ? obj->long_field_acquire(displacement) : obj->long_field(displacement); break;
|
||||
|
||||
case T_OBJECT: {
|
||||
oop object = is_volatile ? obj->obj_field_acquire(displacement) : obj->obj_field(displacement);
|
||||
JVMCIObject result = JVMCIENV->get_object_constant(object);
|
||||
if (result.is_null()) {
|
||||
if (displacement == java_lang_Class::component_mirror_offset() && java_lang_Class::is_instance(obj()) &&
|
||||
(java_lang_Class::as_Klass(obj()) == NULL || !java_lang_Class::as_Klass(obj())->is_array_klass())) {
|
||||
// Class.componentType for non-array classes can transiently contain an int[] that's
|
||||
// used for locking so always return null to mimic Class.getComponentType()
|
||||
return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_NULL_POINTER());
|
||||
}
|
||||
return JVMCIENV->get_jobject(result);
|
||||
|
||||
oop value = is_volatile ? obj->obj_field_acquire(displacement) : obj->obj_field(displacement);
|
||||
if (value == NULL) {
|
||||
return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_NULL_POINTER());
|
||||
} else {
|
||||
if (value != NULL && !oopDesc::is_oop(value)) {
|
||||
// Throw an exception to improve debuggability. This check isn't totally reliable because
|
||||
// is_oop doesn't try to be completety safe but for most invalid values it provides a good
|
||||
// enough answer. It possible to crash in the is_oop call but that just means the crash happens
|
||||
// closer to where things went wrong.
|
||||
JVMCI_THROW_MSG_NULL(InternalError, err_msg("Read bad oop " INTPTR_FORMAT " at offset " JLONG_FORMAT " in object " INTPTR_FORMAT " of type %s",
|
||||
p2i(value), displacement, p2i(obj()), obj->klass()->external_name()));
|
||||
}
|
||||
|
||||
JVMCIObject result = JVMCIENV->get_object_constant(value);
|
||||
return JVMCIENV->get_jobject(result);
|
||||
}
|
||||
}
|
||||
case T_FLOAT: {
|
||||
float f = is_volatile ? obj->float_field_acquire(displacement) : obj->float_field(displacement);
|
||||
JVMCIObject result = JVMCIENV->call_JavaConstant_forFloat(f, JVMCI_CHECK_NULL);
|
||||
return JVMCIENV->get_jobject(result);
|
||||
}
|
||||
case T_DOUBLE: {
|
||||
double f = is_volatile ? obj->double_field_acquire(displacement) : obj->double_field(displacement);
|
||||
JVMCIObject result = JVMCIENV->call_JavaConstant_forDouble(f, JVMCI_CHECK_NULL);
|
||||
return JVMCIENV->get_jobject(result);
|
||||
}
|
||||
case T_BOOLEAN: value = is_volatile ? obj->bool_field_acquire(displacement) : obj->bool_field(displacement); break;
|
||||
case T_BYTE: value = is_volatile ? obj->byte_field_acquire(displacement) : obj->byte_field(displacement); break;
|
||||
case T_SHORT: value = is_volatile ? obj->short_field_acquire(displacement) : obj->short_field(displacement); break;
|
||||
case T_CHAR: value = is_volatile ? obj->char_field_acquire(displacement) : obj->char_field(displacement); break;
|
||||
case T_INT: value = is_volatile ? obj->int_field_acquire(displacement) : obj->int_field(displacement); break;
|
||||
case T_LONG: value = is_volatile ? obj->long_field_acquire(displacement) : obj->long_field(displacement); break;
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
JVMCIObject result = JVMCIENV->call_PrimitiveConstant_forTypeChar(type2char(constant_type), value, JVMCI_CHECK_NULL);
|
||||
JVMCIObject result = JVMCIENV->call_JavaConstant_forPrimitive(kind, value, JVMCI_CHECK_NULL);
|
||||
return JVMCIENV->get_jobject(result);
|
||||
C2V_END
|
||||
|
||||
@ -2179,55 +2207,6 @@ C2V_VMENTRY_0(jint, arrayIndexScale, (JNIEnv* env, jobject, jobject kind))
|
||||
return type2aelembytes(type);
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY_0(jbyte, getByte, (JNIEnv* env, jobject, jobject x, long displacement))
|
||||
if (x == NULL) {
|
||||
JVMCI_THROW_0(NullPointerException);
|
||||
}
|
||||
Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
|
||||
return xobj->byte_field(displacement);
|
||||
}
|
||||
|
||||
C2V_VMENTRY_0(jshort, getShort, (JNIEnv* env, jobject, jobject x, long displacement))
|
||||
if (x == NULL) {
|
||||
JVMCI_THROW_0(NullPointerException);
|
||||
}
|
||||
Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
|
||||
return xobj->short_field(displacement);
|
||||
}
|
||||
|
||||
C2V_VMENTRY_0(jint, getInt, (JNIEnv* env, jobject, jobject x, long displacement))
|
||||
if (x == NULL) {
|
||||
JVMCI_THROW_0(NullPointerException);
|
||||
}
|
||||
Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
|
||||
return xobj->int_field(displacement);
|
||||
}
|
||||
|
||||
C2V_VMENTRY_0(jlong, getLong, (JNIEnv* env, jobject, jobject x, long displacement))
|
||||
if (x == NULL) {
|
||||
JVMCI_THROW_0(NullPointerException);
|
||||
}
|
||||
Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
|
||||
return xobj->long_field(displacement);
|
||||
}
|
||||
|
||||
C2V_VMENTRY_NULL(jobject, getObject, (JNIEnv* env, jobject, jobject x, long displacement))
|
||||
if (x == NULL) {
|
||||
JVMCI_THROW_0(NullPointerException);
|
||||
}
|
||||
Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
|
||||
if (displacement == java_lang_Class::component_mirror_offset() && java_lang_Class::is_instance(xobj()) &&
|
||||
!java_lang_Class::as_Klass(xobj())->is_array_klass()) {
|
||||
// Class.componentType for non-array classes can transiently contain an int[] that's
|
||||
// used for locking so always return null to mimic Class.getComponentType()
|
||||
return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_NULL_POINTER());
|
||||
}
|
||||
|
||||
oop res = xobj->obj_field(displacement);
|
||||
JVMCIObject result = JVMCIENV->get_object_constant(res);
|
||||
return JVMCIENV->get_jobject(result);
|
||||
}
|
||||
|
||||
C2V_VMENTRY(void, deleteGlobalHandle, (JNIEnv* env, jobject, jlong h))
|
||||
jobject handle = (jobject)(address)h;
|
||||
if (handle != NULL) {
|
||||
@ -2768,7 +2747,6 @@ JNINativeMethod CompilerToVM::methods[] = {
|
||||
{CC "getLocalVariableTableLength", CC "(" HS_RESOLVED_METHOD ")I", FN_PTR(getLocalVariableTableLength)},
|
||||
{CC "reprofile", CC "(" HS_RESOLVED_METHOD ")V", FN_PTR(reprofile)},
|
||||
{CC "invalidateHotSpotNmethod", CC "(" HS_NMETHOD ")V", FN_PTR(invalidateHotSpotNmethod)},
|
||||
{CC "readUncompressedOop", CC "(J)" OBJECTCONSTANT, FN_PTR(readUncompressedOop)},
|
||||
{CC "collectCounters", CC "()[J", FN_PTR(collectCounters)},
|
||||
{CC "getCountersSize", CC "()I", FN_PTR(getCountersSize)},
|
||||
{CC "setCountersSize", CC "(I)Z", FN_PTR(setCountersSize)},
|
||||
@ -2787,7 +2765,6 @@ JNINativeMethod CompilerToVM::methods[] = {
|
||||
{CC "interpreterFrameSize", CC "(" BYTECODE_FRAME ")I", FN_PTR(interpreterFrameSize)},
|
||||
{CC "compileToBytecode", CC "(" OBJECTCONSTANT ")V", FN_PTR(compileToBytecode)},
|
||||
{CC "getFlagValue", CC "(" STRING ")" OBJECT, FN_PTR(getFlagValue)},
|
||||
{CC "getObjectAtAddress", CC "(J)" OBJECT, FN_PTR(getObjectAtAddress)},
|
||||
{CC "getInterfaces", CC "(" HS_RESOLVED_KLASS ")[" HS_RESOLVED_KLASS, FN_PTR(getInterfaces)},
|
||||
{CC "getComponentType", CC "(" HS_RESOLVED_KLASS ")" HS_RESOLVED_TYPE, FN_PTR(getComponentType)},
|
||||
{CC "ensureInitialized", CC "(" HS_RESOLVED_KLASS ")V", FN_PTR(ensureInitialized)},
|
||||
@ -2798,8 +2775,8 @@ JNINativeMethod CompilerToVM::methods[] = {
|
||||
{CC "boxPrimitive", CC "(" OBJECT ")" OBJECTCONSTANT, FN_PTR(boxPrimitive)},
|
||||
{CC "getDeclaredConstructors", CC "(" HS_RESOLVED_KLASS ")[" RESOLVED_METHOD, FN_PTR(getDeclaredConstructors)},
|
||||
{CC "getDeclaredMethods", CC "(" HS_RESOLVED_KLASS ")[" RESOLVED_METHOD, FN_PTR(getDeclaredMethods)},
|
||||
{CC "readFieldValue", CC "(" HS_RESOLVED_KLASS HS_RESOLVED_FIELD "Z)" JAVACONSTANT, FN_PTR(readFieldValue)},
|
||||
{CC "readFieldValue", CC "(" OBJECTCONSTANT HS_RESOLVED_FIELD "Z)" JAVACONSTANT, FN_PTR(readFieldValue)},
|
||||
{CC "readFieldValue", CC "(" HS_RESOLVED_KLASS HS_RESOLVED_KLASS "JZLjdk/vm/ci/meta/JavaKind;)" JAVACONSTANT, FN_PTR(readFieldValue)},
|
||||
{CC "readFieldValue", CC "(" OBJECTCONSTANT HS_RESOLVED_KLASS "JZLjdk/vm/ci/meta/JavaKind;)" JAVACONSTANT, FN_PTR(readFieldValue)},
|
||||
{CC "isInstance", CC "(" HS_RESOLVED_KLASS OBJECTCONSTANT ")Z", FN_PTR(isInstance)},
|
||||
{CC "isAssignableFrom", CC "(" HS_RESOLVED_KLASS HS_RESOLVED_KLASS ")Z", FN_PTR(isAssignableFrom)},
|
||||
{CC "isTrustedForIntrinsics", CC "(" HS_RESOLVED_KLASS ")Z", FN_PTR(isTrustedForIntrinsics)},
|
||||
@ -2811,11 +2788,6 @@ JNINativeMethod CompilerToVM::methods[] = {
|
||||
{CC "readArrayElement", CC "(" OBJECTCONSTANT "I)Ljava/lang/Object;", FN_PTR(readArrayElement)},
|
||||
{CC "arrayBaseOffset", CC "(Ljdk/vm/ci/meta/JavaKind;)I", FN_PTR(arrayBaseOffset)},
|
||||
{CC "arrayIndexScale", CC "(Ljdk/vm/ci/meta/JavaKind;)I", FN_PTR(arrayIndexScale)},
|
||||
{CC "getByte", CC "(" OBJECTCONSTANT "J)B", FN_PTR(getByte)},
|
||||
{CC "getShort", CC "(" OBJECTCONSTANT "J)S", FN_PTR(getShort)},
|
||||
{CC "getInt", CC "(" OBJECTCONSTANT "J)I", FN_PTR(getInt)},
|
||||
{CC "getLong", CC "(" OBJECTCONSTANT "J)J", FN_PTR(getLong)},
|
||||
{CC "getObject", CC "(" OBJECTCONSTANT "J)" OBJECTCONSTANT, FN_PTR(getObject)},
|
||||
{CC "deleteGlobalHandle", CC "(J)V", FN_PTR(deleteGlobalHandle)},
|
||||
{CC "registerNativeMethods", CC "(" CLASS ")[J", FN_PTR(registerNativeMethods)},
|
||||
{CC "isCurrentThreadAttached", CC "()Z", FN_PTR(isCurrentThreadAttached)},
|
||||
|
@ -801,69 +801,23 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object,
|
||||
}
|
||||
|
||||
|
||||
JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value, JVMCI_TRAPS) {
|
||||
JVMCIObject JVMCIEnv::call_JavaConstant_forPrimitive(JVMCIObject kind, jlong value, JVMCI_TRAPS) {
|
||||
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
|
||||
if (is_hotspot()) {
|
||||
JavaCallArguments jargs;
|
||||
jargs.push_int(kind);
|
||||
jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(kind)));
|
||||
jargs.push_long(value);
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
HotSpotJVMCI::PrimitiveConstant::klass(),
|
||||
vmSymbols::forTypeChar_name(),
|
||||
vmSymbols::forTypeChar_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
return wrap(result.get_oop());
|
||||
} else {
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::PrimitiveConstant::clazz(),
|
||||
JNIJVMCI::PrimitiveConstant::forTypeChar_method(),
|
||||
kind, value);
|
||||
if (jni()->ExceptionCheck()) {
|
||||
return JVMCIObject();
|
||||
}
|
||||
return wrap(result);
|
||||
}
|
||||
}
|
||||
|
||||
JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) {
|
||||
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
|
||||
if (is_hotspot()) {
|
||||
JavaCallArguments jargs;
|
||||
jargs.push_float(value);
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
HotSpotJVMCI::JavaConstant::klass(),
|
||||
vmSymbols::forFloat_name(),
|
||||
vmSymbols::forFloat_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
vmSymbols::forPrimitive_name(),
|
||||
vmSymbols::forPrimitive_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
return wrap(result.get_oop());
|
||||
} else {
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
|
||||
JNIJVMCI::JavaConstant::forFloat_method(),
|
||||
value);
|
||||
if (jni()->ExceptionCheck()) {
|
||||
return JVMCIObject();
|
||||
}
|
||||
return wrap(result);
|
||||
}
|
||||
}
|
||||
|
||||
JVMCIObject JVMCIEnv::call_JavaConstant_forDouble(double value, JVMCI_TRAPS) {
|
||||
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
|
||||
if (is_hotspot()) {
|
||||
JavaCallArguments jargs;
|
||||
jargs.push_double(value);
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
HotSpotJVMCI::JavaConstant::klass(),
|
||||
vmSymbols::forDouble_name(),
|
||||
vmSymbols::forDouble_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
return wrap(result.get_oop());
|
||||
} else {
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
|
||||
JNIJVMCI::JavaConstant::forDouble_method(),
|
||||
value);
|
||||
JNIJVMCI::JavaConstant::forPrimitive_method(),
|
||||
kind.as_jobject(), value);
|
||||
if (jni()->ExceptionCheck()) {
|
||||
return JVMCIObject();
|
||||
}
|
||||
|
@ -307,9 +307,7 @@ public:
|
||||
|
||||
JVMCIObject call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCI_TRAPS);
|
||||
|
||||
JVMCIObject call_PrimitiveConstant_forTypeChar(jchar kind, jlong value, JVMCI_TRAPS);
|
||||
JVMCIObject call_JavaConstant_forFloat(float value, JVMCI_TRAPS);
|
||||
JVMCIObject call_JavaConstant_forDouble(double value, JVMCI_TRAPS);
|
||||
JVMCIObject call_JavaConstant_forPrimitive(JVMCIObject kind, jlong value, JVMCI_TRAPS);
|
||||
|
||||
jboolean call_HotSpotJVMCIRuntime_isGCSupported(JVMCIObject runtime, jint gcIdentifier);
|
||||
|
||||
|
@ -247,15 +247,13 @@
|
||||
start_class(JavaConstant, jdk_vm_ci_meta_JavaConstant) \
|
||||
static_object_field(JavaConstant, ILLEGAL, "Ljdk/vm/ci/meta/PrimitiveConstant;") \
|
||||
static_object_field(JavaConstant, NULL_POINTER, "Ljdk/vm/ci/meta/JavaConstant;") \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JavaConstant, forFloat, forFloat_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JavaConstant, forDouble, forDouble_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JavaConstant, forPrimitive, forPrimitive_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
|
||||
end_class \
|
||||
start_class(ResolvedJavaMethod, jdk_vm_ci_meta_ResolvedJavaMethod) \
|
||||
end_class \
|
||||
start_class(PrimitiveConstant, jdk_vm_ci_meta_PrimitiveConstant) \
|
||||
object_field(PrimitiveConstant, kind, "Ljdk/vm/ci/meta/JavaKind;") \
|
||||
long_field(PrimitiveConstant, primitive) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, PrimitiveConstant, forTypeChar, forTypeChar_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
|
||||
end_class \
|
||||
start_class(RawConstant, jdk_vm_ci_meta_RawConstant) \
|
||||
end_class \
|
||||
|
@ -125,12 +125,8 @@
|
||||
template(callToString_signature, "(Ljava/lang/Object;)Ljava/lang/String;") \
|
||||
template(getName_name, "getName") \
|
||||
template(bootstrapFinished_name, "bootstrapFinished") \
|
||||
template(forTypeChar_name, "forTypeChar") \
|
||||
template(forTypeChar_signature, "(CJ)Ljdk/vm/ci/meta/PrimitiveConstant;") \
|
||||
template(forFloat_name, "forFloat") \
|
||||
template(forFloat_signature, "(F)Ljdk/vm/ci/meta/PrimitiveConstant;") \
|
||||
template(forDouble_name, "forDouble") \
|
||||
template(forDouble_signature, "(D)Ljdk/vm/ci/meta/PrimitiveConstant;") \
|
||||
template(forPrimitive_name, "forPrimitive") \
|
||||
template(forPrimitive_signature, "(Ljdk/vm/ci/meta/JavaKind;J)Ljdk/vm/ci/meta/PrimitiveConstant;") \
|
||||
template(method_string_bool_long_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \
|
||||
template(initializeSavedProperties_name, "initializeSavedProperties") \
|
||||
|
||||
|
@ -512,19 +512,6 @@ final class CompilerToVM {
|
||||
*/
|
||||
native long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method);
|
||||
|
||||
/**
|
||||
* Reads an object pointer within a VM data structure. That is, any {@link VMField} whose
|
||||
* {@link VMField#type type} is {@code "oop"} (e.g., {@code Klass::_java_mirror},
|
||||
* {@code JavaThread::_threadObj}).
|
||||
*
|
||||
* Note that {@code Unsafe.getObject(Object, long)} cannot be used for this since it does a
|
||||
* {@code narrowOop} read if the VM is using compressed oops whereas oops within VM data
|
||||
* structures are (currently) always uncompressed.
|
||||
*
|
||||
* @param address address of an oop field within a VM data structure
|
||||
*/
|
||||
native HotSpotObjectConstantImpl readUncompressedOop(long address);
|
||||
|
||||
/**
|
||||
* Sets flags on {@code method} indicating that it should never be inlined or compiled by the
|
||||
* VM.
|
||||
@ -741,13 +728,6 @@ final class CompilerToVM {
|
||||
*/
|
||||
native HotSpotResolvedObjectTypeImpl getHostClass(HotSpotResolvedObjectTypeImpl type);
|
||||
|
||||
/**
|
||||
* Gets the object at the address {@code oopAddress}.
|
||||
*
|
||||
* @param oopAddress a valid {@code oopDesc**} value
|
||||
*/
|
||||
native Object getObjectAtAddress(long oopAddress);
|
||||
|
||||
/**
|
||||
* @see ResolvedJavaType#getInterfaces()
|
||||
*/
|
||||
@ -807,14 +787,18 @@ final class CompilerToVM {
|
||||
native ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl holder);
|
||||
|
||||
/**
|
||||
* Reads the current value of a static field.
|
||||
* Reads the current value of a static field. If {@code expectedType} is non-null, then the
|
||||
* object is exptected to be a subtype of {@code expectedType} and extra sanity checking is
|
||||
* performed on the offset and kind of the read being performed.
|
||||
*/
|
||||
native JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl resolvedObjectType, HotSpotResolvedJavaField field, boolean isVolatile);
|
||||
native JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl object, HotSpotResolvedObjectTypeImpl expectedType, long offset, boolean isVolatile, JavaKind kind);
|
||||
|
||||
/**
|
||||
* Reads the current value of an instance field.
|
||||
* Reads the current value of an instance field. If {@code expectedType} is non-null, then the
|
||||
* object is exptected to be a subtype of {@code expectedType} and extra sanity checking is
|
||||
* performed on the offset and kind of the read being performed.
|
||||
*/
|
||||
native JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile);
|
||||
native JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedObjectTypeImpl expectedType, long offset, boolean isVolatile, JavaKind kind);
|
||||
|
||||
/**
|
||||
* @see ResolvedJavaType#isInstance(JavaConstant)
|
||||
@ -858,31 +842,6 @@ final class CompilerToVM {
|
||||
*/
|
||||
native Object readArrayElement(HotSpotObjectConstantImpl object, int index);
|
||||
|
||||
/**
|
||||
* Reads a byte sized value from {@code displacement} in {@code object}.
|
||||
*/
|
||||
native byte getByte(HotSpotObjectConstantImpl object, long displacement);
|
||||
|
||||
/**
|
||||
* Reads a short sized value from {@code displacement} in {@code object}.
|
||||
*/
|
||||
native short getShort(HotSpotObjectConstantImpl object, long displacement);
|
||||
|
||||
/**
|
||||
* Reads an int sized value from {@code displacement} in {@code object}.
|
||||
*/
|
||||
native int getInt(HotSpotObjectConstantImpl object, long displacement);
|
||||
|
||||
/**
|
||||
* Reads a long sized value from {@code displacement} in {@code object}.
|
||||
*/
|
||||
native long getLong(HotSpotObjectConstantImpl object, long displacement);
|
||||
|
||||
/**
|
||||
* Reads a Java object from {@code displacement} in {@code object}.
|
||||
*/
|
||||
native HotSpotObjectConstantImpl getObject(HotSpotObjectConstantImpl object, long displacement);
|
||||
|
||||
/**
|
||||
* @see HotSpotJVMCIRuntime#registerNativeMethods
|
||||
*/
|
||||
|
@ -22,6 +22,8 @@
|
||||
*/
|
||||
package jdk.vm.ci.hotspot;
|
||||
|
||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import jdk.vm.ci.common.JVMCIError;
|
||||
@ -164,15 +166,13 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
|
||||
if (hotspotField.isStatic()) {
|
||||
HotSpotResolvedObjectTypeImpl holder = (HotSpotResolvedObjectTypeImpl) hotspotField.getDeclaringClass();
|
||||
if (holder.isInitialized()) {
|
||||
return holder.readFieldValue(hotspotField, field.isVolatile());
|
||||
}
|
||||
} else {
|
||||
if (receiver.isNonNull() && receiver instanceof HotSpotObjectConstantImpl) {
|
||||
HotSpotObjectConstantImpl object = ((HotSpotObjectConstantImpl) receiver);
|
||||
if (hotspotField.isInObject(receiver)) {
|
||||
return object.readFieldValue(hotspotField, field.isVolatile());
|
||||
}
|
||||
return runtime().compilerToVm.readFieldValue(holder, (HotSpotResolvedObjectTypeImpl) hotspotField.getDeclaringClass(), hotspotField.getOffset(), field.isVolatile(),
|
||||
hotspotField.getType().getJavaKind());
|
||||
}
|
||||
} else if (receiver instanceof HotSpotObjectConstantImpl) {
|
||||
return ((HotSpotObjectConstantImpl) receiver).readFieldValue(hotspotField, field.isVolatile());
|
||||
} else if (receiver == null) {
|
||||
throw new NullPointerException("receiver is null");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ package jdk.vm.ci.hotspot;
|
||||
|
||||
import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
|
||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
|
||||
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Array;
|
||||
@ -37,8 +36,6 @@ import java.util.HashMap;
|
||||
import jdk.vm.ci.common.JVMCIError;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
@ -106,27 +103,13 @@ final class HotSpotJDKReflection extends HotSpotJVMCIReflection {
|
||||
return (HotSpotResolvedObjectType) runtime().fromClass(javaMirror.getEnclosingClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedJavaField field, boolean isVolatile) {
|
||||
Class<?> javaMirror = getMirror(holder);
|
||||
return readFieldValue(field, javaMirror, isVolatile);
|
||||
}
|
||||
|
||||
@Override
|
||||
JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile) {
|
||||
Object value = resolveObject(object);
|
||||
return readFieldValue(field, value, isVolatile);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean equals(HotSpotObjectConstantImpl a, HotSpotObjectConstantImpl b) {
|
||||
return resolveObject(a) == resolveObject(b) && a.isCompressed() == b.isCompressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
JavaConstant getJavaMirror(HotSpotResolvedPrimitiveType holder) {
|
||||
return holder.mirror;
|
||||
}
|
||||
// This field is being kept around for compatibility with libgraal
|
||||
@SuppressWarnings("unused") private long oopSizeOffset;
|
||||
|
||||
@Override
|
||||
ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod) {
|
||||
@ -296,152 +279,6 @@ final class HotSpotJDKReflection extends HotSpotJVMCIReflection {
|
||||
return forNonNullObject(source.asBoxedPrimitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
int getInt(HotSpotObjectConstantImpl object, long displacement) {
|
||||
return UNSAFE.getInt((resolveObject(object)), displacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
byte getByte(HotSpotObjectConstantImpl object, long displacement) {
|
||||
return UNSAFE.getByte(resolveObject(object), displacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
short getShort(HotSpotObjectConstantImpl object, long displacement) {
|
||||
return UNSAFE.getShort(resolveObject(object), displacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
long getLong(HotSpotObjectConstantImpl object, long displacement) {
|
||||
return UNSAFE.getLong(resolveObject(object), displacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type) {
|
||||
checkRead(kind, displacement, type, resolveObject(constant));
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset of injected {@code java.lang.Class::oop_size} field. No need to make {@code volatile}
|
||||
* as initialization is idempotent.
|
||||
*/
|
||||
private long oopSizeOffset;
|
||||
|
||||
private static int computeOopSizeOffset(HotSpotJVMCIRuntime runtime) {
|
||||
MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
|
||||
ResolvedJavaType staticType = metaAccess.lookupJavaType(Class.class);
|
||||
for (ResolvedJavaField f : staticType.getInstanceFields(false)) {
|
||||
if (f.getName().equals("oop_size")) {
|
||||
int offset = f.getOffset();
|
||||
assert offset != 0 : "not expecting offset of java.lang.Class::oop_size to be 0";
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
throw new JVMCIError("Could not find injected java.lang.Class::oop_size field");
|
||||
}
|
||||
|
||||
long oopSizeOffset() {
|
||||
if (oopSizeOffset == 0) {
|
||||
oopSizeOffset = computeOopSizeOffset(runtime());
|
||||
}
|
||||
return oopSizeOffset;
|
||||
}
|
||||
|
||||
private boolean checkRead(JavaKind kind, long displacement, HotSpotResolvedObjectType type, Object object) {
|
||||
if (type.isArray()) {
|
||||
ResolvedJavaType componentType = type.getComponentType();
|
||||
JavaKind componentKind = componentType.getJavaKind();
|
||||
final int headerSize = runtime().getArrayBaseOffset(componentKind);
|
||||
int sizeOfElement = runtime().getArrayIndexScale(componentKind);
|
||||
int length = Array.getLength(object);
|
||||
long arrayEnd = headerSize + (sizeOfElement * length);
|
||||
boolean aligned = ((displacement - headerSize) % sizeOfElement) == 0;
|
||||
if (displacement < 0 || displacement > (arrayEnd - sizeOfElement) || (kind == JavaKind.Object && !aligned)) {
|
||||
int index = (int) ((displacement - headerSize) / sizeOfElement);
|
||||
throw new IllegalArgumentException("Unsafe array access: reading element of kind " + kind +
|
||||
" at offset " + displacement + " (index ~ " + index + ") in " +
|
||||
type.toJavaName() + " object of length " + length);
|
||||
}
|
||||
} else if (kind != JavaKind.Object) {
|
||||
long size;
|
||||
if (object instanceof Class) {
|
||||
int wordSize = runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordSize;
|
||||
size = UNSAFE.getInt(object, oopSizeOffset()) * wordSize;
|
||||
} else {
|
||||
size = Math.abs(type.instanceSize());
|
||||
}
|
||||
int bytesToRead = kind.getByteCount();
|
||||
if (displacement + bytesToRead > size || displacement < 0) {
|
||||
throw new IllegalArgumentException("Unsafe access: reading " + bytesToRead + " bytes at offset " + displacement + " in " +
|
||||
type.toJavaName() + " object of size " + size);
|
||||
}
|
||||
} else {
|
||||
ResolvedJavaField field = null;
|
||||
if (object instanceof Class) {
|
||||
// Read of a static field
|
||||
HotSpotResolvedJavaType hotSpotResolvedJavaType = runtime().fromClass((Class<?>) object);
|
||||
if (hotSpotResolvedJavaType instanceof HotSpotResolvedObjectTypeImpl) {
|
||||
HotSpotResolvedObjectTypeImpl staticFieldsHolder = (HotSpotResolvedObjectTypeImpl) hotSpotResolvedJavaType;
|
||||
field = staticFieldsHolder.findStaticFieldWithOffset(displacement, JavaKind.Object);
|
||||
}
|
||||
}
|
||||
if (field == null) {
|
||||
field = type.findInstanceFieldWithOffset(displacement, JavaKind.Object);
|
||||
}
|
||||
if (field == null) {
|
||||
throw new IllegalArgumentException("Unsafe object access: field not found for read of kind Object" +
|
||||
" at offset " + displacement + " in " + type.toJavaName() + " object");
|
||||
}
|
||||
if (field.getJavaKind() != JavaKind.Object) {
|
||||
throw new IllegalArgumentException("Unsafe object access: field " + field.format("%H.%n:%T") + " not of expected kind Object" +
|
||||
" at offset " + displacement + " in " + type.toJavaName() + " object");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JavaConstant readFieldValue(HotSpotResolvedJavaField field, Object obj, boolean isVolatile) {
|
||||
assert obj != null;
|
||||
assert !field.isStatic() || obj instanceof Class;
|
||||
long displacement = field.getOffset();
|
||||
if (obj instanceof Class && field.getName().equals("componentType")) {
|
||||
Class<?> clazz = (Class<?>) obj;
|
||||
if (!clazz.isArray()) {
|
||||
// Class.componentType for non-array classes can transiently contain an int[] that's
|
||||
// used for locking so always return null to mimic Class.getComponentType()
|
||||
return JavaConstant.NULL_POINTER;
|
||||
}
|
||||
}
|
||||
|
||||
assert checkRead(field.getJavaKind(), displacement,
|
||||
(HotSpotResolvedObjectType) runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaType(field.isStatic() ? (Class<?>) obj : obj.getClass()),
|
||||
obj);
|
||||
JavaKind kind = field.getJavaKind();
|
||||
switch (kind) {
|
||||
case Boolean:
|
||||
return JavaConstant.forBoolean(isVolatile ? UNSAFE.getBooleanVolatile(obj, displacement) : UNSAFE.getBoolean(obj, displacement));
|
||||
case Byte:
|
||||
return JavaConstant.forByte(isVolatile ? UNSAFE.getByteVolatile(obj, displacement) : UNSAFE.getByte(obj, displacement));
|
||||
case Char:
|
||||
return JavaConstant.forChar(isVolatile ? UNSAFE.getCharVolatile(obj, displacement) : UNSAFE.getChar(obj, displacement));
|
||||
case Short:
|
||||
return JavaConstant.forShort(isVolatile ? UNSAFE.getShortVolatile(obj, displacement) : UNSAFE.getShort(obj, displacement));
|
||||
case Int:
|
||||
return JavaConstant.forInt(isVolatile ? UNSAFE.getIntVolatile(obj, displacement) : UNSAFE.getInt(obj, displacement));
|
||||
case Long:
|
||||
return JavaConstant.forLong(isVolatile ? UNSAFE.getLongVolatile(obj, displacement) : UNSAFE.getLong(obj, displacement));
|
||||
case Float:
|
||||
return JavaConstant.forFloat(isVolatile ? UNSAFE.getFloatVolatile(obj, displacement) : UNSAFE.getFloat(obj, displacement));
|
||||
case Double:
|
||||
return JavaConstant.forDouble(isVolatile ? UNSAFE.getDoubleVolatile(obj, displacement) : UNSAFE.getDouble(obj, displacement));
|
||||
case Object:
|
||||
return forObject(isVolatile ? UNSAFE.getReferenceVolatile(obj, displacement) : UNSAFE.getReference(obj, displacement));
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported kind: " + kind);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Method} object corresponding to {@code method}. This method guarantees the same
|
||||
* {@link Method} object is returned if called twice on the same {@code method} value.
|
||||
|
@ -26,12 +26,11 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
/**
|
||||
* Reflection interface for reflecting on the internals of HotSpot JVMCI types and objects.
|
||||
* API for reflecting on the internals of HotSpot JVMCI types and objects.
|
||||
*/
|
||||
abstract class HotSpotJVMCIReflection {
|
||||
|
||||
@ -51,14 +50,8 @@ abstract class HotSpotJVMCIReflection {
|
||||
|
||||
abstract HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder);
|
||||
|
||||
abstract JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedJavaField field, boolean isVolatile);
|
||||
|
||||
abstract JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile);
|
||||
|
||||
abstract boolean equals(HotSpotObjectConstantImpl hotSpotResolvedJavaType, HotSpotObjectConstantImpl that);
|
||||
|
||||
abstract JavaConstant getJavaMirror(HotSpotResolvedPrimitiveType hotSpotResolvedJavaType);
|
||||
|
||||
abstract ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod);
|
||||
|
||||
abstract Annotation[][] getParameterAnnotations(HotSpotResolvedJavaMethodImpl javaMethod);
|
||||
@ -100,16 +93,6 @@ abstract class HotSpotJVMCIReflection {
|
||||
|
||||
abstract JavaConstant boxPrimitive(JavaConstant source);
|
||||
|
||||
abstract int getInt(HotSpotObjectConstantImpl object, long displacement);
|
||||
|
||||
abstract byte getByte(HotSpotObjectConstantImpl object, long displacement);
|
||||
|
||||
abstract short getShort(HotSpotObjectConstantImpl object, long displacement);
|
||||
|
||||
abstract long getLong(HotSpotObjectConstantImpl object, long displacement);
|
||||
|
||||
abstract void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type);
|
||||
|
||||
abstract <T extends Annotation> T getFieldAnnotation(HotSpotResolvedJavaFieldImpl javaField, Class<T> annotationClass);
|
||||
|
||||
/**
|
||||
|
@ -42,39 +42,6 @@ class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {
|
||||
this.runtime = runtime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object boxed by {@code base} that is about to have a value of kind {@code kind} read
|
||||
* from it at the offset {@code displacement}.
|
||||
*
|
||||
* @param base constant value containing the base address for a pending read
|
||||
* @return {@code null} if {@code base} does not box an object otherwise the object boxed in
|
||||
* {@code base}
|
||||
*/
|
||||
private static HotSpotObjectConstantImpl asObject(Constant base, JavaKind kind, long displacement) {
|
||||
if (base instanceof HotSpotObjectConstantImpl) {
|
||||
HotSpotObjectConstantImpl constant = (HotSpotObjectConstantImpl) base;
|
||||
HotSpotResolvedObjectType type = constant.getType();
|
||||
runtime().reflection.checkRead(constant, kind, displacement, type);
|
||||
return constant;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isValidObjectFieldDisplacement(Constant base, long displacement) {
|
||||
if (base instanceof HotSpotMetaspaceConstant) {
|
||||
MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
|
||||
if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
|
||||
if (displacement == runtime.getConfig().javaMirrorOffset) {
|
||||
// Klass::_java_mirror is valid for all Klass* values
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.valueOf(metaspaceObject));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static long asRawPointer(Constant base) {
|
||||
if (base instanceof HotSpotMetaspaceConstantImpl) {
|
||||
MetaspaceObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
|
||||
@ -88,116 +55,87 @@ class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider {
|
||||
throw new IllegalArgumentException(String.valueOf(base));
|
||||
}
|
||||
|
||||
private static long readRawValue(Constant baseConstant, long displacement, JavaKind kind, int bits) {
|
||||
HotSpotObjectConstantImpl base = asObject(baseConstant, kind, displacement);
|
||||
if (base != null) {
|
||||
switch (bits) {
|
||||
case Byte.SIZE:
|
||||
return runtime().reflection.getByte(base, displacement);
|
||||
case Short.SIZE:
|
||||
return runtime().reflection.getShort(base, displacement);
|
||||
case Integer.SIZE:
|
||||
return runtime().reflection.getInt(base, displacement);
|
||||
case Long.SIZE:
|
||||
return runtime().reflection.getLong(base, displacement);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.valueOf(bits));
|
||||
}
|
||||
} else {
|
||||
long pointer = asRawPointer(baseConstant);
|
||||
switch (bits) {
|
||||
case Byte.SIZE:
|
||||
return UNSAFE.getByte(pointer + displacement);
|
||||
case Short.SIZE:
|
||||
return UNSAFE.getShort(pointer + displacement);
|
||||
case Integer.SIZE:
|
||||
return UNSAFE.getInt(pointer + displacement);
|
||||
case Long.SIZE:
|
||||
return UNSAFE.getLong(pointer + displacement);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.valueOf(bits));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean verifyReadRawObject(JavaConstant expected, Constant base, long displacement) {
|
||||
if (base instanceof HotSpotMetaspaceConstant) {
|
||||
MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
|
||||
if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
|
||||
if (displacement == runtime.getConfig().javaMirrorOffset) {
|
||||
HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) metaspaceObject;
|
||||
assert expected.equals(type.getJavaMirror());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private JavaConstant readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
|
||||
long displacement = initialDisplacement;
|
||||
JavaConstant ret;
|
||||
HotSpotObjectConstantImpl base = asObject(baseConstant, JavaKind.Object, displacement);
|
||||
if (base == null) {
|
||||
assert !compressed;
|
||||
displacement += asRawPointer(baseConstant);
|
||||
ret = runtime.getCompilerToVM().readUncompressedOop(displacement);
|
||||
assert verifyReadRawObject(ret, baseConstant, initialDisplacement);
|
||||
} else {
|
||||
assert runtime.getConfig().useCompressedOops == compressed;
|
||||
ret = runtime.getCompilerToVM().getObject(base, displacement);
|
||||
}
|
||||
return ret == null ? JavaConstant.NULL_POINTER : ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) {
|
||||
try {
|
||||
long rawValue = readRawValue(baseConstant, initialDisplacement, kind, bits);
|
||||
switch (kind) {
|
||||
case Boolean:
|
||||
return JavaConstant.forBoolean(rawValue != 0);
|
||||
case Byte:
|
||||
return JavaConstant.forByte((byte) rawValue);
|
||||
case Char:
|
||||
return JavaConstant.forChar((char) rawValue);
|
||||
case Short:
|
||||
return JavaConstant.forShort((short) rawValue);
|
||||
case Int:
|
||||
return JavaConstant.forInt((int) rawValue);
|
||||
case Long:
|
||||
return JavaConstant.forLong(rawValue);
|
||||
case Float:
|
||||
return JavaConstant.forFloat(Float.intBitsToFloat((int) rawValue));
|
||||
case Double:
|
||||
return JavaConstant.forDouble(Double.longBitsToDouble(rawValue));
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported kind: " + kind);
|
||||
if (baseConstant instanceof HotSpotObjectConstantImpl) {
|
||||
JavaKind readKind = kind;
|
||||
if (kind.getBitCount() != bits) {
|
||||
switch (bits) {
|
||||
case Byte.SIZE:
|
||||
readKind = JavaKind.Byte;
|
||||
break;
|
||||
case Short.SIZE:
|
||||
readKind = JavaKind.Short;
|
||||
break;
|
||||
case Integer.SIZE:
|
||||
readKind = JavaKind.Int;
|
||||
break;
|
||||
case Long.SIZE:
|
||||
readKind = JavaKind.Long;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(String.valueOf(bits));
|
||||
}
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
return null;
|
||||
JavaConstant result = runtime().compilerToVm.readFieldValue((HotSpotObjectConstantImpl) baseConstant, null, initialDisplacement, true, readKind);
|
||||
if (result != null && kind != readKind) {
|
||||
return JavaConstant.forPrimitive(kind, result.asLong());
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
long pointer = asRawPointer(baseConstant);
|
||||
long value;
|
||||
switch (bits) {
|
||||
case Byte.SIZE:
|
||||
value = UNSAFE.getByte(pointer + initialDisplacement);
|
||||
break;
|
||||
case Short.SIZE:
|
||||
value = UNSAFE.getShort(pointer + initialDisplacement);
|
||||
break;
|
||||
case Integer.SIZE:
|
||||
value = UNSAFE.getInt(pointer + initialDisplacement);
|
||||
break;
|
||||
case Long.SIZE:
|
||||
value = UNSAFE.getLong(pointer + initialDisplacement);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(String.valueOf(bits));
|
||||
}
|
||||
return JavaConstant.forPrimitive(kind, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaConstant readObjectConstant(Constant base, long displacement) {
|
||||
if (base instanceof HotSpotObjectConstantImpl) {
|
||||
return readRawObject(base, displacement, runtime.getConfig().useCompressedOops);
|
||||
return runtime.getCompilerToVM().readFieldValue((HotSpotObjectConstantImpl) base, null, displacement, true, JavaKind.Object);
|
||||
}
|
||||
if (!isValidObjectFieldDisplacement(base, displacement)) {
|
||||
return null;
|
||||
}
|
||||
if (base instanceof HotSpotMetaspaceConstant &&
|
||||
displacement == runtime.getConfig().javaMirrorOffset) {
|
||||
if (base instanceof HotSpotMetaspaceConstant) {
|
||||
MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
|
||||
return ((HotSpotResolvedObjectTypeImpl) metaspaceObject).getJavaMirror();
|
||||
if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
|
||||
HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) metaspaceObject;
|
||||
if (displacement == runtime.getConfig().javaMirrorOffset) {
|
||||
// Klass::_java_mirror is valid for all Klass* values
|
||||
return type.getJavaMirror();
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.valueOf(metaspaceObject));
|
||||
}
|
||||
}
|
||||
return readRawObject(base, displacement, false);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaConstant readNarrowOopConstant(Constant base, long displacement) {
|
||||
JavaConstant res = readRawObject(base, displacement, true);
|
||||
return JavaConstant.NULL_POINTER.equals(res) ? HotSpotCompressedNullConstant.COMPRESSED_NULL : ((HotSpotObjectConstant) res).compress();
|
||||
if (base instanceof HotSpotObjectConstantImpl) {
|
||||
assert runtime.getConfig().useCompressedOops;
|
||||
JavaConstant res = runtime.getCompilerToVM().readFieldValue((HotSpotObjectConstantImpl) base, null, displacement, true, JavaKind.Object);
|
||||
if (res != null) {
|
||||
return JavaConstant.NULL_POINTER.equals(res) ? HotSpotCompressedNullConstant.COMPRESSED_NULL : ((HotSpotObjectConstant) res).compress();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private HotSpotResolvedObjectTypeImpl readKlass(Constant base, long displacement, boolean compressed) {
|
||||
|
@ -23,6 +23,7 @@
|
||||
package jdk.vm.ci.hotspot;
|
||||
|
||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
|
||||
import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
|
||||
|
||||
import jdk.vm.ci.meta.Assumptions;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
@ -184,7 +185,15 @@ abstract class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
|
||||
}
|
||||
|
||||
public JavaConstant readFieldValue(HotSpotResolvedJavaField field, boolean isVolatile) {
|
||||
return runtime().reflection.readFieldValue(this, field, isVolatile);
|
||||
if (IS_IN_NATIVE_IMAGE && this instanceof DirectHotSpotObjectConstantImpl) {
|
||||
// cannot read fields from objects due to lack of
|
||||
// general reflection support in native image
|
||||
return null;
|
||||
}
|
||||
if (field.isStatic()) {
|
||||
return null;
|
||||
}
|
||||
return runtime().compilerToVm.readFieldValue(this, (HotSpotResolvedObjectTypeImpl) field.getDeclaringClass(), field.getOffset(), isVolatile, field.getType().getJavaKind());
|
||||
}
|
||||
|
||||
public ResolvedJavaType asJavaType() {
|
||||
|
@ -1036,10 +1036,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
return (getAccessFlags() & config().jvmAccIsCloneableFast) != 0;
|
||||
}
|
||||
|
||||
JavaConstant readFieldValue(HotSpotResolvedJavaField field, boolean isVolatile) {
|
||||
return runtime().reflection.readFieldValue(this, field, isVolatile);
|
||||
}
|
||||
|
||||
private int getMiscFlags() {
|
||||
return UNSAFE.getInt(getMetaspaceKlass() + config().instanceKlassMiscFlagsOffset);
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
package jdk.vm.ci.hotspot;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Modifier;
|
||||
@ -320,6 +319,6 @@ public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType
|
||||
|
||||
@Override
|
||||
JavaConstant getJavaMirror() {
|
||||
return runtime().reflection.getJavaMirror(this);
|
||||
return mirror;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
@ -72,29 +71,6 @@ class SharedLibraryJVMCIReflection extends HotSpotJVMCIReflection {
|
||||
throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.getEnclosingClass()");
|
||||
}
|
||||
|
||||
@Override
|
||||
JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedJavaField field, boolean isVolatile) {
|
||||
JavaConstant javaConstant = runtime().compilerToVm.readFieldValue(holder, field, isVolatile);
|
||||
if (javaConstant == null) {
|
||||
return JavaConstant.NULL_POINTER;
|
||||
}
|
||||
return javaConstant;
|
||||
}
|
||||
|
||||
@Override
|
||||
JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile) {
|
||||
if (object instanceof DirectHotSpotObjectConstantImpl) {
|
||||
// cannot read fields from objects due to lack of
|
||||
// general reflection support in native image
|
||||
return null;
|
||||
}
|
||||
JavaConstant javaConstant = runtime().compilerToVm.readFieldValue(object, field, isVolatile);
|
||||
if (javaConstant == null) {
|
||||
return JavaConstant.NULL_POINTER;
|
||||
}
|
||||
return javaConstant;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean equals(HotSpotObjectConstantImpl x, HotSpotObjectConstantImpl y) {
|
||||
if (x == y) {
|
||||
@ -117,11 +93,6 @@ class SharedLibraryJVMCIReflection extends HotSpotJVMCIReflection {
|
||||
return runtime().compilerToVm.equals(x, indirectX.getHandle(), y, indirectY.getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
JavaConstant getJavaMirror(HotSpotResolvedPrimitiveType hotSpotResolvedPrimitiveType) {
|
||||
return runtime().compilerToVm.getJavaMirror(hotSpotResolvedPrimitiveType);
|
||||
}
|
||||
|
||||
@Override
|
||||
ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod) {
|
||||
// ResolvedJavaMethod.getParameters allows a return value of null
|
||||
@ -342,29 +313,4 @@ class SharedLibraryJVMCIReflection extends HotSpotJVMCIReflection {
|
||||
JavaConstant boxPrimitive(JavaConstant source) {
|
||||
return runtime().compilerToVm.boxPrimitive(source.asBoxedPrimitive());
|
||||
}
|
||||
|
||||
@Override
|
||||
int getInt(HotSpotObjectConstantImpl object, long displacement) {
|
||||
return runtime().compilerToVm.getInt(object, displacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
byte getByte(HotSpotObjectConstantImpl object, long displacement) {
|
||||
return runtime().compilerToVm.getByte(object, displacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
short getShort(HotSpotObjectConstantImpl object, long displacement) {
|
||||
return runtime().compilerToVm.getShort(object, displacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
long getLong(HotSpotObjectConstantImpl object, long displacement) {
|
||||
return runtime().compilerToVm.getLong(object, displacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,29 @@ public interface JavaConstant extends Constant, JavaValue {
|
||||
}
|
||||
}
|
||||
|
||||
static PrimitiveConstant forPrimitive(JavaKind kind, long rawValue) {
|
||||
switch (kind) {
|
||||
case Boolean:
|
||||
return JavaConstant.forBoolean(rawValue != 0);
|
||||
case Byte:
|
||||
return JavaConstant.forByte((byte) rawValue);
|
||||
case Char:
|
||||
return JavaConstant.forChar((char) rawValue);
|
||||
case Short:
|
||||
return JavaConstant.forShort((short) rawValue);
|
||||
case Int:
|
||||
return JavaConstant.forInt((int) rawValue);
|
||||
case Long:
|
||||
return JavaConstant.forLong(rawValue);
|
||||
case Float:
|
||||
return JavaConstant.forFloat(Float.intBitsToFloat((int) rawValue));
|
||||
case Double:
|
||||
return JavaConstant.forDouble(Double.longBitsToDouble(rawValue));
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported kind: " + kind);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a boxed constant for the given boxed primitive value.
|
||||
*
|
||||
|
@ -49,7 +49,8 @@ public class MemoryAccessProviderData {
|
||||
private static final TestClass TEST_OBJECT = new TestClass();
|
||||
private static final JavaConstant TEST_CONSTANT = CONSTANT_REFLECTION.forObject(TEST_OBJECT);
|
||||
private static final JavaConstant TEST_CLASS_CONSTANT = CONSTANT_REFLECTION.forObject(TestClass.class);
|
||||
private static KindData[] PRIMITIVE_KIND_DATA = {
|
||||
|
||||
private static final KindData[] PRIMITIVE_KIND_DATA = {
|
||||
new KindData(JavaKind.Boolean, TEST_OBJECT),
|
||||
new KindData(JavaKind.Byte, TEST_OBJECT),
|
||||
new KindData(JavaKind.Char, TEST_OBJECT),
|
||||
@ -108,6 +109,28 @@ public class MemoryAccessProviderData {
|
||||
return result.toArray(new Object[result.size()][]);
|
||||
}
|
||||
|
||||
@DataProvider(name = "outOfBoundsObjectArray")
|
||||
public static Object[][] getOutOfBoundsObjectArrayReads() {
|
||||
List<Object[]> result = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Object[] objects = new Object[i];
|
||||
for (int e = 0; e < i; e++) {
|
||||
objects[e] = e;
|
||||
}
|
||||
long firstValidOffset = UNSAFE.ARRAY_OBJECT_BASE_OFFSET;
|
||||
long endOfObjectOffset = UNSAFE.ARRAY_OBJECT_BASE_OFFSET + i * UNSAFE.ARRAY_OBJECT_INDEX_SCALE;
|
||||
JavaConstant constant = CONSTANT_REFLECTION.forObject(objects);
|
||||
result.add(new Object[] {JavaKind.Object, constant, firstValidOffset, i == 0});
|
||||
result.add(new Object[] {JavaKind.Object, constant, (long) 0, true});
|
||||
result.add(new Object[] {JavaKind.Object, constant, (long) -1, true});
|
||||
result.add(new Object[] {JavaKind.Object, constant, endOfObjectOffset - UNSAFE.ARRAY_OBJECT_INDEX_SCALE, i == 0});
|
||||
result.add(new Object[] {JavaKind.Object, constant, endOfObjectOffset, true});
|
||||
result.add(new Object[] {JavaKind.Object, constant, endOfObjectOffset + 100, true});
|
||||
}
|
||||
return result.toArray(new Object[result.size()][]);
|
||||
}
|
||||
|
||||
@DataProvider(name = "negative")
|
||||
public static Object[][] getNegativeJavaKinds() {
|
||||
return new Object[][]{
|
||||
|
@ -75,7 +75,7 @@ public class MemoryAccessProviderTest {
|
||||
PROVIDER.readPrimitiveConstant(kind, base, offset, kind.getByteCount() * 8);
|
||||
Assert.assertFalse(isOutOfBounds);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
Assert.assertTrue(isOutOfBounds);
|
||||
Assert.assertTrue(isOutOfBounds, iae.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +85,17 @@ public class MemoryAccessProviderTest {
|
||||
PROVIDER.readPrimitiveConstant(kind, base, offset, kind.getByteCount() * 8);
|
||||
Assert.assertFalse(isOutOfBounds);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
Assert.assertTrue(isOutOfBounds);
|
||||
Assert.assertTrue(isOutOfBounds, iae.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "outOfBoundsObjectArray", dataProviderClass = MemoryAccessProviderData.class)
|
||||
public void testReadObjectOutOfBoundsObjectArray(JavaKind kind, Constant base, Long offset, boolean isOutOfBounds) {
|
||||
try {
|
||||
PROVIDER.readObjectConstant(base, offset);
|
||||
Assert.assertFalse(isOutOfBounds);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
Assert.assertTrue(isOutOfBounds, iae.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user