< 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(&reg_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 >