src/share/vm/opto/escape.cpp
Print this page
rev 2892 : 7121140: Allocation paths require explicit memory synchronization operations for RMO systems
Summary: adds store store barrier after initialization of header and body of objects.
Reviewed-by:
*** 1593,1602 ****
--- 1593,1603 ----
}
GrowableArray<Node*> alloc_worklist;
GrowableArray<Node*> addp_worklist;
GrowableArray<Node*> ptr_cmp_worklist;
+ GrowableArray<Node*> storestore_worklist;
PhaseGVN* igvn = _igvn;
// Push all useful nodes onto CG list and set their type.
for( uint next = 0; next < worklist_init.size(); ++next ) {
Node* n = worklist_init.at(next);
*** 1616,1625 ****
--- 1617,1631 ----
_mergemem_worklist.append(n->as_MergeMem());
} else if (OptimizePtrCompare && n->is_Cmp() &&
(n->Opcode() == Op_CmpP || n->Opcode() == Op_CmpN)) {
// Compare pointers nodes
ptr_cmp_worklist.append(n);
+ } else if (n->is_MemBarStoreStore()) {
+ // Collect all MemBarStoreStore nodes so that depending on the
+ // escape status of the associated Allocate node some of them
+ // may be eliminated.
+ storestore_worklist.append(n);
}
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* m = n->fast_out(i); // Get user
worklist_init.push(m);
}
*** 1722,1736 ****
// 6. Find fields initializing values for not escaped allocations
uint alloc_length = alloc_worklist.length();
for (uint next = 0; next < alloc_length; ++next) {
Node* n = alloc_worklist.at(next);
! if (ptnode_adr(n->_idx)->escape_state() == PointsToNode::NoEscape) {
has_non_escaping_obj = true;
if (n->is_Allocate()) {
find_init_values(n, &visited, igvn);
! }
}
}
uint cg_length = cg_worklist.length();
--- 1728,1751 ----
// 6. Find fields initializing values for not escaped allocations
uint alloc_length = alloc_worklist.length();
for (uint next = 0; next < alloc_length; ++next) {
Node* n = alloc_worklist.at(next);
! PointsToNode::EscapeState es = ptnode_adr(n->_idx)->escape_state();
! if (es == PointsToNode::NoEscape) {
has_non_escaping_obj = true;
if (n->is_Allocate()) {
find_init_values(n, &visited, igvn);
! // The object allocated by this Allocate node will never be
! // seen by an other thread. Mark it so that when it is
! // expanded no MemBarStoreStore is added.
! n->as_Allocate()->initialization()->set_does_not_escape();
! }
! } else if ((es == PointsToNode::ArgEscape) && n->is_Allocate()) {
! // Same as above. Mark this Allocate node so that when it is
! // expanded no MemBarStoreStore is added.
! n->as_Allocate()->initialization()->set_does_not_escape();
}
}
uint cg_length = cg_worklist.length();
*** 1872,1881 ****
--- 1887,1915 ----
igvn->hash_delete(_pcmp_neq);
if (_pcmp_eq->outcnt() == 0)
igvn->hash_delete(_pcmp_eq);
}
+ // For MemBarStoreStore nodes added in library_call.cpp, check
+ // escape status of associated AllocateNode and optimize out
+ // MemBarStoreStore node if the allocated object never escapes.
+ while (storestore_worklist.length() != 0) {
+ Node *n = storestore_worklist.pop();
+ MemBarStoreStoreNode *storestore = n ->as_MemBarStoreStore();
+ Node *alloc = storestore->in(MemBarNode::Precedent)->in(0);
+ assert (alloc->is_Allocate(), "storestore should point to AllocateNode");
+ PointsToNode::EscapeState es = ptnode_adr(alloc->_idx)->escape_state();
+ if (es == PointsToNode::NoEscape || es == PointsToNode::ArgEscape) {
+ MemBarNode* mb = MemBarNode::make(C, Op_MemBarCPUOrder, Compile::AliasIdxBot);
+ mb->init_req(TypeFunc::Memory, storestore->in(TypeFunc::Memory));
+ mb->init_req(TypeFunc::Control, storestore->in(TypeFunc::Control));
+
+ _igvn->register_new_node_with_optimizer(mb);
+ _igvn->replace_node(storestore, mb);
+ }
+ }
+
#ifndef PRODUCT
if (PrintEscapeAnalysis) {
dump(); // Dump ConnectionGraph
}
#endif