< prev index next >

src/share/vm/opto/graphKit.cpp

Print this page

        

@@ -1685,10 +1685,15 @@
 
 //-------------------------array_element_address-------------------------
 Node* GraphKit::array_element_address(Node* ary, Node* idx, BasicType elembt,
                                       const TypeInt* sizetype, Node* ctrl) {
   uint shift  = exact_log2(type2aelembytes(elembt));
+  ciKlass* arytype_klass = _gvn.type(ary)->is_aryptr()->klass();
+  if (arytype_klass->is_value_array_klass()) {
+    ciValueArrayKlass* vak = arytype_klass->as_value_array_klass();
+    shift = vak->log2_element_size();
+  }
   uint header = arrayOopDesc::base_offset_in_bytes(elembt);
 
   // short-circuit a common case (saves lots of confusing waste motion)
   jint idx_con = find_int_con(idx, -1);
   if (idx_con >= 0) {

@@ -1705,10 +1710,11 @@
 
 //-------------------------load_array_element-------------------------
 Node* GraphKit::load_array_element(Node* ctl, Node* ary, Node* idx, const TypeAryPtr* arytype) {
   const Type* elemtype = arytype->elem();
   BasicType elembt = elemtype->array_element_basic_type();
+  assert(elembt != T_VALUETYPE, "value types are not supported by this method");
   Node* adr = array_element_address(ary, idx, elembt, arytype->size());
   Node* ld = make_load(ctl, adr, elemtype, elembt, arytype, MemNode::unordered);
   return ld;
 }
 

@@ -3515,11 +3521,11 @@
 
   return set_output_for_allocation(alloc, oop_type, deoptimize_on_exception);
 }
 
 //-------------------------------new_array-------------------------------------
-// helper for both newarray and anewarray
+// helper for newarray, anewarray and vnewarray
 // The 'length' parameter is (obviously) the length of the array.
 // See comments on new_instance for the meaning of the other arguments.
 Node* GraphKit::new_array(Node* klass_node,     // array klass (maybe variable)
                           Node* length,         // number of array elements
                           int   nargs,          // number of arguments to push back for uncommon trap

@@ -3576,11 +3582,12 @@
     int       hsize  = Klass::layout_helper_header_size(layout_con);
     int       eshift = Klass::layout_helper_log2_element_size(layout_con);
     BasicType etype  = Klass::layout_helper_element_type(layout_con);
     if ((round_mask & ~right_n_bits(eshift)) == 0)
       round_mask = 0;  // strength-reduce it if it goes away completely
-    assert((hsize & right_n_bits(eshift)) == 0, "hsize is pre-rounded");
+    // TODO re-enabled assert
+  //  assert((hsize & right_n_bits(eshift)) == 0, "hsize is pre-rounded");
     assert(header_size_min <= hsize, "generic minimum is smallest");
     header_size_min = hsize;
     header_size = intcon(hsize + round_mask);
   } else {
     Node* hss   = intcon(Klass::_lh_header_size_shift);

@@ -3660,11 +3667,11 @@
   }
 
   // Now generate allocation code
 
   // The entire memory state is needed for slow path of the allocation
-  // since GC and deoptimization can happened.
+  // since GC and deoptimization can happen.
   Node *mem = reset_memory();
   set_all_memory(mem); // Create new memory state
 
   if (initial_slow_test->is_Bool()) {
     // Hide it behind a CMoveI, or else PhaseIdealLoop::split_up will get sick.

@@ -3700,13 +3707,93 @@
       record_for_igvn(ccast);
       replace_in_map(length, ccast);
     }
   }
 
+  const TypeAryPtr* ary_ptr = ary_type->isa_aryptr();
+  ciKlass* elem_klass = ary_ptr != NULL ? ary_ptr->klass()->as_array_klass()->element_klass() : NULL;
+  //if (layout_is_con && Klass::layout_helper_element_type(layout_con) == T_VALUETYPE) {
+  if (elem_klass != NULL && elem_klass->is_valuetype()) {
+    ciValueKlass* vk = elem_klass->as_value_klass();
+    if (vk->flatten_array()) {
+      // TODO
+    } else {
+      // TODO explain this and add asserts
+      initialize_value_type_array(javaoop, length, elem_klass->as_value_klass(), nargs);
+      InitializeNode* init = alloc->initialization();
+      init->set_complete_with_arraycopy();
+    }
+  }
+
   return javaoop;
 }
 
+void GraphKit::initialize_value_type_array(Node* array, Node* length, ciValueKlass* vk, int nargs) {
+  // Check for zero length
+  Node* null_ctl = top();
+  null_check_common(length, T_INT, false, &null_ctl, false);
+  if (stopped()) {
+    set_control(null_ctl); // Always zero
+    return;
+  }
+
+  // Prepare for merging control and IO
+  RegionNode* res_ctl = new RegionNode(3);
+  res_ctl->init_req(1, null_ctl);
+  gvn().set_type(res_ctl, Type::CONTROL);
+  record_for_igvn(res_ctl);
+  Node* res_io = PhiNode::make(res_ctl, i_o(), Type::ABIO);
+  gvn().set_type(res_io, Type::ABIO);
+  record_for_igvn(res_io);
+
+  // TODO comment
+  SafePointNode* loop_map = NULL;
+  {
+    PreserveJVMState pjvms(this);
+    // Create default value type and store it to memory
+    Node* oop = ValueTypeNode::make_default(gvn(), vk);
+    oop = oop->as_ValueType()->store_to_memory(this);
+
+    length = SubI(length, intcon(1));
+    add_predicate(nargs);
+    RegionNode* loop = new RegionNode(3);
+    loop->init_req(1, control());
+    gvn().set_type(loop, Type::CONTROL);
+    record_for_igvn(loop);
+
+    Node* index = new PhiNode(loop, TypeInt::INT);
+    index->init_req(1, intcon(0));
+    gvn().set_type(index, TypeInt::INT);
+    record_for_igvn(index);
+
+    // TODO explain why we need to capture all memory
+    PhiNode* mem = new PhiNode(loop, Type::MEMORY, TypePtr::BOTTOM);
+    mem->init_req(1, reset_memory());
+    gvn().set_type(mem, Type::MEMORY);
+    record_for_igvn(mem);
+    set_control(loop);
+    set_all_memory(mem);
+    // Initialize array element
+    Node* adr = array_element_address(array, index, T_OBJECT);
+    const TypeOopPtr* elemtype = TypeValueTypePtr::make(TypePtr::NotNull, vk); // ary_type->is_aryptr()->elem()->make_oopptr();
+    Node* store = store_oop_to_array(control(), array, adr, TypeAryPtr::OOPS, oop, elemtype, T_OBJECT, MemNode::release);
+
+    IfNode* iff = create_and_map_if(control(), Bool(CmpI(index, length), BoolTest::lt), PROB_FAIR, COUNT_UNKNOWN);
+    loop->init_req(2, IfTrue(iff));
+    mem->init_req(2, merged_memory());
+    index->init_req(2, AddI(index, intcon(1)));
+
+    res_ctl->init_req(2, IfFalse(iff));
+    res_io->set_req(2, i_o());
+    loop_map = stop();
+  }
+  // Set merged control, IO and memory
+  set_control(res_ctl);
+  set_i_o(res_io);
+  merge_memory(loop_map->merged_memory(), res_ctl, 2);
+}
+
 // The following "Ideal_foo" functions are placed here because they recognize
 // the graph shapes created by the functions immediately above.
 
 //---------------------------Ideal_allocation----------------------------------
 // Given an oop pointer or raw pointer, see if it feeds from an AllocateNode.
< prev index next >