< prev index next >

src/hotspot/share/interpreter/interpreterRuntime.cpp

Print this page

        

*** 46,55 **** --- 46,59 ---- #include "oops/methodData.hpp" #include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" + #include "oops/valueKlass.hpp" + #include "oops/valueArrayKlass.hpp" + #include "oops/valueArrayOop.hpp" + #include "oops/valueArrayOop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "prims/nativeLookup.hpp" #include "runtime/atomic.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/compilationPolicy.hpp"
*** 68,77 **** --- 72,82 ---- #include "runtime/synchronizer.hpp" #include "runtime/threadCritical.hpp" #include "utilities/align.hpp" #include "utilities/copy.hpp" #include "utilities/events.hpp" + #include "utilities/globalDefinitions.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif class UnlockFlagSaver {
*** 252,285 **** // because the _breakpoint bytecode would be lost. oop obj = klass->allocate_instance(CHECK); thread->set_vm_result(obj); JRT_END JRT_ENTRY(void, InterpreterRuntime::newarray(JavaThread* thread, BasicType type, jint size)) oop obj = oopFactory::new_typeArray(type, size, CHECK); thread->set_vm_result(obj); JRT_END JRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* thread, ConstantPool* pool, int index, jint size)) Klass* klass = pool->klass_at(index, CHECK); ! objArrayOop obj = oopFactory::new_objArray(klass, size, CHECK); thread->set_vm_result(obj); JRT_END JRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* thread, jint* first_size_address)) // We may want to pass in more arguments - could make this slightly faster LastFrameAccessor last_frame(thread); ConstantPool* constants = last_frame.method()->constants(); ! int i = last_frame.get_index_u2(Bytecodes::_multianewarray); ! Klass* klass = constants->klass_at(i, CHECK); int nof_dims = last_frame.number_of_dimensions(); assert(klass->is_klass(), "not a class"); assert(nof_dims >= 1, "multianewarray rank must be nonzero"); // We must create an array of jints to pass to multi_allocate. ResourceMark rm(thread); const int small_dims = 10; jint dim_array[small_dims]; jint *dims = &dim_array[0]; --- 257,526 ---- // because the _breakpoint bytecode would be lost. oop obj = klass->allocate_instance(CHECK); thread->set_vm_result(obj); JRT_END + void copy_primitive_argument(intptr_t* addr, Handle instance, int offset, BasicType type) { + switch (type) { + case T_BOOLEAN: + instance()->bool_field_put(offset, (jboolean)*((int*)addr)); + break; + case T_CHAR: + instance()->char_field_put(offset, (jchar) *((int*)addr)); + break; + case T_FLOAT: + instance()->float_field_put(offset, (jfloat)*((float*)addr)); + break; + case T_DOUBLE: + instance()->double_field_put(offset, (jdouble)*((double*)addr)); + break; + case T_BYTE: + instance()->byte_field_put(offset, (jbyte)*((int*)addr)); + break; + case T_SHORT: + instance()->short_field_put(offset, (jshort)*((int*)addr)); + break; + case T_INT: + instance()->int_field_put(offset, (jint)*((int*)addr)); + break; + case T_LONG: + instance()->long_field_put(offset, (jlong)*((long long*)addr)); + break; + case T_OBJECT: + case T_ARRAY: + case T_VALUETYPE: + fatal("Should not be handled with this method"); + break; + default: + fatal("Unsupported BasicType"); + } + } + + JRT_ENTRY(void, InterpreterRuntime::defaultvalue(JavaThread* thread, ConstantPool* pool, int index)) + // Getting the ValueKlass + Klass* k = pool->klass_at(index, CHECK); + assert(k->is_value(), "defaultvalue argument must be the value type class"); + ValueKlass* vklass = ValueKlass::cast(k); + + vklass->initialize(THREAD); + oop res = vklass->default_value(); + thread->set_vm_result(res); + JRT_END + + JRT_ENTRY(int, InterpreterRuntime::withfield(JavaThread* thread, ConstantPoolCache* cp_cache)) + LastFrameAccessor last_frame(thread); + // Getting the ValueKlass + int index = ConstantPool::decode_cpcache_index(last_frame.get_index_u2_cpcache(Bytecodes::_withfield)); + ConstantPoolCacheEntry* cp_entry = cp_cache->entry_at(index); + assert(cp_entry->is_resolved(Bytecodes::_withfield), "Should have been resolved"); + Klass* klass = cp_entry->f1_as_klass(); + assert(klass->is_value(), "withfield only applies to value types"); + ValueKlass* vklass = ValueKlass::cast(klass); + + // Getting Field information + int offset = cp_entry->f2_as_index(); + int field_index = cp_entry->field_index(); + int field_offset = cp_entry->f2_as_offset(); + Symbol* field_signature = vklass->field_signature(field_index); + ResourceMark rm(THREAD); + const char* signature = (const char *) field_signature->as_utf8(); + BasicType field_type = char2type(signature[0]); + + // Getting old value + frame& f = last_frame.get_frame(); + jint tos_idx = f.interpreter_frame_expression_stack_size() - 1; + int vt_offset = type2size[field_type]; + oop old_value = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx - vt_offset); + assert(old_value != NULL && oopDesc::is_oop(old_value) && old_value->is_value(),"Verifying receiver"); + Handle old_value_h(THREAD, old_value); + + // Creating new value by copying the one passed in argument + instanceOop new_value = vklass->allocate_instance( + CHECK_((type2size[field_type]) * AbstractInterpreter::stackElementSize)); + Handle new_value_h = Handle(THREAD, new_value); + int first_offset = vklass->first_field_offset(); + vklass->value_store(vklass->data_for_oop(old_value_h()), + vklass->data_for_oop(new_value_h()), true, false); + + // Updating the field specified in arguments + if (field_type == T_ARRAY || field_type == T_OBJECT) { + oop aoop = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx); + assert(aoop == NULL || oopDesc::is_oop(aoop),"argument must be a reference type"); + new_value_h()->obj_field_put(field_offset, aoop); + } else if (field_type == T_VALUETYPE) { + if (cp_entry->is_flattened()) { + oop vt_oop = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx); + if (vt_oop == NULL) { + THROW_(vmSymbols::java_lang_NullPointerException(), + (type2size[field_type] * AbstractInterpreter::stackElementSize)); + } + assert(vt_oop != NULL && oopDesc::is_oop(vt_oop) && vt_oop->is_value(),"argument must be a value type"); + Klass* field_k = vklass->get_value_field_klass(field_index); + ValueKlass* field_vk = ValueKlass::cast(field_k); + assert(field_vk == vt_oop->klass(), "Must match"); + field_vk->value_store(field_vk->data_for_oop(vt_oop), + ((char*)(oopDesc*)new_value_h()) + field_offset, false, false); + } else { // not flattened + oop voop = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx); + if (voop == NULL && cp_entry->is_flattenable()) { + THROW_(vmSymbols::java_lang_NullPointerException(), + (type2size[field_type] * AbstractInterpreter::stackElementSize)); + } + assert(voop == NULL || oopDesc::is_oop(voop),"checking argument"); + new_value_h()->obj_field_put(field_offset, voop); + } + } else { // not T_OBJECT nor T_ARRAY nor T_VALUETYPE + intptr_t* addr = f.interpreter_frame_expression_stack_at(tos_idx); + copy_primitive_argument(addr, new_value_h, field_offset, field_type); + } + + // returning result + thread->set_vm_result(new_value_h()); + return (type2size[field_type] + type2size[T_OBJECT]) * AbstractInterpreter::stackElementSize; + JRT_END + + JRT_ENTRY(void, InterpreterRuntime::uninitialized_static_value_field(JavaThread* thread, oopDesc* mirror, int index)) + // The interpreter tries to access a flattenable static field that has not been initialized. + // This situation can happen only if the load or initialization of the field failed during step 8 of + // the initialization of the holder of the field. The code below tries to load and initialize + // the field's class again in order to throw likely the same exception or error as the one that caused + // the field initialization to fail. + instanceHandle mirror_h(THREAD, (instanceOop)mirror); + InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); + int offset = klass->field_offset(index); + Klass* field_k = klass->get_value_field_klass_or_null(index); + if (field_k == NULL) { + field_k = SystemDictionary::resolve_or_fail(klass->field_signature(index)->fundamental_name(THREAD), + Handle(THREAD, klass->class_loader()), + Handle(THREAD, klass->protection_domain()), + true, CHECK); + assert(field_k != NULL, "Should have been loaded or an exception thrown above"); + klass->set_value_field_klass(index, field_k); + } + field_k->initialize(CHECK); + fatal("An exception should have been thrown above"); + JRT_END + + JRT_ENTRY(void, InterpreterRuntime::uninitialized_instance_value_field(JavaThread* thread, oopDesc* obj, int index)) + instanceHandle obj_h(THREAD, (instanceOop)obj); + InstanceKlass* klass = InstanceKlass::cast(obj_h()->klass()); + Klass* field_k = klass->get_value_field_klass_or_null(index); + assert(field_k != NULL, "Must have been initialized"); + ValueKlass* field_vklass = ValueKlass::cast(field_k); + assert(field_vklass->is_initialized(), "Must have been initialized at this point"); + instanceOop res = (instanceOop)field_vklass->default_value(); + thread->set_vm_result(res); + JRT_END + + JRT_ENTRY(void, InterpreterRuntime::write_flattened_value(JavaThread* thread, oopDesc* value, int offset, oopDesc* rcv)) + assert(oopDesc::is_oop(value), "Sanity check"); + assert(oopDesc::is_oop(rcv), "Sanity check"); + assert(value->is_value(), "Sanity check"); + + ValueKlass* vklass = ValueKlass::cast(value->klass()); + if (!vklass->is_empty_value()) { + vklass->value_store(vklass->data_for_oop(value), ((char*)(oopDesc*)rcv) + offset, true, true); + } + JRT_END + + JRT_ENTRY(void, InterpreterRuntime::read_flattened_field(JavaThread* thread, oopDesc* obj, int index, Klass* field_holder)) + Handle obj_h(THREAD, obj); + + assert(oopDesc::is_oop(obj), "Sanity check"); + + assert(field_holder->is_instance_klass(), "Sanity check"); + InstanceKlass* klass = InstanceKlass::cast(field_holder); + + assert(klass->field_is_flattened(index), "Sanity check"); + + ValueKlass* field_vklass = ValueKlass::cast(klass->get_value_field_klass(index)); + assert(field_vklass->is_initialized(), "Must be initialized at this point"); + + instanceOop res = NULL; + if (field_vklass->is_empty_value()) { + res = (instanceOop)field_vklass->default_value(); + } else { + // allocate instance + res = field_vklass->allocate_instance(CHECK); + // copy value + field_vklass->value_store(((char*)(oopDesc*)obj_h()) + klass->field_offset(index), + field_vklass->data_for_oop(res), true, true); + } + assert(res != NULL, "Must be set in one of two paths above"); + thread->set_vm_result(res); + JRT_END JRT_ENTRY(void, InterpreterRuntime::newarray(JavaThread* thread, BasicType type, jint size)) oop obj = oopFactory::new_typeArray(type, size, CHECK); thread->set_vm_result(obj); JRT_END JRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* thread, ConstantPool* pool, int index, jint size)) Klass* klass = pool->klass_at(index, CHECK); ! bool is_qtype_desc = pool->tag_at(index).is_Qdescriptor_klass(); ! arrayOop obj; ! if ((!klass->is_array_klass()) && is_qtype_desc) { // Logically creates elements, ensure klass init ! klass->initialize(CHECK); ! obj = oopFactory::new_valueArray(klass, size, CHECK); ! } else { ! obj = oopFactory::new_objArray(klass, size, CHECK); ! } thread->set_vm_result(obj); JRT_END + JRT_ENTRY(void, InterpreterRuntime::value_array_load(JavaThread* thread, arrayOopDesc* array, int index)) + Klass* klass = array->klass(); + assert(klass->is_valueArray_klass(), "expected value array oop"); + + ValueArrayKlass* vaklass = ValueArrayKlass::cast(klass); + ValueKlass* vklass = vaklass->element_klass(); + arrayHandle ah(THREAD, array); + instanceOop value_holder = NULL; + if (vklass->is_empty_value()) { + value_holder = (instanceOop)vklass->default_value(); + } else { + value_holder = vklass->allocate_instance(CHECK); + void* src = ((valueArrayOop)ah())->value_at_addr(index, vaklass->layout_helper()); + vklass->value_store(src, vklass->data_for_oop(value_holder), + vaklass->element_byte_size(), true, false); + } + assert(value_holder != NULL, "Must be set in one of two paths above"); + thread->set_vm_result(value_holder); + JRT_END + + JRT_ENTRY(void, InterpreterRuntime::value_array_store(JavaThread* thread, void* val, arrayOopDesc* array, int index)) + assert(val != NULL, "can't store null into flat array"); + Klass* klass = array->klass(); + assert(klass->is_valueArray_klass(), "expected value array"); + assert(ArrayKlass::cast(klass)->element_klass() == ((oop)val)->klass(), "Store type incorrect"); + + valueArrayOop varray = (valueArrayOop)array; + ValueArrayKlass* vaklass = ValueArrayKlass::cast(klass); + ValueKlass* vklass = vaklass->element_klass(); + if (!vklass->is_empty_value()) { + const int lh = vaklass->layout_helper(); + vklass->value_store(vklass->data_for_oop((oop)val), varray->value_at_addr(index, lh), + vaklass->element_byte_size(), true, false); + } + JRT_END JRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* thread, jint* first_size_address)) // We may want to pass in more arguments - could make this slightly faster LastFrameAccessor last_frame(thread); ConstantPool* constants = last_frame.method()->constants(); ! int i = last_frame.get_index_u2(Bytecodes::_multianewarray); ! Klass* klass = constants->klass_at(i, CHECK); ! bool is_qtype = klass->name()->is_Q_array_signature(); int nof_dims = last_frame.number_of_dimensions(); assert(klass->is_klass(), "not a class"); assert(nof_dims >= 1, "multianewarray rank must be nonzero"); + if (is_qtype) { // Logically creates elements, ensure klass init + klass->initialize(CHECK); + } + // We must create an array of jints to pass to multi_allocate. ResourceMark rm(thread); const int small_dims = 10; jint dim_array[small_dims]; jint *dims = &dim_array[0];
*** 300,309 **** --- 541,564 ---- assert(oopDesc::is_oop(obj), "must be a valid oop"); assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise"); InstanceKlass::register_finalizer(instanceOop(obj), CHECK); JRT_END + JRT_ENTRY(jboolean, InterpreterRuntime::is_substitutable(JavaThread* thread, oopDesc* aobj, oopDesc* bobj)) + assert(oopDesc::is_oop(aobj) && oopDesc::is_oop(bobj), "must be valid oops"); + + Handle ha(THREAD, aobj); + Handle hb(THREAD, bobj); + JavaValue result(T_BOOLEAN); + JavaCallArguments args; + args.push_oop(ha); + args.push_oop(hb); + methodHandle method(Universe::is_substitutable_method()); + JavaCalls::call(&result, method, &args, THREAD); + guarantee(!HAS_PENDING_EXCEPTION, "isSubstitutable() raised exception"); + return result.get_jboolean(); + JRT_END // Quicken instance-of and check-cast bytecodes JRT_ENTRY(void, InterpreterRuntime::quicken_io_cc(JavaThread* thread)) // Force resolving; quicken the bytecode LastFrameAccessor last_frame(thread);
*** 686,697 **** fieldDescriptor info; LastFrameAccessor last_frame(thread); constantPoolHandle pool(thread, last_frame.method()->constants()); methodHandle m(thread, last_frame.method()); bool is_put = (bytecode == Bytecodes::_putfield || bytecode == Bytecodes::_nofast_putfield || ! bytecode == Bytecodes::_putstatic); bool is_static = (bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic); { JvmtiHideSingleStepping jhss(thread); LinkResolver::resolve_field_access(info, pool, last_frame.get_index_u2_cpcache(bytecode), m, bytecode, CHECK); --- 941,953 ---- fieldDescriptor info; LastFrameAccessor last_frame(thread); constantPoolHandle pool(thread, last_frame.method()->constants()); methodHandle m(thread, last_frame.method()); bool is_put = (bytecode == Bytecodes::_putfield || bytecode == Bytecodes::_nofast_putfield || ! bytecode == Bytecodes::_putstatic || bytecode == Bytecodes::_withfield); bool is_static = (bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic); + bool is_value = bytecode == Bytecodes::_withfield; { JvmtiHideSingleStepping jhss(thread); LinkResolver::resolve_field_access(info, pool, last_frame.get_index_u2_cpcache(bytecode), m, bytecode, CHECK);
*** 731,743 **** assert(!(has_initialized_final_update && !info.access_flags().is_final()), "Fields with initialized final updates must be final"); Bytecodes::Code get_code = (Bytecodes::Code)0; Bytecodes::Code put_code = (Bytecodes::Code)0; if (!uninitialized_static) { ! get_code = ((is_static) ? Bytecodes::_getstatic : Bytecodes::_getfield); ! if ((is_put && !has_initialized_final_update) || !info.access_flags().is_final()) { ! put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield); } } cp_cache_entry->set_field( get_code, --- 987,1005 ---- assert(!(has_initialized_final_update && !info.access_flags().is_final()), "Fields with initialized final updates must be final"); Bytecodes::Code get_code = (Bytecodes::Code)0; Bytecodes::Code put_code = (Bytecodes::Code)0; if (!uninitialized_static) { ! if (is_static) { ! get_code = Bytecodes::_getstatic; ! } else { ! get_code = Bytecodes::_getfield; ! } ! if (is_put && is_value) { ! put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_withfield); ! } else if ((is_put && !has_initialized_final_update) || !info.access_flags().is_final()) { ! put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield); } } cp_cache_entry->set_field( get_code,
*** 746,755 **** --- 1008,1019 ---- info.index(), info.offset(), state, info.access_flags().is_final(), info.access_flags().is_volatile(), + info.is_flattened(), + info.is_flattenable(), pool->pool_holder() ); }
*** 856,867 **** methodHandle m (thread, last_frame.method()); Bytecode_invoke call(m, last_frame.bci()); Symbol* signature = call.signature(); receiver = Handle(thread, last_frame.callee_receiver(signature)); ! assert(Universe::heap()->is_in_reserved_or_null(receiver()), ! "sanity check"); assert(receiver.is_null() || !Universe::heap()->is_in_reserved(receiver->klass()), "sanity check"); } --- 1120,1130 ---- methodHandle m (thread, last_frame.method()); Bytecode_invoke call(m, last_frame.bci()); Symbol* signature = call.signature(); receiver = Handle(thread, last_frame.callee_receiver(signature)); ! assert(Universe::heap()->is_in_reserved_or_null(receiver()), "sanity check"); assert(receiver.is_null() || !Universe::heap()->is_in_reserved(receiver->klass()), "sanity check"); }
*** 999,1008 **** --- 1262,1272 ---- switch (bytecode) { case Bytecodes::_getstatic: case Bytecodes::_putstatic: case Bytecodes::_getfield: case Bytecodes::_putfield: + case Bytecodes::_withfield: resolve_get_put(thread, bytecode); break; case Bytecodes::_invokevirtual: case Bytecodes::_invokespecial: case Bytecodes::_invokestatic:
*** 1263,1272 **** --- 1527,1542 ---- case atos: sig_type = 'L'; break; case ltos: sig_type = 'J'; break; case dtos: sig_type = 'D'; break; default: ShouldNotReachHere(); return; } + + // Both Q-signatures and L-signatures are mapped to atos + if (cp_entry->flag_state() == atos && ik->field_signature(index)->is_Q_signature()) { + sig_type = 'Q'; + } + bool is_static = (obj == NULL); HandleMark hm(thread); jfieldID fid = jfieldIDWorkaround::to_jfieldID(ik, cp_entry->f2_as_index(), is_static); jvalue fvalue;
< prev index next >