< prev index next >
src/hotspot/share/interpreter/interpreterRuntime.cpp
Print this page
*** 45,54 ****
--- 45,58 ----
#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"
*** 67,76 ****
--- 71,81 ----
#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 {
*** 251,273 ****
// because the _breakpoint bytecode would be lost.
oop obj = klass->allocate_instance(CHECK);
thread->set_vm_result(obj);
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
IRT_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);
IRT_END
IRT_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();
--- 256,478 ----
// because the _breakpoint bytecode would be lost.
oop obj = klass->allocate_instance(CHECK);
thread->set_vm_result(obj);
IRT_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");
+ }
+ }
+
+ IRT_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);
+ IRT_END
+
+ IRT_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;
+ IRT_END
+
+ IRT_ENTRY(void, InterpreterRuntime::uninitialized_static_value_field(JavaThread* thread, oopDesc* mirror, int index))
+ 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);
+ assert(field_k != NULL, "Must have been initialized");
+ ValueKlass* field_vklass = ValueKlass::cast(field_k);
+ instanceOop res = (instanceOop)field_vklass->default_value();
+ thread->set_vm_result(res);
+ IRT_END
+
+ IRT_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);
+ IRT_END
+
+ IRT_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());
+ vklass->value_store(vklass->data_for_oop(value), ((char*)(oopDesc*)rcv) + offset, true, true);
+ IRT_END
+
+ IRT_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");
+
+ // allocate instance
+ instanceOop 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);
+ thread->set_vm_result(res);
+ 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
IRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* thread, ConstantPool* pool, int index, jint size))
Klass* klass = pool->klass_at(index, CHECK);
! if (klass->is_value()) { // Logically creates elements, ensure klass init
! klass->initialize(CHECK);
! }
! arrayOop obj = oopFactory::new_array(klass, size, CHECK);
thread->set_vm_result(obj);
IRT_END
+ IRT_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 = 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);
+ thread->set_vm_result(value_holder);
+ IRT_END
+
+ IRT_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();
+ 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);
+ IRT_END
IRT_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();
*** 275,284 ****
--- 480,493 ----
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");
+ if (klass->is_value()) { // 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];
*** 685,696 ****
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);
--- 894,906 ----
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);
*** 730,741 ****
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(
--- 940,957 ----
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(
*** 745,754 ****
--- 961,972 ----
info.index(),
info.offset(),
state,
info.access_flags().is_final(),
info.access_flags().is_volatile(),
+ info.is_flattened(),
+ info.is_flattenable(),
pool->pool_holder()
);
}
*** 855,866 ****
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");
}
--- 1073,1083 ----
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");
}
*** 998,1007 ****
--- 1215,1225 ----
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:
*** 1262,1271 ****
--- 1480,1495 ----
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 >