< prev index next >

src/share/vm/opto/valuetypenode.cpp

Print this page

        

*** 35,58 **** return new ValueTypeNode(type, gvn.zerocon(T_VALUETYPE)); } Node* ValueTypeNode::make(PhaseGVN& gvn, Node* mem, Node* oop) { // Create and initialize a ValueTypeNode by loading all field ! // values from memory and also save the oop to the heap-allocated version. const TypeValueTypePtr* vtptr = gvn.type(oop)->is_valuetypeptr(); ValueTypeNode* vt = new ValueTypeNode(vtptr->value_type(), oop); ! for (uint index = 0; index < vt->field_count(); ++index) { ! int offset = vt->get_field_offset(index); ! const TypePtr* adr_type = vtptr->add_offset(offset); ! const Type* field_type = Type::get_const_basic_type(vt->get_field_type(index)); ! Node* adr = gvn.transform(new AddPNode(oop, oop, gvn.longcon(offset))); ! Node* ld = LoadNode::make(gvn, NULL, mem, adr, adr_type, field_type, field_type->basic_type(), MemNode::unordered); ! vt->set_field_value(index, gvn.transform(ld)); ! } return gvn.transform(vt); } Node* ValueTypeNode::store_to_memory(GraphKit* kit) { Node* in_oop = get_oop(); Node* null_ctl = kit->top(); // Check if value type is already allocated Node* not_null_oop = kit->null_check_oop(in_oop, &null_ctl); --- 35,106 ---- return new ValueTypeNode(type, gvn.zerocon(T_VALUETYPE)); } 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 TypeValueTypePtr* vtptr = gvn.type(oop)->is_valuetypeptr(); ValueTypeNode* vt = new ValueTypeNode(vtptr->value_type(), oop); ! vt->load_values(gvn, mem, vt->get_value_klass(), oop); ! return gvn.transform(vt); ! } ! ! Node* ValueTypeNode::make(PhaseGVN& gvn, ciValueKlass* klass, Node* mem, ciInstanceKlass* holder, Node* obj, int field_offset) { ! // Create and initialize a ValueTypeNode by loading all field ! // values from a flattened value type field at 'field_offset' in 'obj'. ! ValueTypeNode* vt = make(gvn, klass)->as_ValueType(); ! // 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. ! int base_offset = field_offset - klass->get_first_field_offset(); ! vt->load_values(gvn, mem, holder, obj, base_offset); return gvn.transform(vt); } + void ValueTypeNode::load_values(PhaseGVN& gvn, Node* mem, ciInstanceKlass* holder, Node* base, int base_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 = base_offset + get_field_offset(i); + Node* adr = gvn.transform(new AddPNode(base, base, gvn.longcon(offset))); + ciField* field = holder->get_field_by_offset(offset, false); + const TypePtr* adr_type = gvn.C->alias_type(field)->adr_type(); + Node* value = NULL; + ciType* field_type = get_field_type(i); + if (field_type->is_valuetype()) { + // Recursively load the flattened value type field + value = ValueTypeNode::make(gvn, field_type->as_value_klass(), mem, holder, base, offset); + } else { + value = LoadNode::make(gvn, NULL, mem, adr, adr_type, Type::get_const_type(field_type), field_type->basic_type(), MemNode::unordered); + } + set_field_value(i, gvn.transform(value)); + } + } + + void ValueTypeNode::store_to_field(GraphKit* kit, ciInstanceKlass* holder, Node* obj, int field_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. + int base_offset = field_offset - get_value_klass()->get_first_field_offset(); + store_values(kit, holder, obj, base_offset); + } + + void ValueTypeNode::store_values(GraphKit* kit, ciInstanceKlass* holder, Node* base, int base_offset) const { + // Write field values to memory + for (uint i = 0; i < field_count(); ++i) { + int offset = base_offset + get_field_offset(i); + Node* adr = kit->basic_plus_adr(base, base, offset); + ciField* field = holder->get_field_by_offset(offset, false); + const TypePtr* adr_type = kit->C->alias_type(field)->adr_type(); + Node* value = get_field_value(i); + if (value->is_ValueType()) { + // Recursively store the flattened value type field + value->isa_ValueType()->store_to_field(kit, holder, base, offset); + } else { + kit->store_to_memory(kit->control(), adr, value, get_field_type(i)->basic_type(), adr_type, MemNode::unordered); + } + } + } + Node* ValueTypeNode::store_to_memory(GraphKit* kit) { Node* in_oop = get_oop(); Node* null_ctl = kit->top(); // Check if value type is already allocated Node* not_null_oop = kit->null_check_oop(in_oop, &null_ctl);
*** 84,99 **** kit->set_control(null_ctl); kit->kill_dead_locals(); Node* klass_node = kit->makecon(TypeKlassPtr::make(get_value_klass())); Node* alloc_oop = kit->new_instance(klass_node); // Write field values to memory ! for (uint index = 0; index < field_count(); ++index) { ! int offset = get_field_offset(index); ! const TypePtr* adr_type = vtptr_type->add_offset(offset); ! Node* adr = kit->basic_plus_adr(alloc_oop, alloc_oop, offset); ! kit->store_to_memory(kit->control(), adr, get_field_value(index), get_field_type(index), adr_type, MemNode::unordered); ! } region->init_req(2, kit->control()); oop ->init_req(2, alloc_oop); io ->init_req(2, kit->i_o()); mem ->init_req(2, kit->merged_memory()); --- 132,142 ---- kit->set_control(null_ctl); kit->kill_dead_locals(); Node* klass_node = kit->makecon(TypeKlassPtr::make(get_value_klass())); Node* alloc_oop = kit->new_instance(klass_node); // Write field values to memory ! store_values(kit, get_value_klass(), alloc_oop); region->init_req(2, kit->control()); oop ->init_req(2, alloc_oop); io ->init_req(2, kit->i_o()); mem ->init_req(2, kit->merged_memory());
*** 104,128 **** kit->record_for_igvn(region); kit->record_for_igvn(oop); kit->record_for_igvn(io); kit->record_for_igvn(mem); Node* res_oop = kit->gvn().transform(oop); ValueTypeNode* vt = clone()->as_ValueType(); vt->set_oop(res_oop); kit->replace_in_map(this, kit->gvn().transform(vt)); return res_oop; } Node* ValueTypeNode::get_field_value(uint index) const { assert(index < field_count(), "index out of bounds"); return in(Values + index); } ! Node* ValueTypeNode::get_field_value_by_offset(int field_offset) const { ! int index = get_value_klass()->get_field_index_by_offset(field_offset); ! return get_field_value(index); } void ValueTypeNode::set_field_value(uint index, Node* value) { assert(index < field_count(), "index out of bounds"); set_req(Values + index, value); --- 147,249 ---- kit->record_for_igvn(region); kit->record_for_igvn(oop); kit->record_for_igvn(io); kit->record_for_igvn(mem); + // Use cloned ValueTypeNode to propagate oop from now on Node* res_oop = kit->gvn().transform(oop); ValueTypeNode* vt = clone()->as_ValueType(); vt->set_oop(res_oop); kit->replace_in_map(this, kit->gvn().transform(vt)); return res_oop; } + // Clones the values type to handle control flow merges involving multiple value types. + // The input edges are replaced by PhiNodes to represent the merged values. + ValueTypeNode* ValueTypeNode::clone_with_phis(PhaseGVN& gvn, Node* region) { + ValueTypeNode* vt = clone()->as_ValueType(); + + // Create a PhiNode for merging the oop values + const TypeValueTypePtr* vtptr = TypeValueTypePtr::make(vt->bottom_type()->isa_valuetype()); + PhiNode* oop = PhiNode::make(region, vt->get_oop(), vtptr); + gvn.set_type(oop, vtptr); + vt->set_oop(oop); + + // Create a PhiNode each for merging the field values + for (uint i = 0; i < vt->field_count(); ++i) { + ciType* type = vt->get_field_type(i); + Node* value = vt->get_field_value(i); + if (type->is_valuetype()) { + // Handle flattened value type fields recursively + value = value->as_ValueType()->clone_with_phis(gvn, region); + } else { + const Type* phi_type = Type::get_const_type(type); + value = PhiNode::make(region, value, phi_type); + gvn.set_type(value, phi_type); + } + vt->set_field_value(i, value); + } + gvn.set_type(vt, vt->bottom_type()); + return vt; + } + + // Merges 'this' with 'other' by updating the input PhiNodes added by 'clone_with_phis' + Node* ValueTypeNode::merge_with(GraphKit* kit, const ValueTypeNode* other, int pnum) { + // Merge oop inputs + PhiNode* phi = get_oop()->as_Phi(); + phi->set_req(pnum, other->get_oop()); + if (pnum == PhiNode::Input) { + // Last merge + set_oop(kit->gvn().transform_no_reclaim(phi)); + kit->record_for_igvn(phi); + } + // Merge field values + for (uint i = 0; i < field_count(); ++i) { + Node* val1 = get_field_value(i); + Node* val2 = other->get_field_value(i); + if (val1->isa_ValueType()) { + val1->as_ValueType()->merge_with(kit, val2->as_ValueType(), pnum); + } else { + assert(!val2->is_ValueType(), "inconsistent merge values"); + val1->set_req(pnum, val2); + } + if (pnum == PhiNode::Input) { + // Last merge + set_field_value(i, kit->gvn().transform_no_reclaim(val1)); + kit->record_for_igvn(val1); + } + } + if (pnum == PhiNode::Input) { + // Last merge for this value type. + kit->record_for_igvn(this); + return kit->gvn().transform_no_reclaim(this); + } + return this; + } + Node* ValueTypeNode::get_field_value(uint index) const { assert(index < field_count(), "index out of bounds"); return in(Values + index); } ! // Get the value of the field at the given offset. ! // If 'recursive' is true, flattened value type fields will be resolved recursively. ! Node* ValueTypeNode::get_field_value_by_offset(int offset, bool recursive) const { ! // If the field at 'offset' belongs to a flattened value type field, 'index' refers to the ! // corresponding ValueTypeNode input and 'sub_offset' is the offset in flattened value type. ! int index = get_value_klass()->get_field_index_by_offset(offset); ! int sub_offset = offset - get_field_offset(index); ! Node* value = get_field_value(index); ! if (recursive && value->is_ValueType()) { ! // Flattened value type field ! ValueTypeNode* vt = value->as_ValueType(); ! sub_offset += vt->get_value_klass()->get_first_field_offset(); // Add header size ! return vt->get_field_value_by_offset(sub_offset); ! } ! assert(!(recursive && value->is_ValueType()), "should not be a value type"); ! assert(sub_offset == 0, "offset mismatch"); ! return value; } void ValueTypeNode::set_field_value(uint index, Node* value) { assert(index < field_count(), "index out of bounds"); set_req(Values + index, value);
*** 131,183 **** int ValueTypeNode::get_field_offset(uint index) const { assert(index < field_count(), "index out of bounds"); return get_value_klass()->get_field_offset_by_index(index); } ! BasicType ValueTypeNode::get_field_type(uint index) const { assert(index < field_count(), "index out of bounds"); return get_value_klass()->get_field_type_by_index(index); } void ValueTypeNode::make_scalar_in_safepoints(Compile* C) { const TypeValueTypePtr* res_type = TypeValueTypePtr::make(bottom_type()->isa_valuetype(), TypePtr::NotNull); ! uint nfields = field_count(); for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) { Node* u = fast_out(i); if (u->is_SafePoint() && (!u->is_Call() || u->as_Call()->has_debug_use(this))) { Node* in_oop = get_oop(); const Type* oop_type = in_oop->bottom_type(); SafePointNode* sfpt = u->as_SafePoint(); JVMState* jvms = sfpt->jvms(); int start = jvms->debug_start(); int end = jvms->debug_end(); if (oop_type->meet(TypePtr::NULL_PTR) != oop_type) { int nb = sfpt->replace_edges_in_range(this, in_oop, start, end); --i; imax -= nb; } else { assert(jvms != NULL, "missing JVMS"); uint first_ind = (sfpt->req() - jvms->scloff()); SafePointScalarObjectNode* sobj = new SafePointScalarObjectNode(res_type, #ifdef ASSERT NULL, #endif first_ind, nfields); sobj->init_req(0, C->root()); ! // fields must be added to the safepoint in order of increasing offset ! int min = 0; ! for (uint j = 0; j < nfields; j++) { ! int off = INT_MAX; ! uint next = 0; ! for (uint k = 0; k < nfields; k++) { ! int offset = get_field_offset(k); ! if (offset > min && offset < off) { ! off = offset; ! next = k; ! } ! } ! min = get_field_offset(next); ! sfpt->add_req(in(Values + next)); } jvms->set_endoff(sfpt->req()); int nb = sfpt->replace_edges_in_range(this, sobj, start, end); --i; imax -= nb; } --- 252,299 ---- int ValueTypeNode::get_field_offset(uint index) const { assert(index < field_count(), "index out of bounds"); return get_value_klass()->get_field_offset_by_index(index); } ! ciType* ValueTypeNode::get_field_type(uint index) const { assert(index < field_count(), "index out of bounds"); return get_value_klass()->get_field_type_by_index(index); } void ValueTypeNode::make_scalar_in_safepoints(Compile* C) { const TypeValueTypePtr* res_type = TypeValueTypePtr::make(bottom_type()->isa_valuetype(), TypePtr::NotNull); ! ciValueKlass* vk = get_value_klass(); ! uint nfields = vk->get_field_count(); for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) { Node* u = fast_out(i); if (u->is_SafePoint() && (!u->is_Call() || u->as_Call()->has_debug_use(this))) { Node* in_oop = get_oop(); const Type* oop_type = in_oop->bottom_type(); SafePointNode* sfpt = u->as_SafePoint(); JVMState* jvms = sfpt->jvms(); int start = jvms->debug_start(); int end = jvms->debug_end(); if (oop_type->meet(TypePtr::NULL_PTR) != oop_type) { + // Replace safepoint edge by oop int nb = sfpt->replace_edges_in_range(this, in_oop, start, end); --i; imax -= nb; } else { + // Replace safepoint edge by SafePointScalarObjectNode and add field values assert(jvms != NULL, "missing JVMS"); uint first_ind = (sfpt->req() - jvms->scloff()); SafePointScalarObjectNode* sobj = new SafePointScalarObjectNode(res_type, #ifdef ASSERT NULL, #endif first_ind, nfields); sobj->init_req(0, C->root()); ! // Iterate over the value type fields in order of increasing ! // offset and add the field values to the safepoint. ! for (uint j = 0; j < nfields; ++j) { ! int offset = vk->nonstatic_field_at(j)->offset(); ! Node* value = get_field_value_by_offset(offset, true /* include flattened value type fields */); ! sfpt->add_req(value); } jvms->set_endoff(sfpt->req()); int nb = sfpt->replace_edges_in_range(this, sobj, start, end); --i; imax -= nb; }
*** 192,202 **** #ifndef PRODUCT void ValueTypeNode::dump_spec(outputStream* st) const { TypeNode::dump_spec(st); - if (!get_oop()->is_top()) { - st->print(" #oop"); - } } #endif --- 308,315 ----
< prev index next >