Mercurial > hg > truffle
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(); |