< prev index next >

src/share/vm/opto/valuetypenode.cpp

Print this page

        

@@ -192,57 +192,54 @@
       --i; imax -= nb;
     }
   }
 }
 
-ValueTypeNode* ValueTypeNode::make(PhaseGVN& gvn, ciValueKlass* klass) {
-  // Create a new ValueTypeNode with uninitialized values and NULL oop
-  const TypeValueType* type = TypeValueType::make(klass);
-  return new ValueTypeNode(type, gvn.zerocon(T_VALUETYPE));
-}
-
-Node* ValueTypeNode::make_default(PhaseGVN& gvn, ciValueKlass* vk) {
-  // TODO re-use constant oop of pre-allocated default value type here?
-  // Create a new ValueTypeNode with default values
-  ValueTypeNode* vt = ValueTypeNode::make(gvn, vk);
-  for (uint i = 0; i < vt->field_count(); ++i) {
+void ValueTypeBaseNode::make(PhaseGVN* gvn, Node* n, ValueTypeBaseNode* vt, ciValueKlass* base_vk, int base_offset, int base_input, bool in) {
+  assert(base_offset >= 0, "offset in value type always positive");
+  for (uint i = 0; i < vt->field_count(); i++) {
     ciType* field_type = vt->field_type(i);
-    Node* value = NULL;
+    int offset = base_offset + vt->field_offset(i);
     if (field_type->is_valuetype()) {
-      value = ValueTypeNode::make_default(gvn, field_type->as_value_klass());
+      ciValueKlass* embedded_vk = field_type->as_value_klass();
+      ValueTypeNode* embedded_vt = ValueTypeNode::make(*gvn, embedded_vk);
+      ValueTypeBaseNode::make(gvn, n, embedded_vt, base_vk, offset - vt->value_klass()->first_field_offset(), base_input, in);
+      vt->set_field_value(i, gvn->transform(embedded_vt));
     } else {
-      value = gvn.zerocon(field_type->basic_type());
+      int j = 0; int extra = 0;
+      for (; j < base_vk->nof_nonstatic_fields(); j++) {
+        ciField* f = base_vk->nonstatic_field_at(j);
+        if (offset == f->offset()) {
+          assert(f->type() == field_type, "inconsistent field type");
+          break;
+        }
+        BasicType bt = f->type()->basic_type();
+        if (bt == T_LONG || bt == T_DOUBLE) {
+          extra++;
+        }
+      }
+      assert(j != base_vk->nof_nonstatic_fields(), "must find");
+      Node* parm = NULL;
+      if (n->is_Start()) {
+        assert(in, "return from start?");
+        parm = gvn->transform(new ParmNode(n->as_Start(), base_input + j + extra));
+      } else {
+        if (in) {
+          assert(n->is_Call(), "nothing else here");
+          parm = n->in(base_input + j + extra);
+        } else {
+          parm = gvn->transform(new ProjNode(n->as_Call(), base_input + j + extra));
+        }
+      }
+      vt->set_field_value(i, parm);
+      // Record all these guys for later GVN.
+      gvn->record_for_igvn(parm);
     }
-    vt->set_field_value(i, value);
   }
-  return gvn.transform(vt);
-}
-
-Node* ValueTypeNode::make(PhaseGVN& gvn, Node* mem, Node* oop) {
-  // Create and initialize a ValueTypeNode by loading all field
-  // values from a heap-allocated version and also save the oop.
-  const TypeValueType* type = gvn.type(oop)->is_valuetypeptr()->value_type();
-  ValueTypeNode* vt = new ValueTypeNode(type, oop);
-  vt->load(gvn, mem, oop, oop, type->value_klass());
-  assert(vt->is_allocated(&gvn), "value type should be allocated");
-  assert(oop->is_Con() || oop->is_CheckCastPP() || oop->Opcode() == Op_ValueTypePtr || vt->is_loaded(&gvn, type) == oop, "value type should be loaded");
-  return gvn.transform(vt);
-}
-
-Node* ValueTypeNode::make(PhaseGVN& gvn, ciValueKlass* vk, Node* mem, Node* obj, Node* ptr, ciInstanceKlass* holder, int holder_offset) {
-  // Create and initialize a ValueTypeNode by loading all field values from
-  // a flattened value type field at 'holder_offset' or from a value type array.
-  ValueTypeNode* vt = make(gvn, vk);
-  // The value type is flattened into the object without an oop header. Subtract the
-  // offset of the first field to account for the missing header when loading the values.
-  holder_offset -= vk->first_field_offset();
-  vt->load(gvn, mem, obj, ptr, holder, holder_offset);
-  assert(vt->is_loaded(&gvn, vt->type()->isa_valuetype()) != obj, "holder oop should not be used as flattened value type oop");
-  return gvn.transform(vt)->as_ValueType();
 }
 
-void ValueTypeNode::load(PhaseGVN& gvn, Node* mem, Node* base, Node* ptr, ciInstanceKlass* holder, int holder_offset) {
+void ValueTypeBaseNode::load(PhaseGVN& gvn, Node* mem, Node* base, Node* ptr, ciInstanceKlass* holder, int holder_offset) {
   // Initialize the value type by loading its field values from
   // memory and adding the values as input edges to the node.
   for (uint i = 0; i < field_count(); ++i) {
     int offset = holder_offset + field_offset(i);
     ciType* ftype = field_type(i);

@@ -283,10 +280,129 @@
     }
     set_field_value(i, gvn.transform(value));
   }
 }
 
+void ValueTypeBaseNode::store_flattened(PhaseGVN* gvn, Node* ctl, MergeMemNode* mem, Node* base, ciValueKlass* holder, int holder_offset) const {
+  // The value type is embedded into the object without an oop header. Subtract the
+  // offset of the first field to account for the missing header when storing the values.
+  holder_offset -= value_klass()->first_field_offset();
+  store(gvn, ctl, mem, base, holder, holder_offset);
+}
+
+void ValueTypeBaseNode::store(PhaseGVN* gvn, Node* ctl, MergeMemNode* mem, Node* base, ciValueKlass* holder, int holder_offset) const {
+  if (holder == NULL) {
+    holder = value_klass();
+  }
+  // Write field values to memory
+  for (uint i = 0; i < field_count(); ++i) {
+    int offset = holder_offset + field_offset(i);
+    Node* value = field_value(i);
+    if (value->is_ValueType()) {
+      // Recursively store the flattened value type field
+      value->isa_ValueTypeBase()->store_flattened(gvn, ctl, mem, base, holder, offset);
+    } else {
+      const Type* base_type = gvn->type(base);
+      const TypePtr* adr_type = NULL;
+      if (base_type->isa_aryptr()) {
+        // In the case of a flattened value type array, each field has its own slice
+        adr_type = base_type->is_aryptr()->with_field_offset(offset)->add_offset(Type::OffsetBot);
+      } else {
+        ciField* field = holder->get_field_by_offset(offset, false);
+        adr_type = gvn->C->alias_type(field)->adr_type();
+      }
+      Node* adr = gvn->transform(new AddPNode(base, base, gvn->MakeConX(offset)));
+      BasicType bt = type2field[field_type(i)->basic_type()];
+      uint alias_idx = gvn->C->get_alias_index(adr_type);
+      Node* st = StoreNode::make(*gvn, ctl, mem->memory_at(alias_idx), adr, adr_type, value, bt, MemNode::unordered);
+      mem->set_memory_at(alias_idx, gvn->transform(st));
+    }
+  }
+}
+
+// When a call returns multiple values, it has several result
+// projections, one per field. Replacing the result of the call by a
+// value type node (after late inlining) requires that for each result
+// projection, we find the corresponding value type field.
+void ValueTypeBaseNode::replace_call_results(Node* call, Compile* C) {
+  ciValueKlass* vk = value_klass();
+  for (DUIterator_Fast imax, i = call->fast_outs(imax); i < imax; i++) {
+    ProjNode *pn = call->fast_out(i)->as_Proj();
+    uint con = pn->_con;
+    if (con >= TypeFunc::Parms+1) {
+      uint field_nb = con - (TypeFunc::Parms+1);
+      int extra = 0;
+      for (uint j = 0; j < field_nb - extra; j++) {
+        ciField* f = vk->nonstatic_field_at(j);
+        BasicType bt = f->type()->basic_type();
+        if (bt == T_LONG || bt == T_DOUBLE) {
+          extra++;
+        }
+      }
+      ciField* f = vk->nonstatic_field_at(field_nb - extra);
+      Node* field = field_value_by_offset(f->offset(), true);
+
+      C->gvn_replace_by(pn, field);
+      C->initial_gvn()->hash_delete(pn);
+      pn->set_req(0, C->top());
+      --i; --imax;
+    }
+  }
+}
+
+ValueTypeNode* ValueTypeNode::make(PhaseGVN& gvn, ciValueKlass* klass) {
+  // Create a new ValueTypeNode with uninitialized values and NULL oop
+  const TypeValueType* type = TypeValueType::make(klass);
+  return new ValueTypeNode(type, gvn.zerocon(T_VALUETYPE));
+}
+
+Node* ValueTypeNode::make_default(PhaseGVN& gvn, ciValueKlass* vk) {
+  // TODO re-use constant oop of pre-allocated default value type here?
+  // Create a new ValueTypeNode with default values
+  ValueTypeNode* vt = ValueTypeNode::make(gvn, vk);
+  for (uint i = 0; i < vt->field_count(); ++i) {
+    ciType* field_type = vt->field_type(i);
+    Node* value = NULL;
+    if (field_type->is_valuetype()) {
+      value = ValueTypeNode::make_default(gvn, field_type->as_value_klass());
+    } else {
+      value = gvn.zerocon(field_type->basic_type());
+    }
+    vt->set_field_value(i, value);
+  }
+  return gvn.transform(vt);
+}
+
+Node* ValueTypeNode::make(PhaseGVN& gvn, Node* mem, Node* oop) {
+  // Create and initialize a ValueTypeNode by loading all field
+  // values from a heap-allocated version and also save the oop.
+  const TypeValueType* type = gvn.type(oop)->is_valuetypeptr()->value_type();
+  ValueTypeNode* vt = new ValueTypeNode(type, oop);
+  vt->load(gvn, mem, oop, oop, type->value_klass());
+  assert(vt->is_allocated(&gvn), "value type should be allocated");
+  assert(oop->is_Con() || oop->is_CheckCastPP() || oop->Opcode() == Op_ValueTypePtr || vt->is_loaded(&gvn, type) == oop, "value type should be loaded");
+  return gvn.transform(vt);
+}
+
+Node* ValueTypeNode::make(PhaseGVN& gvn, ciValueKlass* vk, Node* mem, Node* obj, Node* ptr, ciInstanceKlass* holder, int holder_offset) {
+  // Create and initialize a ValueTypeNode by loading all field values from
+  // a flattened value type field at 'holder_offset' or from a value type array.
+  ValueTypeNode* vt = make(gvn, vk);
+  // The value type is flattened into the object without an oop header. Subtract the
+  // offset of the first field to account for the missing header when loading the values.
+  holder_offset -= vk->first_field_offset();
+  vt->load(gvn, mem, obj, ptr, holder, holder_offset);
+  assert(vt->is_loaded(&gvn, vt->type()->isa_valuetype()) != obj, "holder oop should not be used as flattened value type oop");
+  return gvn.transform(vt)->as_ValueType();
+}
+
+Node* ValueTypeNode::make(PhaseGVN& gvn, Node* n, ciValueKlass* vk, int base_input, bool in) {
+  ValueTypeNode* vt = ValueTypeNode::make(gvn, vk);
+  ValueTypeBaseNode::make(&gvn, n, vt, vk, 0, base_input, in);
+  return gvn.transform(vt);
+}
+
 Node* ValueTypeNode::is_loaded(PhaseGVN* phase, const TypeValueType* t, Node* base, int holder_offset) {
   if (field_count() == 0) {
     assert(t->value_klass() == phase->C->env()->___Value_klass(), "unexpected value type klass");
     assert(is_allocated(phase), "must be allocated");
     return get_oop();

@@ -565,43 +681,31 @@
     phase->lazy_replace(projs.catchall_catchproj, phase->C->top());
     phase->lazy_replace(projs.resproj, phase->C->top());
   }
 }
 
-// When a call returns multiple values, it has several result
-// projections, one per field. Replacing the result of the call by a
-// value type node (after late inlining) requires that for each result
-// projection, we find the corresponding value type field.
-void ValueTypeNode::replace_call_results(Node* call, Compile* C) {
-  ciValueKlass* vk = value_klass();
-  for (DUIterator_Fast imax, i = call->fast_outs(imax); i < imax; i++) {
-    ProjNode *pn = call->fast_out(i)->as_Proj();
-    uint con = pn->_con;
-    if (con >= TypeFunc::Parms+1) {
-      uint field_nb = con - (TypeFunc::Parms+1);
-      int extra = 0;
-      for (uint j = 0; j < field_nb - extra; j++) {
-        ciField* f = vk->nonstatic_field_at(j);
-        BasicType bt = f->type()->basic_type();
-        if (bt == T_LONG || bt == T_DOUBLE) {
-          extra++;
-        }
-      }
-      ciField* f = vk->nonstatic_field_at(field_nb - extra);
-      Node* field = field_value_by_offset(f->offset(), true);
-
-      C->gvn_replace_by(pn, field);
-      C->initial_gvn()->hash_delete(pn);
-      pn->set_req(0, C->top());
-      --i; --imax;
-    }
-  }
-}
-
 
 #ifndef PRODUCT
 
 void ValueTypeNode::dump_spec(outputStream* st) const {
   TypeNode::dump_spec(st);
 }
 
 #endif
+
+ValueTypePtrNode* ValueTypePtrNode::make(PhaseGVN* gvn, CheckCastPPNode* cast) {
+  ciValueKlass* vk = cast->type()->is_valuetypeptr()->value_type()->value_klass();
+  ValueTypePtrNode* vt = new ValueTypePtrNode(vk, gvn->C);
+  assert(cast->in(1)->is_Proj(), "bad graph shape");
+  ValueTypeBaseNode::make(gvn, cast->in(1)->in(0), vt, vk, 0, TypeFunc::Parms+1, false);
+  return vt;
+}
+
+ValueTypePtrNode* ValueTypePtrNode::make(PhaseGVN& gvn, Node* mem, Node* oop) {
+  // Create and initialize a ValueTypePtrNode by loading all field
+  // values from a heap-allocated version and also save the oop.
+  ciValueKlass* vk = gvn.type(oop)->is_valuetypeptr()->value_type()->value_klass();
+  ValueTypePtrNode* vtptr = new ValueTypePtrNode(vk, gvn.C);
+  vtptr->set_oop(oop);
+  vtptr->load(gvn, mem, oop, oop, vk);
+  return vtptr;
+}
< prev index next >