--- old/src/share/vm/interpreter/interpreterRuntime.cpp 2017-06-20 16:28:12.858152214 -0400 +++ new/src/share/vm/interpreter/interpreterRuntime.cpp 2017-06-20 16:28:12.318149536 -0400 @@ -38,6 +38,7 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" +#include "memory/vtBuffer.hpp" #include "oops/constantPool.hpp" #include "oops/instanceKlass.hpp" #include "oops/methodData.hpp" @@ -193,7 +194,7 @@ instance()->int_field_put(offset, (jint)*((int*)addr)); break; case T_LONG: - instance()->long_field_put(offset, (jlong)*((long*)addr)); // Is it correct on 32 and 64 bits? + instance()->long_field_put(offset, (jlong)*((long long*)addr)); break; case T_OBJECT: case T_ARRAY: @@ -214,14 +215,10 @@ vklass->initialize(THREAD); // Creating value - instanceOop value = vklass->allocate_instance(CHECK); + bool in_heap; + instanceOop value = vklass->allocate_buffered_or_heap_instance(&in_heap, CHECK); Handle value_h = Handle(THREAD, value); - // Zeroing, already performed by allocate_instance() when allocating in the Java Heap - // Might need to be performed manually for off-heap allocations - // memset(((char*)(oopDesc*)value) + vklass_h->first_field_offset(), 0, - // vklass_h->size_helper() * wordSize - vklass_h->first_field_offset()); - thread->set_vm_result(value_h()); IRT_END @@ -252,11 +249,13 @@ Handle old_value_h(THREAD, old_value); // Creating new value by copying the one passed in argument - instanceOop new_value = vklass->allocate_instance(CHECK_0); + bool in_heap; + instanceOop new_value = vklass->allocate_buffered_or_heap_instance(&in_heap, + CHECK_((type2size[field_type]) * AbstractInterpreter::stackElementSize)); Handle new_value_h = Handle(THREAD, new_value); int first_offset = vklass->first_field_offset(); - vklass->value_store(((char*)(oopDesc*)old_value_h()) + first_offset, - ((char*)(oopDesc*)new_value_h()) + first_offset, true, false); + vklass->value_store(vklass->data_for_oop(old_value_h()), + vklass->data_for_oop(new_value_h()), in_heap, false); // Updating the field specified in arguments if (field_type == T_OBJECT || field_type == T_ARRAY) { @@ -269,8 +268,8 @@ oop vt_oop = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx); assert(vt_oop != NULL && vt_oop->is_oop() && vt_oop->is_value(),"argument must be a value type"); assert(field_vk == vt_oop->klass(), "Must match"); - field_vk->value_store(((char*)(oopDesc*)vt_oop + field_vk->first_field_offset()), - ((char*)(oopDesc*)new_value_h()) + fd.offset(), true, false); + field_vk->value_store(field_vk->data_for_oop(vt_oop), + ((char*)(oopDesc*)new_value_h()) + fd.offset(), true, false); } else { intptr_t* addr = f.interpreter_frame_expression_stack_at(tos_idx); copy_primitive_argument(addr, new_value_h, fd.offset(), field_type); @@ -300,11 +299,10 @@ if (vtklass->get_vcc_klass() != target_klass) { THROW_MSG(vmSymbols::java_lang_ClassCastException(), "vbox target is not derive value type box"); } - - oop boxed = vtklass->derive_value_type_copy(Handle(THREAD, value), - InstanceKlass::cast(target_klass), - CHECK); - thread->set_vm_result(boxed); + oop box = vtklass->box(Handle(THREAD, value), + InstanceKlass::cast(target_klass), + CHECK); + thread->set_vm_result(box); IRT_END IRT_ENTRY(void, InterpreterRuntime::vunbox(JavaThread* thread, ConstantPool* pool, int index, oopDesc* obj)) @@ -323,9 +321,9 @@ if (klass != InstanceKlass::cast(target_klass)->get_vcc_klass()) { THROW_MSG(vmSymbols::java_lang_ClassCastException(), "vunbox target is not derive value type"); } - oop value = ValueKlass::cast(target_klass)->derive_value_type_copy(Handle(THREAD, obj), - InstanceKlass::cast(target_klass), - CHECK); + oop value = ValueKlass::cast(target_klass)->unbox(Handle(THREAD, obj), + InstanceKlass::cast(target_klass), + CHECK); thread->set_vm_result(value); IRT_END @@ -337,28 +335,90 @@ klass->find_field_from_offset(offset, false, &fd); Klass* field_k = klass->get_value_field_klass(fd.index()); ValueKlass* field_vklass = ValueKlass::cast(field_k); + field_vklass->initialize(THREAD); + // allocate instance - instanceOop res = field_vklass->allocate_instance(CHECK); + bool in_heap; + instanceOop res = field_vklass->allocate_buffered_or_heap_instance(&in_heap, CHECK); + instanceHandle res_h(THREAD, res); // copy value - int size = field_vklass->layout_helper_size_in_bytes(field_vklass->layout_helper()); field_vklass->value_store(((char*)(oopDesc*)value_h()) + offset, - ((char*)(oopDesc*)res) + field_vklass->first_field_offset(),true, false); - thread->set_vm_result(res); + field_vklass->data_for_oop(res), in_heap, false); + thread->set_vm_result(res_h()); +IRT_END + +IRT_ENTRY(void, InterpreterRuntime::initialize_static_value_field(JavaThread* thread, oopDesc* mirror, int offset)) + instanceHandle mirror_h(THREAD, (instanceOop)mirror); + InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); + assert(mirror->obj_field(offset) == NULL,"Field must not be initialized twice"); + + fieldDescriptor fd; + klass->find_field_from_offset(offset, true, &fd); + Klass* field_k = klass->get_value_field_klass(fd.index()); + ValueKlass* field_vklass = ValueKlass::cast(field_k); + // allocate instance, because it is going to be assigned to a static field + // it must not be a buffered value + instanceOop res = field_vklass->allocate_instance(CHECK); + instanceHandle res_h(THREAD, res); + mirror_h()->obj_field_put(offset, res_h()); + thread->set_vm_result(res_h()); IRT_END IRT_ENTRY(void, InterpreterRuntime::qputfield(JavaThread* thread, oopDesc* obj, oopDesc* value, int offset)) Handle value_h(THREAD, value); Handle obj_h(THREAD, obj); + assert(!obj_h()->klass()->is_value(), "obj must be an object"); + assert(value_h()->klass()->is_value(), "value must be an value type"); - InstanceKlass* klass_h = InstanceKlass::cast(obj->klass()); + InstanceKlass* klass = InstanceKlass::cast(obj->klass()); + fieldDescriptor fd; + klass->find_field_from_offset(offset, false, &fd); + Klass* field_k = klass->get_value_field_klass(fd.index()); ValueKlass* field_vklass = ValueKlass::cast(value->klass()); - + assert(field_k == field_vklass, "Field descriptor and argument must match"); // copy value - int size = field_vklass->layout_helper_size_in_bytes(field_vklass->layout_helper()); - field_vklass->value_store(((char*)(oopDesc*)value_h()) + field_vklass->first_field_offset(), + field_vklass->value_store(field_vklass->data_for_oop(value_h()), ((char*)(oopDesc*)obj_h()) + offset, true, false); IRT_END +IRT_ENTRY(void, InterpreterRuntime::qputstatic(JavaThread* thread, oopDesc* value)) + instanceHandle value_h(THREAD, (instanceOop)value); + assert(value_h()->is_value(), "qputstatic only deals with value arguments"); + Method* m = last_frame(thread).interpreter_frame_method(); + jint bci = last_frame(thread).interpreter_frame_bci(); + assert(m->code_at(bci) == Bytecodes::_putstatic, "qputstatic is a particular case of putstatic"); + ConstantPoolCache* cp_cache = last_frame(thread).interpreter_frame_method()->constants()->cache(); + int index = ConstantPool::decode_cpcache_index(get_index_u2_cpcache(thread, Bytecodes::_putstatic)); + ConstantPoolCacheEntry* cp_entry = cp_cache->entry_at(index); + assert(cp_entry->is_field_entry(), "Sanity check"); + + InstanceKlass* klass = InstanceKlass::cast(cp_entry->f1_as_klass()); + int offset = cp_entry->f2_as_index(); + oop mirror = klass->java_mirror(); + + if (Universe::heap()->is_in_reserved(value_h())) { + mirror->obj_field_put(offset, value_h()); + } else { + // The argument is a buffered value, a copy must be created in the Java heap + // because a static field cannot point to a thread-local buffered value + fieldDescriptor fd; + klass->find_field_from_offset(offset, false, &fd); + Klass* field_k = klass->get_value_field_klass(fd.index()); + ValueKlass* field_vklass = ValueKlass::cast(field_k); + assert(field_vklass == value->klass(), "Field descriptor and argument must match"); + // allocate heap instance + instanceOop res = field_vklass->allocate_instance(CHECK); + assert(Universe::heap()->is_in_reserved(res), "Must be in the Java heap"); + instanceHandle res_h(THREAD, res); + // copy value + field_vklass->value_store(field_vklass->data_for_oop(value_h()), + field_vklass->data_for_oop(res), true, false); + // writing static field + mirror->obj_field_put(offset, res_h()); + assert(mirror->obj_field(offset) != NULL,"Sanity check"); + } +IRT_END + IRT_ENTRY(void, InterpreterRuntime::newarray(JavaThread* thread, BasicType type, jint size)) oop obj = oopFactory::new_typeArray(type, size, CHECK); thread->set_vm_result(obj); @@ -382,14 +442,14 @@ thread->set_vm_result(((objArrayOop) array)->obj_at(index)); } else { - // Early prototype: we don't have valorind support...just allocate aref and copy ValueArrayKlass* vaklass = ValueArrayKlass::cast(klass); ValueKlass* vklass = vaklass->element_klass(); arrayHandle ah(THREAD, array); - instanceOop value_holder = vklass->allocate_instance(CHECK); + bool in_heap; + instanceOop value_holder = vklass->allocate_buffered_or_heap_instance(&in_heap, 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, true); + vaklass->element_byte_size(), in_heap, false); thread->set_vm_result(value_holder); } IRT_END @@ -402,9 +462,25 @@ THROW(vmSymbols::java_lang_ArrayStoreException()); } if (klass->is_objArray_klass()) { + if(!Universe::heap()->is_in_reserved(val)) { + // A Java heap allocated copy must be made because an array cannot + // reference a thread-local buffered value + Handle val_h(THREAD, (oop)val); + ObjArrayKlass* aklass = ObjArrayKlass::cast(klass); + Klass* eklass = aklass->element_klass(); + assert(eklass->is_value(), "Sanity check"); + assert(eklass == ((oop)val)->klass(), "Sanity check"); + ValueKlass* vklass = ValueKlass::cast(eklass); + // allocate heap instance + instanceOop res = vklass->allocate_instance(CHECK); + Handle res_h(THREAD, res); + // copy value + vklass->value_store(((char*)(oopDesc*)val_h()) + vklass->first_field_offset(), + ((char*)(oopDesc*)res_h()) + vklass->first_field_offset(),true, false); + val = res_h(); + } ((objArrayOop) array)->obj_at_put(index, (oop)val); - } - else { + } else { valueArrayOop varray = (valueArrayOop)array; ValueArrayKlass* vaklass = ValueArrayKlass::cast(klass); ValueKlass* vklass = vaklass->element_klass(); @@ -444,6 +520,58 @@ thread->set_vm_result(obj); IRT_END +IRT_ENTRY(void, InterpreterRuntime::recycle_vtbuffer(JavaThread* thread)) + VTBuffer::recycle_vtbuffer(thread, last_frame(thread)); +IRT_END + +IRT_ENTRY(void, InterpreterRuntime::recycle_buffered_values(JavaThread* thread)) + frame f = thread->last_frame(); + assert(f.is_interpreted_frame(), "recycling can only be triggered from interpreted frames"); + VTBuffer::recycle_vt_in_frame(thread, &f); +IRT_END + +IRT_ENTRY(void, InterpreterRuntime::fix_frame_vt_alloc_ptr(JavaThread* thread)) + frame f = thread->last_frame(); + VTBuffer::fix_frame_vt_alloc_ptr(f, VTBufferChunk::chunk(thread->vt_alloc_ptr())); +IRT_END + +IRT_ENTRY(void, InterpreterRuntime::return_value(JavaThread* thread, oopDesc* obj)) + if (Universe::heap()->is_in_reserved(obj)) { + thread->set_vm_result(obj); + return; + } + assert(obj->klass()->is_value(), "Sanity check"); + ValueKlass* vk = ValueKlass::cast(obj->klass()); + RegisterMap reg_map(thread, false); + frame current_frame = last_frame(thread); + frame caller_frame = current_frame.sender(®_map); + if (!caller_frame.is_interpreted_frame()) { + // caller is not an interpreted frame, creating a new value in Java heap + Handle obj_h(THREAD, obj); + instanceOop res = vk->allocate_instance(CHECK); + Handle res_h(THREAD, res); + // copy value + vk->value_store(vk->data_for_oop(obj_h()), + vk->data_for_oop(res_h()), true, false); + thread->set_vm_result(res_h()); + return; + } else { + oop dest = VTBuffer::relocate_return_value(thread, current_frame, obj); + thread->set_vm_result(dest); + } +IRT_END + +IRT_ENTRY(void, InterpreterRuntime::check_areturn(JavaThread* thread, oopDesc* obj)) + if (obj != NULL) { + Klass* k = obj->klass(); + if (k->is_value()) { + ResourceMark rm(thread); + tty->print_cr("areturn used on a value from %s", k->name()->as_C_string()); + } + assert(!k->is_value(), "areturn should never be used on values"); + } + thread->set_vm_result(obj); +IRT_END IRT_ENTRY(void, InterpreterRuntime::register_finalizer(JavaThread* thread, oopDesc* obj)) assert(obj->is_oop(), "must be a valid oop"); @@ -974,7 +1102,8 @@ Symbol* signature = call.signature(); receiver = Handle(thread, thread->last_frame().interpreter_callee_receiver(signature)); - assert(Universe::heap()->is_in_reserved_or_null(receiver()), + assert(Universe::heap()->is_in_reserved_or_null(receiver()) + || VTBuffer::is_in_vt_buffer(receiver()), "sanity check"); assert(receiver.is_null() || !Universe::heap()->is_in_reserved(receiver->klass()),