< 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 >