src/share/vm/opto/memnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
hotspot Cdiff src/share/vm/opto/memnode.cpp
src/share/vm/opto/memnode.cpp
Print this page
rev 8052 : castpp gcm
rev 8833 : 8130847: Cloned object's fields observed as null after C2 escape analysis
Summary: Eliminated instance/array written to by an array copy variant must be correctly initialized when reallocated at a deopt
Reviewed-by:
*** 106,146 ****
extern void print_alias_types();
#endif
- static bool membar_for_arraycopy_helper(const TypeOopPtr *t_oop, Node* n, PhaseTransform *phase) {
- if (n->is_Proj()) {
- n = n->in(0);
- if (n->is_Call() && n->as_Call()->may_modify(t_oop, phase)) {
- return true;
- }
- }
- return false;
- }
-
- static bool membar_for_arraycopy(const TypeOopPtr *t_oop, MemBarNode* mb, PhaseTransform *phase) {
- Node* mem = mb->in(TypeFunc::Memory);
-
- if (mem->is_MergeMem()) {
- Node* n = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw);
- if (membar_for_arraycopy_helper(t_oop, n, phase)) {
- return true;
- } else if (n->is_Phi()) {
- for (uint i = 1; i < n->req(); i++) {
- if (n->in(i) != NULL) {
- if (membar_for_arraycopy_helper(t_oop, n->in(i), phase)) {
- return true;
- }
- }
- }
- }
- }
-
- return false;
- }
-
Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypeOopPtr *t_oop, Node *load, PhaseGVN *phase) {
assert((t_oop != NULL), "sanity");
bool is_instance = t_oop->is_known_instance_field();
bool is_boxed_value_load = t_oop->is_ptr_to_boxed_value() &&
(load != NULL) && load->is_Load() &&
--- 106,115 ----
*** 181,191 ****
if (tklass->klass_is_exact() && !tklass->klass()->equals(t_oop->klass())) {
result = proj_in->in(TypeFunc::Memory); // not related allocation
}
}
} else if (proj_in->is_MemBar()) {
! if (membar_for_arraycopy(t_oop, proj_in->as_MemBar(), phase)) {
break;
}
result = proj_in->in(TypeFunc::Memory);
} else {
assert(false, "unexpected projection");
--- 150,160 ----
if (tklass->klass_is_exact() && !tklass->klass()->equals(t_oop->klass())) {
result = proj_in->in(TypeFunc::Memory); // not related allocation
}
}
} else if (proj_in->is_MemBar()) {
! if (ArrayCopyNode::membar_for_arraycopy(t_oop, proj_in->as_MemBar(), phase)) {
break;
}
result = proj_in->in(TypeFunc::Memory);
} else {
assert(false, "unexpected projection");
*** 543,582 ****
Node* ld_offs = ld_addp->in(AddPNode::Offset);
Node* dest = ac->in(ArrayCopyNode::Dest);
if (dest == ld_base) {
- Node* src_pos = ac->in(ArrayCopyNode::SrcPos);
- Node* dest_pos = ac->in(ArrayCopyNode::DestPos);
- Node* len = ac->in(ArrayCopyNode::Length);
-
- const TypeInt *dest_pos_t = phase->type(dest_pos)->isa_int();
const TypeX *ld_offs_t = phase->type(ld_offs)->isa_intptr_t();
! const TypeInt *len_t = phase->type(len)->isa_int();
! const TypeAryPtr* ary_t = phase->type(dest)->isa_aryptr();
!
! if (dest_pos_t != NULL && ld_offs_t != NULL && len_t != NULL && ary_t != NULL) {
! BasicType ary_elem = ary_t->klass()->as_array_klass()->element_type()->basic_type();
! uint header = arrayOopDesc::base_offset_in_bytes(ary_elem);
! uint elemsize = type2aelembytes(ary_elem);
!
! intptr_t dest_pos_plus_len_lo = (((intptr_t)dest_pos_t->_lo) + len_t->_lo) * elemsize + header;
! intptr_t dest_pos_plus_len_hi = (((intptr_t)dest_pos_t->_hi) + len_t->_hi) * elemsize + header;
! intptr_t dest_pos_lo = ((intptr_t)dest_pos_t->_lo) * elemsize + header;
! intptr_t dest_pos_hi = ((intptr_t)dest_pos_t->_hi) * elemsize + header;
!
! if (can_see_stored_value) {
! if (ld_offs_t->_lo >= dest_pos_hi && ld_offs_t->_hi < dest_pos_plus_len_lo) {
return ac;
}
! } else {
! if (ld_offs_t->_hi < dest_pos_lo || ld_offs_t->_lo >= dest_pos_plus_len_hi) {
mem = ac->in(TypeFunc::Memory);
}
- return ac;
- }
- }
}
}
}
}
return NULL;
--- 512,528 ----
Node* ld_offs = ld_addp->in(AddPNode::Offset);
Node* dest = ac->in(ArrayCopyNode::Dest);
if (dest == ld_base) {
const TypeX *ld_offs_t = phase->type(ld_offs)->isa_intptr_t();
! if (ac->modifies(ld_offs_t->_lo, ld_offs_t->_hi, phase, can_see_stored_value)) {
return ac;
}
! if (!can_see_stored_value) {
mem = ac->in(TypeFunc::Memory);
}
}
}
}
}
return NULL;
*** 701,711 ****
if (!call->may_modify(addr_t, phase)) {
mem = call->in(TypeFunc::Memory);
continue; // (a) advance through independent call memory
}
} else if (mem->is_Proj() && mem->in(0)->is_MemBar()) {
! if (membar_for_arraycopy(addr_t, mem->in(0)->as_MemBar(), phase)) {
break;
}
mem = mem->in(0)->in(TypeFunc::Memory);
continue; // (a) advance through independent MemBar memory
} else if (mem->is_ClearArray()) {
--- 647,657 ----
if (!call->may_modify(addr_t, phase)) {
mem = call->in(TypeFunc::Memory);
continue; // (a) advance through independent call memory
}
} else if (mem->is_Proj() && mem->in(0)->is_MemBar()) {
! if (ArrayCopyNode::membar_for_arraycopy(addr_t, mem->in(0)->as_MemBar(), phase)) {
break;
}
mem = mem->in(0)->in(TypeFunc::Memory);
continue; // (a) advance through independent MemBar memory
} else if (mem->is_ClearArray()) {
*** 881,902 ****
}
// Is the value loaded previously stored by an arraycopy? If so return
// a load node that reads from the source array so we may be able to
// optimize out the ArrayCopy node later.
! Node* MemNode::can_see_arraycopy_value(Node* st, PhaseTransform* phase) const {
Node* ld_adr = in(MemNode::Address);
intptr_t ld_off = 0;
AllocateNode* ld_alloc = AllocateNode::Ideal_allocation(ld_adr, phase, ld_off);
Node* ac = find_previous_arraycopy(phase, ld_alloc, st, true);
if (ac != NULL) {
assert(ac->is_ArrayCopy(), "what kind of node can this be?");
- assert(is_Load(), "only for loads");
if (ac->as_ArrayCopy()->is_clonebasic()) {
assert(ld_alloc != NULL, "need an alloc");
- Node* ld = clone();
Node* addp = in(MemNode::Address)->clone();
assert(addp->is_AddP(), "address must be addp");
assert(addp->in(AddPNode::Base) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Base), "strange pattern");
assert(addp->in(AddPNode::Address) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Address), "strange pattern");
addp->set_req(AddPNode::Base, ac->in(ArrayCopyNode::Src)->in(AddPNode::Base));
--- 827,847 ----
}
// Is the value loaded previously stored by an arraycopy? If so return
// a load node that reads from the source array so we may be able to
// optimize out the ArrayCopy node later.
! Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseTransform* phase) const {
Node* ld_adr = in(MemNode::Address);
intptr_t ld_off = 0;
AllocateNode* ld_alloc = AllocateNode::Ideal_allocation(ld_adr, phase, ld_off);
Node* ac = find_previous_arraycopy(phase, ld_alloc, st, true);
if (ac != NULL) {
assert(ac->is_ArrayCopy(), "what kind of node can this be?");
+ Node* ld = clone();
if (ac->as_ArrayCopy()->is_clonebasic()) {
assert(ld_alloc != NULL, "need an alloc");
Node* addp = in(MemNode::Address)->clone();
assert(addp->is_AddP(), "address must be addp");
assert(addp->in(AddPNode::Base) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Base), "strange pattern");
assert(addp->in(AddPNode::Address) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Address), "strange pattern");
addp->set_req(AddPNode::Base, ac->in(ArrayCopyNode::Src)->in(AddPNode::Base));
*** 904,916 ****
ld->set_req(MemNode::Address, phase->transform(addp));
if (in(0) != NULL) {
assert(ld_alloc->in(0) != NULL, "alloc must have control");
ld->set_req(0, ld_alloc->in(0));
}
- return ld;
} else {
- Node* ld = clone();
Node* addp = in(MemNode::Address)->clone();
assert(addp->in(AddPNode::Base) == addp->in(AddPNode::Address), "should be");
addp->set_req(AddPNode::Base, ac->in(ArrayCopyNode::Src));
addp->set_req(AddPNode::Address, ac->in(ArrayCopyNode::Src));
--- 849,859 ----
*** 931,942 ****
if (in(0) != NULL) {
assert(ac->in(0) != NULL, "alloc must have control");
ld->set_req(0, ac->in(0));
}
- return ld;
}
}
return NULL;
}
--- 874,887 ----
if (in(0) != NULL) {
assert(ac->in(0) != NULL, "alloc must have control");
ld->set_req(0, ac->in(0));
}
}
+ // load depends on the tests that validate the arraycopy
+ ld->as_Load()->_depends_only_on_test = Pinned;
+ return ld;
}
return NULL;
}
src/share/vm/opto/memnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File