comparison src/share/vm/opto/escape.cpp @ 10278:6f3fd5150b67

6934604: enable parts of EliminateAutoBox by default Summary: Resurrected autobox elimination code and enabled part of it by default. Reviewed-by: roland, twisti
author kvn
date Wed, 08 May 2013 15:08:01 -0700
parents b30b3c2a0cf2
children 70120f47d403
comparison
equal deleted inserted replaced
10277:aabf54ccedb1 10278:6f3fd5150b67
61 61
62 bool ConnectionGraph::has_candidates(Compile *C) { 62 bool ConnectionGraph::has_candidates(Compile *C) {
63 // EA brings benefits only when the code has allocations and/or locks which 63 // EA brings benefits only when the code has allocations and/or locks which
64 // are represented by ideal Macro nodes. 64 // are represented by ideal Macro nodes.
65 int cnt = C->macro_count(); 65 int cnt = C->macro_count();
66 for( int i=0; i < cnt; i++ ) { 66 for (int i = 0; i < cnt; i++) {
67 Node *n = C->macro_node(i); 67 Node *n = C->macro_node(i);
68 if ( n->is_Allocate() ) 68 if (n->is_Allocate())
69 return true; 69 return true;
70 if( n->is_Lock() ) { 70 if (n->is_Lock()) {
71 Node* obj = n->as_Lock()->obj_node()->uncast(); 71 Node* obj = n->as_Lock()->obj_node()->uncast();
72 if( !(obj->is_Parm() || obj->is_Con()) ) 72 if (!(obj->is_Parm() || obj->is_Con()))
73 return true; 73 return true;
74 }
75 if (n->is_CallStaticJava() &&
76 n->as_CallStaticJava()->is_boxing_method()) {
77 return true;
74 } 78 }
75 } 79 }
76 return false; 80 return false;
77 } 81 }
78 82
113 DEBUG_ONLY( GrowableArray<Node*> addp_worklist; ) 117 DEBUG_ONLY( GrowableArray<Node*> addp_worklist; )
114 118
115 { Compile::TracePhase t3("connectionGraph", &Phase::_t_connectionGraph, true); 119 { Compile::TracePhase t3("connectionGraph", &Phase::_t_connectionGraph, true);
116 120
117 // 1. Populate Connection Graph (CG) with PointsTo nodes. 121 // 1. Populate Connection Graph (CG) with PointsTo nodes.
118 ideal_nodes.map(C->unique(), NULL); // preallocate space 122 ideal_nodes.map(C->live_nodes(), NULL); // preallocate space
119 // Initialize worklist 123 // Initialize worklist
120 if (C->root() != NULL) { 124 if (C->root() != NULL) {
121 ideal_nodes.push(C->root()); 125 ideal_nodes.push(C->root());
122 } 126 }
123 for( uint next = 0; next < ideal_nodes.size(); ++next ) { 127 for( uint next = 0; next < ideal_nodes.size(); ++next ) {
150 } else if (n->is_MemBarStoreStore()) { 154 } else if (n->is_MemBarStoreStore()) {
151 // Collect all MemBarStoreStore nodes so that depending on the 155 // Collect all MemBarStoreStore nodes so that depending on the
152 // escape status of the associated Allocate node some of them 156 // escape status of the associated Allocate node some of them
153 // may be eliminated. 157 // may be eliminated.
154 storestore_worklist.append(n); 158 storestore_worklist.append(n);
159 } else if (n->is_MemBar() && (n->Opcode() == Op_MemBarRelease) &&
160 (n->req() > MemBarNode::Precedent)) {
161 record_for_optimizer(n);
155 #ifdef ASSERT 162 #ifdef ASSERT
156 } else if(n->is_AddP()) { 163 } else if (n->is_AddP()) {
157 // Collect address nodes for graph verification. 164 // Collect address nodes for graph verification.
158 addp_worklist.append(n); 165 addp_worklist.append(n);
159 #endif 166 #endif
160 } 167 }
161 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { 168 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
204 // scalar replaceable allocations on alloc_worklist for processing 211 // scalar replaceable allocations on alloc_worklist for processing
205 // in split_unique_types(). 212 // in split_unique_types().
206 int non_escaped_length = non_escaped_worklist.length(); 213 int non_escaped_length = non_escaped_worklist.length();
207 for (int next = 0; next < non_escaped_length; next++) { 214 for (int next = 0; next < non_escaped_length; next++) {
208 JavaObjectNode* ptn = non_escaped_worklist.at(next); 215 JavaObjectNode* ptn = non_escaped_worklist.at(next);
209 if (ptn->escape_state() == PointsToNode::NoEscape && 216 bool noescape = (ptn->escape_state() == PointsToNode::NoEscape);
210 ptn->scalar_replaceable()) { 217 Node* n = ptn->ideal_node();
218 if (n->is_Allocate()) {
219 n->as_Allocate()->_is_non_escaping = noescape;
220 }
221 if (n->is_CallStaticJava()) {
222 n->as_CallStaticJava()->_is_non_escaping = noescape;
223 }
224 if (noescape && ptn->scalar_replaceable()) {
211 adjust_scalar_replaceable_state(ptn); 225 adjust_scalar_replaceable_state(ptn);
212 if (ptn->scalar_replaceable()) { 226 if (ptn->scalar_replaceable()) {
213 alloc_worklist.append(ptn->ideal_node()); 227 alloc_worklist.append(ptn->ideal_node());
214 } 228 }
215 } 229 }
328 return; // Skip uncommon traps 342 return; // Skip uncommon traps
329 } 343 }
330 // Don't mark as processed since call's arguments have to be processed. 344 // Don't mark as processed since call's arguments have to be processed.
331 delayed_worklist->push(n); 345 delayed_worklist->push(n);
332 // Check if a call returns an object. 346 // Check if a call returns an object.
333 if (n->as_Call()->returns_pointer() && 347 if ((n->as_Call()->returns_pointer() &&
334 n->as_Call()->proj_out(TypeFunc::Parms) != NULL) { 348 n->as_Call()->proj_out(TypeFunc::Parms) != NULL) ||
349 (n->is_CallStaticJava() &&
350 n->as_CallStaticJava()->is_boxing_method())) {
335 add_call_node(n->as_Call()); 351 add_call_node(n->as_Call());
336 } 352 }
337 } 353 }
338 return; 354 return;
339 } 355 }
385 case Op_ConP: 401 case Op_ConP:
386 case Op_ConN: 402 case Op_ConN:
387 case Op_ConNKlass: { 403 case Op_ConNKlass: {
388 // assume all oop constants globally escape except for null 404 // assume all oop constants globally escape except for null
389 PointsToNode::EscapeState es; 405 PointsToNode::EscapeState es;
390 if (igvn->type(n) == TypePtr::NULL_PTR || 406 const Type* t = igvn->type(n);
391 igvn->type(n) == TypeNarrowOop::NULL_PTR) { 407 if (t == TypePtr::NULL_PTR || t == TypeNarrowOop::NULL_PTR) {
392 es = PointsToNode::NoEscape; 408 es = PointsToNode::NoEscape;
393 } else { 409 } else {
394 es = PointsToNode::GlobalEscape; 410 es = PointsToNode::GlobalEscape;
395 } 411 }
396 add_java_object(n, es); 412 add_java_object(n, es);
795 const char* name = call->as_CallStaticJava()->_name; 811 const char* name = call->as_CallStaticJava()->_name;
796 assert(strncmp(name, "_multianewarray", 15) == 0, "TODO: add failed case check"); 812 assert(strncmp(name, "_multianewarray", 15) == 0, "TODO: add failed case check");
797 // Returns a newly allocated unescaped object. 813 // Returns a newly allocated unescaped object.
798 add_java_object(call, PointsToNode::NoEscape); 814 add_java_object(call, PointsToNode::NoEscape);
799 ptnode_adr(call_idx)->set_scalar_replaceable(false); 815 ptnode_adr(call_idx)->set_scalar_replaceable(false);
816 } else if (meth->is_boxing_method()) {
817 // Returns boxing object
818 add_java_object(call, PointsToNode::NoEscape);
800 } else { 819 } else {
801 BCEscapeAnalyzer* call_analyzer = meth->get_bcea(); 820 BCEscapeAnalyzer* call_analyzer = meth->get_bcea();
802 call_analyzer->copy_dependencies(_compile->dependencies()); 821 call_analyzer->copy_dependencies(_compile->dependencies());
803 if (call_analyzer->is_return_allocated()) { 822 if (call_analyzer->is_return_allocated()) {
804 // Returns a newly allocated unescaped object, simply 823 // Returns a newly allocated unescaped object, simply
941 #ifdef ASSERT 960 #ifdef ASSERT
942 const char* name = call->as_CallStaticJava()->_name; 961 const char* name = call->as_CallStaticJava()->_name;
943 assert((name == NULL || strcmp(name, "uncommon_trap") != 0), "normal calls only"); 962 assert((name == NULL || strcmp(name, "uncommon_trap") != 0), "normal calls only");
944 #endif 963 #endif
945 ciMethod* meth = call->as_CallJava()->method(); 964 ciMethod* meth = call->as_CallJava()->method();
965 if ((meth != NULL) && meth->is_boxing_method()) {
966 break; // Boxing methods do not modify any oops.
967 }
946 BCEscapeAnalyzer* call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL; 968 BCEscapeAnalyzer* call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL;
947 // fall-through if not a Java method or no analyzer information 969 // fall-through if not a Java method or no analyzer information
948 if (call_analyzer != NULL) { 970 if (call_analyzer != NULL) {
949 PointsToNode* call_ptn = ptnode_adr(call->_idx); 971 PointsToNode* call_ptn = ptnode_adr(call->_idx);
950 const TypeTuple* d = call->tf()->domain(); 972 const TypeTuple* d = call->tf()->domain();
2742 if (alloc->is_Allocate()) { 2764 if (alloc->is_Allocate()) {
2743 // Set the scalar_replaceable flag for allocation 2765 // Set the scalar_replaceable flag for allocation
2744 // so it could be eliminated if it has no uses. 2766 // so it could be eliminated if it has no uses.
2745 alloc->as_Allocate()->_is_scalar_replaceable = true; 2767 alloc->as_Allocate()->_is_scalar_replaceable = true;
2746 } 2768 }
2769 if (alloc->is_CallStaticJava()) {
2770 // Set the scalar_replaceable flag for boxing method
2771 // so it could be eliminated if it has no uses.
2772 alloc->as_CallStaticJava()->_is_scalar_replaceable = true;
2773 }
2747 continue; 2774 continue;
2748 } 2775 }
2749 if (!n->is_CheckCastPP()) { // not unique CheckCastPP. 2776 if (!n->is_CheckCastPP()) { // not unique CheckCastPP.
2750 assert(!alloc->is_Allocate(), "allocation should have unique type"); 2777 assert(!alloc->is_Allocate(), "allocation should have unique type");
2751 continue; 2778 continue;
2779 } 2806 }
2780 if (alloc->is_Allocate()) { 2807 if (alloc->is_Allocate()) {
2781 // Set the scalar_replaceable flag for allocation 2808 // Set the scalar_replaceable flag for allocation
2782 // so it could be eliminated. 2809 // so it could be eliminated.
2783 alloc->as_Allocate()->_is_scalar_replaceable = true; 2810 alloc->as_Allocate()->_is_scalar_replaceable = true;
2811 }
2812 if (alloc->is_CallStaticJava()) {
2813 // Set the scalar_replaceable flag for boxing method
2814 // so it could be eliminated.
2815 alloc->as_CallStaticJava()->_is_scalar_replaceable = true;
2784 } 2816 }
2785 set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state 2817 set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state
2786 // in order for an object to be scalar-replaceable, it must be: 2818 // in order for an object to be scalar-replaceable, it must be:
2787 // - a direct allocation (not a call returning an object) 2819 // - a direct allocation (not a call returning an object)
2788 // - non-escaping 2820 // - non-escaping
2909 Node *use = n->fast_out(i); 2941 Node *use = n->fast_out(i);
2910 if(use->is_Mem() && use->in(MemNode::Address) == n) { 2942 if(use->is_Mem() && use->in(MemNode::Address) == n) {
2911 // Load/store to instance's field 2943 // Load/store to instance's field
2912 memnode_worklist.append_if_missing(use); 2944 memnode_worklist.append_if_missing(use);
2913 } else if (use->is_MemBar()) { 2945 } else if (use->is_MemBar()) {
2914 memnode_worklist.append_if_missing(use); 2946 if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge
2947 memnode_worklist.append_if_missing(use);
2948 }
2915 } else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes 2949 } else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes
2916 Node* addp2 = find_second_addp(use, n); 2950 Node* addp2 = find_second_addp(use, n);
2917 if (addp2 != NULL) { 2951 if (addp2 != NULL) {
2918 alloc_worklist.append_if_missing(addp2); 2952 alloc_worklist.append_if_missing(addp2);
2919 } 2953 }
3026 } else if (use->is_Mem() && use->in(MemNode::Memory) == n) { 3060 } else if (use->is_Mem() && use->in(MemNode::Memory) == n) {
3027 if (use->Opcode() == Op_StoreCM) // Ignore cardmark stores 3061 if (use->Opcode() == Op_StoreCM) // Ignore cardmark stores
3028 continue; 3062 continue;
3029 memnode_worklist.append_if_missing(use); 3063 memnode_worklist.append_if_missing(use);
3030 } else if (use->is_MemBar()) { 3064 } else if (use->is_MemBar()) {
3031 memnode_worklist.append_if_missing(use); 3065 if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge
3066 memnode_worklist.append_if_missing(use);
3067 }
3032 #ifdef ASSERT 3068 #ifdef ASSERT
3033 } else if(use->is_Mem()) { 3069 } else if(use->is_Mem()) {
3034 assert(use->in(MemNode::Memory) != n, "EA: missing memory path"); 3070 assert(use->in(MemNode::Memory) != n, "EA: missing memory path");
3035 } else if (use->is_MergeMem()) { 3071 } else if (use->is_MergeMem()) {
3036 assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist"); 3072 assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist");
3262 for (int i = 0; i < ptnodes_length; i++) { 3298 for (int i = 0; i < ptnodes_length; i++) {
3263 PointsToNode *ptn = ptnodes_worklist.at(i); 3299 PointsToNode *ptn = ptnodes_worklist.at(i);
3264 if (ptn == NULL || !ptn->is_JavaObject()) 3300 if (ptn == NULL || !ptn->is_JavaObject())
3265 continue; 3301 continue;
3266 PointsToNode::EscapeState es = ptn->escape_state(); 3302 PointsToNode::EscapeState es = ptn->escape_state();
3267 if (ptn->ideal_node()->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) { 3303 if ((es != PointsToNode::NoEscape) && !Verbose) {
3304 continue;
3305 }
3306 Node* n = ptn->ideal_node();
3307 if (n->is_Allocate() || (n->is_CallStaticJava() &&
3308 n->as_CallStaticJava()->is_boxing_method())) {
3268 if (first) { 3309 if (first) {
3269 tty->cr(); 3310 tty->cr();
3270 tty->print("======== Connection graph for "); 3311 tty->print("======== Connection graph for ");
3271 _compile->method()->print_short_name(); 3312 _compile->method()->print_short_name();
3272 tty->cr(); 3313 tty->cr();