< prev index next >

src/hotspot/share/interpreter/interpreterRuntime.cpp

Print this page

        

@@ -45,10 +45,14 @@
 #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,10 +71,11 @@
 #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,23 +256,223 @@
   //       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);
-  objArrayOop obj = oopFactory::new_objArray(klass, size, 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,10 +480,14 @@
   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,12 +894,13 @@
   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::_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,12 +940,18 @@
   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()) {
+    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,10 +961,12 @@
     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,12 +1073,11 @@
     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(Universe::heap()->is_in_reserved_or_null(receiver()), "sanity check");
     assert(receiver.is_null() ||
            !Universe::heap()->is_in_reserved(receiver->klass()),
            "sanity check");
   }
 

@@ -998,10 +1215,11 @@
   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,10 +1480,16 @@
     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 >