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(); |