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