< prev index next >
src/share/vm/interpreter/interpreterRuntime.cpp
Print this page
@@ -36,10 +36,11 @@
#include "interpreter/templateTable.hpp"
#include "logging/log.hpp"
#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"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
@@ -191,11 +192,11 @@
break;
case T_INT:
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:
case T_VALUETYPE:
fatal("Should not be handled with this method");
@@ -212,18 +213,14 @@
ValueKlass* vklass = ValueKlass::cast(k);
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
IRT_ENTRY(int, InterpreterRuntime::vwithfield(JavaThread* thread, ConstantPoolCache* cp_cache))
// Getting the ValueKlass
@@ -250,15 +247,17 @@
oop old_value = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx - vt_offset);
assert(old_value != NULL && old_value->is_oop() && 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_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) {
oop aoop = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx);
assert(aoop == NULL || (aoop->is_oop() && (!aoop->is_value())),"argument must be a reference type");
@@ -267,11 +266,11 @@
Klass* field_k = vklass->get_value_field_klass(fd.index());
ValueKlass* field_vk = ValueKlass::cast(field_k);
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()),
+ 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);
}
@@ -298,15 +297,14 @@
}
ValueKlass* vtklass = ValueKlass::cast(klass);
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),
+ oop box = vtklass->box(Handle(THREAD, value),
InstanceKlass::cast(target_klass),
CHECK);
- thread->set_vm_result(boxed);
+ thread->set_vm_result(box);
IRT_END
IRT_ENTRY(void, InterpreterRuntime::vunbox(JavaThread* thread, ConstantPool* pool, int index, oopDesc* obj))
assert(EnableMVT, "vunbox is supported only when the MVT programming model is enabled");
if (obj == NULL) {
@@ -321,11 +319,11 @@
THROW_MSG(vmSymbols::java_lang_ClassCastException(), "vunbox source is not an instance");
}
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),
+ oop value = ValueKlass::cast(target_klass)->unbox(Handle(THREAD, obj),
InstanceKlass::cast(target_klass),
CHECK);
thread->set_vm_result(value);
IRT_END
@@ -335,32 +333,94 @@
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);
+ 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);
IRT_END
@@ -380,18 +440,18 @@
if (klass->is_objArray_klass()) {
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
IRT_ENTRY(void, InterpreterRuntime::value_array_store(JavaThread* thread, arrayOopDesc* array, int index, void* val))
@@ -400,13 +460,29 @@
if (ArrayKlass::cast(klass)->element_klass() != ((oop)val)->klass()) {
THROW(vmSymbols::java_lang_ArrayStoreException());
}
if (klass->is_objArray_klass()) {
- ((objArrayOop) array)->obj_at_put(index, (oop)val);
+ 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();
}
- else {
+ ((objArrayOop) array)->obj_at_put(index, (oop)val);
+ } else {
valueArrayOop varray = (valueArrayOop)array;
ValueArrayKlass* vaklass = ValueArrayKlass::cast(klass);
ValueKlass* vklass = vaklass->element_klass();
const int lh = vaklass->layout_helper();
vklass->value_store(vklass->data_for_oop((oop)val), varray->value_at_addr(index, lh),
@@ -442,10 +518,62 @@
}
oop obj = ArrayKlass::cast(klass)->multi_allocate(nof_dims, dims, CHECK);
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");
assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
@@ -972,11 +1100,12 @@
methodHandle m (thread, method(thread));
Bytecode_invoke call(m, bci(thread));
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()),
"sanity check");
}
< prev index next >