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