< prev index next >

src/share/vm/opto/macro.cpp

Print this page

        

@@ -42,10 +42,11 @@
 #include "opto/phaseX.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
 #include "opto/subnode.hpp"
 #include "opto/type.hpp"
+#include "opto/valuetypenode.hpp"
 #include "runtime/sharedRuntime.hpp"
 
 
 //
 // Replace any references to "oldref" in inputs to "use" with "newref".

@@ -560,10 +561,11 @@
 }
 
 // Search the last value stored into the object's field.
 Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, Node *sfpt_ctl, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, AllocateNode *alloc) {
   assert(adr_t->is_known_instance_field(), "instance required");
+  assert(ft != T_VALUETYPE, "should not be used for value type fields");
   int instance_id = adr_t->instance_id();
   assert((uint)instance_id == alloc->_idx, "wrong allocation");
 
   int alias_idx = C->get_alias_index(adr_t);
   int offset = adr_t->offset();

@@ -571,11 +573,10 @@
   Node *alloc_ctrl = alloc->in(TypeFunc::Control);
   Node *alloc_mem = alloc->in(TypeFunc::Memory);
   Arena *a = Thread::current()->resource_area();
   VectorSet visited(a);
 
-
   bool done = sfpt_mem == alloc_mem;
   Node *mem = sfpt_mem;
   while (!done) {
     if (visited.test_set(mem->_idx)) {
       return NULL;  // found a loop, give up

@@ -584,11 +585,11 @@
     if (mem == start_mem || mem == alloc_mem) {
       done = true;  // hit a sentinel, return appropriate 0 value
     } else if (mem->is_Initialize()) {
       mem = mem->as_Initialize()->find_captured_store(offset, type2aelembytes(ft), &_igvn);
       if (mem == NULL) {
-        done = true; // Something go wrong.
+        done = true; // Something went wrong.
       } else if (mem->is_Store()) {
         const TypePtr* atype = mem->as_Store()->adr_type();
         assert(C->get_alias_index(atype) == Compile::AliasIdxRaw, "store is correct memory slice");
         done = true;
       }

@@ -652,14 +653,36 @@
         ctl = sfpt_ctl;
       }
       return make_arraycopy_load(mem->as_ArrayCopy(), offset, ctl, ft, ftype, alloc);
     }
   }
-  // Something go wrong.
+  // Something went wrong.
   return NULL;
 }
 
+// Search the last value stored into the value type's fields.
+Node* PhaseMacroExpand::value_type_from_mem(Node* mem, Node* ctl, ciValueKlass* vk, const TypeAryPtr* adr_type, int offset, AllocateNode* alloc) {
+  // Subtract the offset of the first field to account for the missing oop header
+  offset -= vk->first_field_offset();
+  // Create a new ValueTypeNode and retrieve the field values from memory
+  ValueTypeNode* vt = ValueTypeNode::make(_igvn, vk)->as_ValueType();
+  for (int i = 0; i < vk->field_count(); ++i) {
+    ciType* field_type = vt->field_type(i);
+    int field_offset = offset + vt->field_offset(i);
+    // Each value type field has its own memory slice
+    adr_type = adr_type->with_field_offset(field_offset);
+    Node* value = NULL;
+    if (field_type->basic_type() == T_VALUETYPE) {
+      value = value_type_from_mem(mem, ctl, field_type->as_value_klass(), adr_type, field_offset, alloc);
+    } else {
+      value = value_from_mem(mem, ctl, field_type->basic_type(), Type::get_const_type(field_type), adr_type, alloc);
+    }
+    vt->set_field_value(i, value);
+  }
+  return vt;
+}
+
 // Check the possibility of scalar replacement.
 bool PhaseMacroExpand::can_eliminate_allocation(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints) {
   //  Scan the uses of the allocation to check for anything that would
   //  prevent us from eliminating it.
   NOT_PRODUCT( const char* fail_eliminate = NULL; )

@@ -710,11 +733,11 @@
                 n->in(ArrayCopyNode::Dest) == use)) {
             DEBUG_ONLY(disq_node = n;)
             if (n->is_Load() || n->is_LoadStore()) {
               NOT_PRODUCT(fail_eliminate = "Field load";)
             } else {
-              NOT_PRODUCT(fail_eliminate = "Not store field referrence";)
+              NOT_PRODUCT(fail_eliminate = "Not store field reference";)
             }
             can_eliminate = false;
           }
         }
       } else if (use->is_ArrayCopy() &&

@@ -748,11 +771,11 @@
           }
           DEBUG_ONLY(disq_node = use;)
         } else {
           if (use->Opcode() == Op_Return) {
             NOT_PRODUCT(fail_eliminate = "Object is return value";)
-          }else {
+          } else {
             NOT_PRODUCT(fail_eliminate = "Object is referenced by node";)
           }
           DEBUG_ONLY(disq_node = use;)
         }
         can_eliminate = false;

@@ -805,11 +828,13 @@
     res_type = _igvn.type(res)->isa_oopptr();
   }
 
   if (res != NULL) {
     klass = res_type->klass();
-    if (res_type->isa_instptr() || res_type->isa_valuetypeptr()) {
+    // Value types are only allocated on demand
+    assert(!klass->is_valuetype(), "value type allocations should not be scalar replaceable");
+    if (res_type->isa_instptr()) {
       // find the fields of the class which will be needed for safepoint debug information
       assert(klass->is_instance_klass(), "must be an instance klass.");
       iklass = klass->as_instance_klass();
       nfields = iklass->nof_nonstatic_fields();
     } else {

@@ -849,10 +874,11 @@
       if (iklass != NULL) {
         field = iklass->nonstatic_field_at(j);
         offset = field->offset();
         elem_type = field->type();
         basic_elem_type = field->layout_type();
+        // Value type fields should not have safepoint uses
         assert(basic_elem_type != T_VALUETYPE, "value type fields are flattened");
       } else {
         offset = array_base + j * (intptr_t)element_size;
       }
 

@@ -877,13 +903,19 @@
         }
       } else {
         field_type = Type::get_const_basic_type(basic_elem_type);
       }
 
-      const TypeOopPtr *field_addr_type = res_type->add_offset(offset)->isa_oopptr();
-
-      Node *field_val = value_from_mem(mem, ctl, basic_elem_type, field_type, field_addr_type, alloc);
+      Node* field_val = NULL;
+      const TypeOopPtr* field_addr_type = res_type->add_offset(offset)->isa_oopptr();
+      if (klass->is_value_array_klass()) {
+        ciValueKlass* vk = elem_type->as_value_klass();
+        assert(vk->flatten_array(), "must be flattened");
+        field_val = value_type_from_mem(mem, ctl, vk, field_addr_type->isa_aryptr(), 0, alloc);
+      } else {
+        field_val = value_from_mem(mem, ctl, basic_elem_type, field_type, field_addr_type, alloc);
+      }
       if (field_val == NULL) {
         // We weren't able to find a value for this field,
         // give up on eliminating this allocation.
 
         // Remove any extra entries we added to the safepoint.
< prev index next >