comparison src/share/vm/opto/escape.cpp @ 1634:60a14ad85270

6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP Summary: Execute IGVN optimization before and after Escape Analysis Reviewed-by: never
author kvn
date Fri, 02 Jul 2010 17:30:30 -0700
parents c18cbe5936b8
children 5867d89c129b
comparison
equal deleted inserted replaced
1633:65b0c03b165d 1634:60a14ad85270
79 else 79 else
80 _node->dump(); 80 _node->dump();
81 } 81 }
82 #endif 82 #endif
83 83
84 ConnectionGraph::ConnectionGraph(Compile * C) : 84 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
85 _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), 85 _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
86 _processed(C->comp_arena()), 86 _processed(C->comp_arena()),
87 _collecting(true), 87 _collecting(true),
88 _compile(C), 88 _compile(C),
89 _igvn(igvn),
89 _node_map(C->comp_arena()) { 90 _node_map(C->comp_arena()) {
90 91
91 _phantom_object = C->top()->_idx, 92 _phantom_object = C->top()->_idx,
92 add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true); 93 add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true);
93 94
94 // Add ConP(#NULL) and ConN(#NULL) nodes. 95 // Add ConP(#NULL) and ConN(#NULL) nodes.
95 PhaseGVN* igvn = C->initial_gvn();
96 Node* oop_null = igvn->zerocon(T_OBJECT); 96 Node* oop_null = igvn->zerocon(T_OBJECT);
97 _oop_null = oop_null->_idx; 97 _oop_null = oop_null->_idx;
98 assert(_oop_null < C->unique(), "should be created already"); 98 assert(_oop_null < C->unique(), "should be created already");
99 add_node(oop_null, PointsToNode::JavaObject, PointsToNode::NoEscape, true); 99 add_node(oop_null, PointsToNode::JavaObject, PointsToNode::NoEscape, true);
100 100
180 180
181 if (done) 181 if (done)
182 _processed.set(n->_idx); 182 _processed.set(n->_idx);
183 } 183 }
184 184
185 PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform *phase) { 185 PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) {
186 uint idx = n->_idx; 186 uint idx = n->_idx;
187 PointsToNode::EscapeState es; 187 PointsToNode::EscapeState es;
188 188
189 // If we are still collecting or there were no non-escaping allocations 189 // If we are still collecting or there were no non-escaping allocations
190 // we don't know the answer yet 190 // we don't know the answer yet
205 205
206 // PointsTo() calls n->uncast() which can return a new ideal node. 206 // PointsTo() calls n->uncast() which can return a new ideal node.
207 if (n->uncast()->_idx >= nodes_size()) 207 if (n->uncast()->_idx >= nodes_size())
208 return PointsToNode::UnknownEscape; 208 return PointsToNode::UnknownEscape;
209 209
210 PointsToNode::EscapeState orig_es = es;
211
210 // compute max escape state of anything this node could point to 212 // compute max escape state of anything this node could point to
211 VectorSet ptset(Thread::current()->resource_area()); 213 VectorSet ptset(Thread::current()->resource_area());
212 PointsTo(ptset, n, phase); 214 PointsTo(ptset, n);
213 for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) { 215 for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) {
214 uint pt = i.elem; 216 uint pt = i.elem;
215 PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state(); 217 PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state();
216 if (pes > es) 218 if (pes > es)
217 es = pes; 219 es = pes;
218 } 220 }
219 // cache the computed escape state 221 if (orig_es != es) {
220 assert(es != PointsToNode::UnknownEscape, "should have computed an escape state"); 222 // cache the computed escape state
221 ptnode_adr(idx)->set_escape_state(es); 223 assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
224 ptnode_adr(idx)->set_escape_state(es);
225 } // orig_es could be PointsToNode::UnknownEscape
222 return es; 226 return es;
223 } 227 }
224 228
225 void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase) { 229 void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) {
226 VectorSet visited(Thread::current()->resource_area()); 230 VectorSet visited(Thread::current()->resource_area());
227 GrowableArray<uint> worklist; 231 GrowableArray<uint> worklist;
228 232
229 #ifdef ASSERT 233 #ifdef ASSERT
230 Node *orig_n = n; 234 Node *orig_n = n;
988 // 992 //
989 void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist) { 993 void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist) {
990 GrowableArray<Node *> memnode_worklist; 994 GrowableArray<Node *> memnode_worklist;
991 GrowableArray<PhiNode *> orig_phis; 995 GrowableArray<PhiNode *> orig_phis;
992 996
993 PhaseGVN *igvn = _compile->initial_gvn(); 997 PhaseGVN *igvn = _igvn;
994 uint new_index_start = (uint) _compile->num_alias_types(); 998 uint new_index_start = (uint) _compile->num_alias_types();
995 Arena* arena = Thread::current()->resource_area(); 999 Arena* arena = Thread::current()->resource_area();
996 VectorSet visited(arena); 1000 VectorSet visited(arena);
997 VectorSet ptset(arena); 1001 VectorSet ptset(arena);
998 1002
1010 const TypeOopPtr* tinst = NULL; 1014 const TypeOopPtr* tinst = NULL;
1011 if (n->is_Call()) { 1015 if (n->is_Call()) {
1012 CallNode *alloc = n->as_Call(); 1016 CallNode *alloc = n->as_Call();
1013 // copy escape information to call node 1017 // copy escape information to call node
1014 PointsToNode* ptn = ptnode_adr(alloc->_idx); 1018 PointsToNode* ptn = ptnode_adr(alloc->_idx);
1015 PointsToNode::EscapeState es = escape_state(alloc, igvn); 1019 PointsToNode::EscapeState es = escape_state(alloc);
1016 // We have an allocation or call which returns a Java object, 1020 // We have an allocation or call which returns a Java object,
1017 // see if it is unescaped. 1021 // see if it is unescaped.
1018 if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable) 1022 if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable)
1019 continue; 1023 continue;
1020 1024
1121 } 1125 }
1122 } 1126 }
1123 } 1127 }
1124 } else if (n->is_AddP()) { 1128 } else if (n->is_AddP()) {
1125 ptset.Clear(); 1129 ptset.Clear();
1126 PointsTo(ptset, get_addp_base(n), igvn); 1130 PointsTo(ptset, get_addp_base(n));
1127 assert(ptset.Size() == 1, "AddP address is unique"); 1131 assert(ptset.Size() == 1, "AddP address is unique");
1128 uint elem = ptset.getelem(); // Allocation node's index 1132 uint elem = ptset.getelem(); // Allocation node's index
1129 if (elem == _phantom_object) { 1133 if (elem == _phantom_object) {
1130 assert(false, "escaped allocation"); 1134 assert(false, "escaped allocation");
1131 continue; // Assume the value was set outside this method. 1135 continue; // Assume the value was set outside this method.
1141 if (visited.test_set(n->_idx)) { 1145 if (visited.test_set(n->_idx)) {
1142 assert(n->is_Phi(), "loops only through Phi's"); 1146 assert(n->is_Phi(), "loops only through Phi's");
1143 continue; // already processed 1147 continue; // already processed
1144 } 1148 }
1145 ptset.Clear(); 1149 ptset.Clear();
1146 PointsTo(ptset, n, igvn); 1150 PointsTo(ptset, n);
1147 if (ptset.Size() == 1) { 1151 if (ptset.Size() == 1) {
1148 uint elem = ptset.getelem(); // Allocation node's index 1152 uint elem = ptset.getelem(); // Allocation node's index
1149 if (elem == _phantom_object) { 1153 if (elem == _phantom_object) {
1150 assert(false, "escaped allocation"); 1154 assert(false, "escaped allocation");
1151 continue; // Assume the value was set outside this method. 1155 continue; // Assume the value was set outside this method.
1476 } 1480 }
1477 } 1481 }
1478 return false; 1482 return false;
1479 } 1483 }
1480 1484
1485 void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) {
1486 // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction
1487 // to create space for them in ConnectionGraph::_nodes[].
1488 Node* oop_null = igvn->zerocon(T_OBJECT);
1489 Node* noop_null = igvn->zerocon(T_NARROWOOP);
1490
1491 ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn);
1492 // Perform escape analysis
1493 if (congraph->compute_escape()) {
1494 // There are non escaping objects.
1495 C->set_congraph(congraph);
1496 }
1497
1498 // Cleanup.
1499 if (oop_null->outcnt() == 0)
1500 igvn->hash_delete(oop_null);
1501 if (noop_null->outcnt() == 0)
1502 igvn->hash_delete(noop_null);
1503 }
1504
1481 bool ConnectionGraph::compute_escape() { 1505 bool ConnectionGraph::compute_escape() {
1482 Compile* C = _compile; 1506 Compile* C = _compile;
1483 1507
1484 // 1. Populate Connection Graph (CG) with Ideal nodes. 1508 // 1. Populate Connection Graph (CG) with Ideal nodes.
1485 1509
1490 if (C->root() != NULL) { 1514 if (C->root() != NULL) {
1491 worklist_init.push(C->root()); 1515 worklist_init.push(C->root());
1492 } 1516 }
1493 1517
1494 GrowableArray<int> cg_worklist; 1518 GrowableArray<int> cg_worklist;
1495 PhaseGVN* igvn = C->initial_gvn(); 1519 PhaseGVN* igvn = _igvn;
1496 bool has_allocations = false; 1520 bool has_allocations = false;
1497 1521
1498 // Push all useful nodes onto CG list and set their type. 1522 // Push all useful nodes onto CG list and set their type.
1499 for( uint next = 0; next < worklist_init.size(); ++next ) { 1523 for( uint next = 0; next < worklist_init.size(); ++next ) {
1500 Node* n = worklist_init.at(next); 1524 Node* n = worklist_init.at(next);
1659 } 1683 }
1660 1684
1661 _collecting = false; 1685 _collecting = false;
1662 assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build"); 1686 assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build");
1663 1687
1688 #ifndef PRODUCT
1689 if (PrintEscapeAnalysis) {
1690 dump(); // Dump ConnectionGraph
1691 }
1692 #endif
1693
1664 bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0; 1694 bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0;
1665 if ( has_scalar_replaceable_candidates && 1695 if ( has_scalar_replaceable_candidates &&
1666 C->AliasLevel() >= 3 && EliminateAllocations ) { 1696 C->AliasLevel() >= 3 && EliminateAllocations ) {
1667 1697
1668 // Now use the escape information to create unique types for 1698 // Now use the escape information to create unique types for
1669 // scalar replaceable objects. 1699 // scalar replaceable objects.
1670 split_unique_types(alloc_worklist); 1700 split_unique_types(alloc_worklist);
1671 1701
1672 if (C->failing()) return false; 1702 if (C->failing()) return false;
1673
1674 // Clean up after split unique types.
1675 ResourceMark rm;
1676 PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn());
1677 1703
1678 C->print_method("After Escape Analysis", 2); 1704 C->print_method("After Escape Analysis", 2);
1679 1705
1680 #ifdef ASSERT 1706 #ifdef ASSERT
1681 } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) { 1707 } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) {
1709 Compile* C = _compile; 1735 Compile* C = _compile;
1710 1736
1711 int offset = ptn->offset(); 1737 int offset = ptn->offset();
1712 Node* base = get_addp_base(n); 1738 Node* base = get_addp_base(n);
1713 ptset.Clear(); 1739 ptset.Clear();
1714 PointsTo(ptset, base, phase); 1740 PointsTo(ptset, base);
1715 int ptset_size = ptset.Size(); 1741 int ptset_size = ptset.Size();
1716 1742
1717 // Check if a oop field's initializing value is recorded and add 1743 // Check if a oop field's initializing value is recorded and add
1718 // a corresponding NULL field's value if it is not recorded. 1744 // a corresponding NULL field's value if it is not recorded.
1719 // Connection Graph does not record a default initialization by NULL 1745 // Connection Graph does not record a default initialization by NULL
1887 // pointer to the base (with offset) is passed as argument. 1913 // pointer to the base (with offset) is passed as argument.
1888 // 1914 //
1889 arg = get_addp_base(arg); 1915 arg = get_addp_base(arg);
1890 } 1916 }
1891 ptset.Clear(); 1917 ptset.Clear();
1892 PointsTo(ptset, arg, phase); 1918 PointsTo(ptset, arg);
1893 for( VectorSetI j(&ptset); j.test(); ++j ) { 1919 for( VectorSetI j(&ptset); j.test(); ++j ) {
1894 uint pt = j.elem; 1920 uint pt = j.elem;
1895 set_escape_state(pt, PointsToNode::ArgEscape); 1921 set_escape_state(pt, PointsToNode::ArgEscape);
1896 } 1922 }
1897 } 1923 }
1932 set_escape_state(arg->_idx, PointsToNode::ArgEscape); 1958 set_escape_state(arg->_idx, PointsToNode::ArgEscape);
1933 copy_dependencies = true; 1959 copy_dependencies = true;
1934 } 1960 }
1935 1961
1936 ptset.Clear(); 1962 ptset.Clear();
1937 PointsTo(ptset, arg, phase); 1963 PointsTo(ptset, arg);
1938 for( VectorSetI j(&ptset); j.test(); ++j ) { 1964 for( VectorSetI j(&ptset); j.test(); ++j ) {
1939 uint pt = j.elem; 1965 uint pt = j.elem;
1940 if (global_escapes) { 1966 if (global_escapes) {
1941 //The argument global escapes, mark everything it could point to 1967 //The argument global escapes, mark everything it could point to
1942 set_escape_state(pt, PointsToNode::GlobalEscape); 1968 set_escape_state(pt, PointsToNode::GlobalEscape);
1968 const Type* at = d->field_at(i); 1994 const Type* at = d->field_at(i);
1969 if (at->isa_oopptr() != NULL) { 1995 if (at->isa_oopptr() != NULL) {
1970 Node *arg = call->in(i)->uncast(); 1996 Node *arg = call->in(i)->uncast();
1971 set_escape_state(arg->_idx, PointsToNode::GlobalEscape); 1997 set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
1972 ptset.Clear(); 1998 ptset.Clear();
1973 PointsTo(ptset, arg, phase); 1999 PointsTo(ptset, arg);
1974 for( VectorSetI j(&ptset); j.test(); ++j ) { 2000 for( VectorSetI j(&ptset); j.test(); ++j ) {
1975 uint pt = j.elem; 2001 uint pt = j.elem;
1976 set_escape_state(pt, PointsToNode::GlobalEscape); 2002 set_escape_state(pt, PointsToNode::GlobalEscape);
1977 } 2003 }
1978 } 2004 }
2431 case Op_AddP: 2457 case Op_AddP:
2432 { 2458 {
2433 Node *base = get_addp_base(n); 2459 Node *base = get_addp_base(n);
2434 // Create a field edge to this node from everything base could point to. 2460 // Create a field edge to this node from everything base could point to.
2435 VectorSet ptset(Thread::current()->resource_area()); 2461 VectorSet ptset(Thread::current()->resource_area());
2436 PointsTo(ptset, base, phase); 2462 PointsTo(ptset, base);
2437 for( VectorSetI i(&ptset); i.test(); ++i ) { 2463 for( VectorSetI i(&ptset); i.test(); ++i ) {
2438 uint pt = i.elem; 2464 uint pt = i.elem;
2439 add_field_edge(pt, n_idx, address_offset(n, phase)); 2465 add_field_edge(pt, n_idx, address_offset(n, phase));
2440 } 2466 }
2441 break; 2467 break;
2499 } 2525 }
2500 2526
2501 // For everything "adr_base" could point to, create a deferred edge from 2527 // For everything "adr_base" could point to, create a deferred edge from
2502 // this node to each field with the same offset. 2528 // this node to each field with the same offset.
2503 VectorSet ptset(Thread::current()->resource_area()); 2529 VectorSet ptset(Thread::current()->resource_area());
2504 PointsTo(ptset, adr_base, phase); 2530 PointsTo(ptset, adr_base);
2505 int offset = address_offset(adr, phase); 2531 int offset = address_offset(adr, phase);
2506 for( VectorSetI i(&ptset); i.test(); ++i ) { 2532 for( VectorSetI i(&ptset); i.test(); ++i ) {
2507 uint pt = i.elem; 2533 uint pt = i.elem;
2508 add_deferred_edge_to_fields(n_idx, pt, offset); 2534 add_deferred_edge_to_fields(n_idx, pt, offset);
2509 } 2535 }
2592 Node *adr_base = get_addp_base(adr); 2618 Node *adr_base = get_addp_base(adr);
2593 Node *val = n->in(MemNode::ValueIn)->uncast(); 2619 Node *val = n->in(MemNode::ValueIn)->uncast();
2594 // For everything "adr_base" could point to, create a deferred edge 2620 // For everything "adr_base" could point to, create a deferred edge
2595 // to "val" from each field with the same offset. 2621 // to "val" from each field with the same offset.
2596 VectorSet ptset(Thread::current()->resource_area()); 2622 VectorSet ptset(Thread::current()->resource_area());
2597 PointsTo(ptset, adr_base, phase); 2623 PointsTo(ptset, adr_base);
2598 for( VectorSetI i(&ptset); i.test(); ++i ) { 2624 for( VectorSetI i(&ptset); i.test(); ++i ) {
2599 uint pt = i.elem; 2625 uint pt = i.elem;
2600 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase)); 2626 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase));
2601 } 2627 }
2602 break; 2628 break;
2636 } 2662 }
2637 } 2663 }
2638 2664
2639 #ifndef PRODUCT 2665 #ifndef PRODUCT
2640 void ConnectionGraph::dump() { 2666 void ConnectionGraph::dump() {
2641 PhaseGVN *igvn = _compile->initial_gvn();
2642 bool first = true; 2667 bool first = true;
2643 2668
2644 uint size = nodes_size(); 2669 uint size = nodes_size();
2645 for (uint ni = 0; ni < size; ni++) { 2670 for (uint ni = 0; ni < size; ni++) {
2646 PointsToNode *ptn = ptnode_adr(ni); 2671 PointsToNode *ptn = ptnode_adr(ni);
2647 PointsToNode::NodeType ptn_type = ptn->node_type(); 2672 PointsToNode::NodeType ptn_type = ptn->node_type();
2648 2673
2649 if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL) 2674 if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL)
2650 continue; 2675 continue;
2651 PointsToNode::EscapeState es = escape_state(ptn->_node, igvn); 2676 PointsToNode::EscapeState es = escape_state(ptn->_node);
2652 if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) { 2677 if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) {
2653 if (first) { 2678 if (first) {
2654 tty->cr(); 2679 tty->cr();
2655 tty->print("======== Connection graph for "); 2680 tty->print("======== Connection graph for ");
2656 _compile->method()->print_short_name(); 2681 _compile->method()->print_short_name();