< prev index next >

src/hotspot/share/prims/jni.cpp

Print this page

        

*** 56,65 **** --- 56,66 ---- #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "oops/typeArrayKlass.hpp" #include "oops/typeArrayOop.inline.hpp" + #include "oops/valueArrayOop.inline.hpp" #include "oops/valueKlass.inline.hpp" #include "prims/jniCheck.hpp" #include "prims/jniExport.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp"
*** 495,506 **** // The slot is the index of the field description in the field-array // The jfieldID is the offset of the field within the object // It may also have hash bits for k, if VerifyJNIFields is turned on. intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot ); assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object"); ! ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset); return ret; JNI_END DT_RETURN_MARK_DECL(ToReflectedMethod, jobject --- 496,508 ---- // The slot is the index of the field description in the field-array // The jfieldID is the offset of the field within the object // It may also have hash bits for k, if VerifyJNIFields is turned on. intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot ); + bool is_flattened = InstanceKlass::cast(k1)->field_is_flattened(slot); assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object"); ! ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset, is_flattened); return ret; JNI_END DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
*** 2048,2075 **** THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig)); } // A jfieldID for a non-static field is simply the offset of the field within the instanceOop // It may also have hash bits for k, if VerifyJNIFields is turned on. ! ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset()); return ret; JNI_END JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)) JNIWrapper("GetObjectField"); HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID); oop o = JNIHandles::resolve_non_null(obj); Klass* k = o->klass(); int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); // Keep JVMTI addition small and only check enabled flag here. // jni_GetField_probe() assumes that is okay to create handles. if (JvmtiExport::should_post_field_access()) { o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); } ! oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset); ! jobject ret = JNIHandles::make_local(env, loaded_obj); HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret); return ret; JNI_END --- 2050,2098 ---- THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig)); } // A jfieldID for a non-static field is simply the offset of the field within the instanceOop // It may also have hash bits for k, if VerifyJNIFields is turned on. ! ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset(), fd.is_flattened()); return ret; JNI_END JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)) JNIWrapper("GetObjectField"); HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID); oop o = JNIHandles::resolve_non_null(obj); Klass* k = o->klass(); int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); + oop res = NULL; // Keep JVMTI addition small and only check enabled flag here. // jni_GetField_probe() assumes that is okay to create handles. if (JvmtiExport::should_post_field_access()) { o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); } ! if (!jfieldIDWorkaround::is_flattened_field(fieldID)) { ! res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset); ! } else { ! assert(k->is_instance_klass(), "Only instance can have flattened fields"); ! InstanceKlass* ik = InstanceKlass::cast(k); ! fieldDescriptor fd; ! ik->find_field_from_offset(offset, false, &fd); ! InstanceKlass* holder = fd.field_holder(); ! ValueKlass* field_vklass = ValueKlass::cast(holder->get_value_field_klass(fd.index())); ! assert(field_vklass->is_initialized(), "Must be initialized at this point"); ! ! Handle obj_h(THREAD, o); ! if (field_vklass->is_empty_value()) { ! res = (instanceOop)field_vklass->default_value(); ! } else { ! // allocate instance ! res = field_vklass->allocate_instance(CHECK_NULL); ! // copy value ! field_vklass->value_copy_payload_to_new_oop(((char*)(oopDesc*)obj_h()) + ik->field_offset(fd.index()), res); ! } ! } ! jobject ret = JNIHandles::make_local(env, res); HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret); return ret; JNI_END
*** 2163,2173 **** --- 2186,2207 ---- if (JvmtiExport::should_post_field_modification()) { jvalue field_value; field_value.l = value; o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, 'L', (jvalue *)&field_value); } + if (!jfieldIDWorkaround::is_flattened_field(fieldID)) { HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value)); + } else { + assert(k->is_instance_klass(), "Only instances can have flattened fields"); + InstanceKlass* ik = InstanceKlass::cast(k); + fieldDescriptor fd; + ik->find_field_from_offset(offset, false, &fd); + InstanceKlass* holder = fd.field_holder(); + ValueKlass* vklass = ValueKlass::cast(holder->get_value_field_klass(fd.index())); + oop v = JNIHandles::resolve_non_null(value); + vklass->value_copy_oop_to_payload(v, ((char*)(oopDesc*)o) + offset); + } HOTSPOT_JNI_SETOBJECTFIELD_RETURN(); JNI_END #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
*** 2600,2632 **** JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)) JNIWrapper("GetObjectArrayElement"); HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index); jobject ret = NULL; DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret); objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); ! if (a->is_within_bounds(index)) { ! ret = JNIHandles::make_local(env, a->obj_at(index)); ! return ret; } else { ResourceMark rm(THREAD); stringStream ss; ! ss.print("Index %d out of bounds for length %d", index, a->length()); THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string()); } JNI_END DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN()); JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value)) JNIWrapper("SetObjectArrayElement"); HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value); DT_VOID_RETURN_MARK(SetObjectArrayElement); objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); oop v = JNIHandles::resolve(value); - if (a->is_within_bounds(index)) { if (v == NULL || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) { a->obj_at_put(index, v); } else { ResourceMark rm(THREAD); stringStream ss; --- 2634,2704 ---- JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)) JNIWrapper("GetObjectArrayElement"); HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index); jobject ret = NULL; DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret); + oop res = NULL; + arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array)); + if (arr->is_within_bounds(index)) { + if (arr->is_valueArray()) { + valueArrayOop a = valueArrayOop(JNIHandles::resolve_non_null(array)); + arrayHandle ah(THREAD, a); + valueArrayHandle vah(thread, a); + res = valueArrayOopDesc::value_alloc_copy_from_index(vah, index, CHECK_NULL); + assert(res != NULL, "Must be set in one of two paths above"); + } else { + assert(arr->is_objArray(), "If not a valueArray. must be an objArray"); objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); ! res = a->obj_at(index); ! } } else { ResourceMark rm(THREAD); stringStream ss; ! ss.print("Index %d out of bounds for length %d", index,arr->length()); THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string()); } + ret = JNIHandles::make_local(env, res); + return ret; JNI_END DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN()); JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value)) JNIWrapper("SetObjectArrayElement"); HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value); DT_VOID_RETURN_MARK(SetObjectArrayElement); + bool oob = false; + int length = -1; + oop res = NULL; + arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array)); + if (arr->is_within_bounds(index)) { + if (arr->is_valueArray()) { + valueArrayOop a = valueArrayOop(JNIHandles::resolve_non_null(array)); + oop v = JNIHandles::resolve(value); + ValueArrayKlass* vaklass = ValueArrayKlass::cast(a->klass()); + ValueKlass* element_vklass = vaklass->element_klass(); + if (v != NULL && v->is_a(element_vklass)) { + a->value_copy_to_index(v, index); + } else { + ResourceMark rm(THREAD); + stringStream ss; + Klass *kl = ValueArrayKlass::cast(a->klass()); + ss.print("type mismatch: can not store %s to %s[%d]", + v->klass()->external_name(), + kl->external_name(), + index); + for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) { + ss.print("[]"); + } + THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string()); + } + } else { + assert(arr->is_objArray(), "If not a valueArray. must be an objArray"); objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); oop v = JNIHandles::resolve(value); if (v == NULL || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) { a->obj_at_put(index, v); } else { ResourceMark rm(THREAD); stringStream ss;
*** 2638,2651 **** for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) { ss.print("[]"); } THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string()); } } else { ResourceMark rm(THREAD); stringStream ss; ! ss.print("Index %d out of bounds for length %d", index, a->length()); THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string()); } JNI_END --- 2710,2724 ---- for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) { ss.print("[]"); } THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string()); } + } } else { ResourceMark rm(THREAD); stringStream ss; ! ss.print("Index %d out of bounds for length %d", index, arr->length()); THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string()); } JNI_END
< prev index next >