Mercurial > hg > truffle
comparison src/share/vm/opto/bytecodeInfo.cpp @ 41:874b2c4f43d1
6667605: (Escape Analysis) inline java constructors when EA is on
Summary: java constructors should be inlined to be able scalar replace a new object
Reviewed-by: rasbold
author | kvn |
---|---|
date | Fri, 07 Mar 2008 11:09:13 -0800 |
parents | a61af66fc99e |
children | d1605aabd0a1 524eca34ea76 |
comparison
equal
deleted
inserted
replaced
40:7c1f32ae4a20 | 41:874b2c4f43d1 |
---|---|
77 static void print_indent(int depth) { | 77 static void print_indent(int depth) { |
78 tty->print(" "); | 78 tty->print(" "); |
79 for (int i = depth; i != 0; --i) tty->print(" "); | 79 for (int i = depth; i != 0; --i) tty->print(" "); |
80 } | 80 } |
81 | 81 |
82 static bool is_init_with_ea(ciMethod* callee_method, | |
83 ciMethod* caller_method, Compile* C) { | |
84 // True when EA is ON and a java constructor is called or | |
85 // a super constructor is called from an inlined java constructor. | |
86 return DoEscapeAnalysis && EliminateAllocations && | |
87 ( callee_method->is_initializer() || | |
88 (caller_method->is_initializer() && | |
89 caller_method != C->method() && | |
90 caller_method->holder()->is_subclass_of(callee_method->holder())) | |
91 ); | |
92 } | |
93 | |
82 // positive filter: should send be inlined? returns NULL, if yes, or rejection msg | 94 // positive filter: should send be inlined? returns NULL, if yes, or rejection msg |
83 const char* InlineTree::shouldInline(ciMethod* callee_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const { | 95 const char* InlineTree::shouldInline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const { |
84 // Allows targeted inlining | 96 // Allows targeted inlining |
85 if(callee_method->should_inline()) { | 97 if(callee_method->should_inline()) { |
86 *wci_result = *(WarmCallInfo::always_hot()); | 98 *wci_result = *(WarmCallInfo::always_hot()); |
87 if (PrintInlining && Verbose) { | 99 if (PrintInlining && Verbose) { |
88 print_indent(inline_depth()); | 100 print_indent(inline_depth()); |
95 // or rejection msg | 107 // or rejection msg |
96 int max_size = C->max_inline_size(); | 108 int max_size = C->max_inline_size(); |
97 int size = callee_method->code_size(); | 109 int size = callee_method->code_size(); |
98 | 110 |
99 // Check for too many throws (and not too huge) | 111 // Check for too many throws (and not too huge) |
100 if(callee_method->interpreter_throwout_count() > InlineThrowCount && size < InlineThrowMaxSize ) { | 112 if(callee_method->interpreter_throwout_count() > InlineThrowCount && |
113 size < InlineThrowMaxSize ) { | |
101 wci_result->set_profit(wci_result->profit() * 100); | 114 wci_result->set_profit(wci_result->profit() * 100); |
102 if (PrintInlining && Verbose) { | 115 if (PrintInlining && Verbose) { |
103 print_indent(inline_depth()); | 116 print_indent(inline_depth()); |
104 tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count()); | 117 tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count()); |
105 } | 118 } |
112 | 125 |
113 int call_site_count = method()->scale_count(profile.count()); | 126 int call_site_count = method()->scale_count(profile.count()); |
114 int invoke_count = method()->interpreter_invocation_count(); | 127 int invoke_count = method()->interpreter_invocation_count(); |
115 assert( invoke_count != 0, "Require invokation count greater than zero"); | 128 assert( invoke_count != 0, "Require invokation count greater than zero"); |
116 int freq = call_site_count/invoke_count; | 129 int freq = call_site_count/invoke_count; |
130 | |
117 // bump the max size if the call is frequent | 131 // bump the max size if the call is frequent |
118 if ((freq >= InlineFrequencyRatio) || (call_site_count >= InlineFrequencyCount)) { | 132 if ((freq >= InlineFrequencyRatio) || |
133 (call_site_count >= InlineFrequencyCount) || | |
134 is_init_with_ea(callee_method, caller_method, C)) { | |
135 | |
119 max_size = C->freq_inline_size(); | 136 max_size = C->freq_inline_size(); |
120 if (size <= max_size && TraceFrequencyInlining) { | 137 if (size <= max_size && TraceFrequencyInlining) { |
121 print_indent(inline_depth()); | 138 print_indent(inline_depth()); |
122 tty->print_cr("Inlined frequent method (freq=%d count=%d):", freq, call_site_count); | 139 tty->print_cr("Inlined frequent method (freq=%d count=%d):", freq, call_site_count); |
123 print_indent(inline_depth()); | 140 print_indent(inline_depth()); |
124 callee_method->print(); | 141 callee_method->print(); |
125 tty->cr(); | 142 tty->cr(); |
126 } | 143 } |
127 } else { | 144 } else { |
128 // Not hot. Check for medium-sized pre-existing nmethod at cold sites. | 145 // Not hot. Check for medium-sized pre-existing nmethod at cold sites. |
129 if (callee_method->has_compiled_code() && callee_method->instructions_size() > InlineSmallCode/4) | 146 if (callee_method->has_compiled_code() && |
147 callee_method->instructions_size() > InlineSmallCode/4) | |
130 return "already compiled into a medium method"; | 148 return "already compiled into a medium method"; |
131 } | 149 } |
132 if (size > max_size) { | 150 if (size > max_size) { |
133 if (max_size > C->max_inline_size()) | 151 if (max_size > C->max_inline_size()) |
134 return "hot method too big"; | 152 return "hot method too big"; |
137 return NULL; | 155 return NULL; |
138 } | 156 } |
139 | 157 |
140 | 158 |
141 // negative filter: should send NOT be inlined? returns NULL, ok to inline, or rejection msg | 159 // negative filter: should send NOT be inlined? returns NULL, ok to inline, or rejection msg |
142 const char* InlineTree::shouldNotInline(ciMethod *callee_method, WarmCallInfo* wci_result) const { | 160 const char* InlineTree::shouldNotInline(ciMethod *callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const { |
143 // negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg | 161 // negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg |
144 if (!UseOldInlining) { | 162 if (!UseOldInlining) { |
145 const char* fail = NULL; | 163 const char* fail = NULL; |
146 if (callee_method->is_abstract()) fail = "abstract method"; | 164 if (callee_method->is_abstract()) fail = "abstract method"; |
147 // note: we allow ik->is_abstract() | 165 // note: we allow ik->is_abstract() |
202 return "exception method"; | 220 return "exception method"; |
203 } | 221 } |
204 | 222 |
205 // use frequency-based objections only for non-trivial methods | 223 // use frequency-based objections only for non-trivial methods |
206 if (callee_method->code_size() <= MaxTrivialSize) return NULL; | 224 if (callee_method->code_size() <= MaxTrivialSize) return NULL; |
207 if (UseInterpreter && !CompileTheWorld) { // don't use counts with -Xcomp or CTW | 225 |
208 if (!callee_method->has_compiled_code() && !callee_method->was_executed_more_than(0)) return "never executed"; | 226 // don't use counts with -Xcomp or CTW |
209 if (!callee_method->was_executed_more_than(MIN2(MinInliningThreshold, CompileThreshold >> 1))) return "executed < MinInliningThreshold times"; | 227 if (UseInterpreter && !CompileTheWorld) { |
228 | |
229 if (!callee_method->has_compiled_code() && | |
230 !callee_method->was_executed_more_than(0)) { | |
231 return "never executed"; | |
232 } | |
233 | |
234 if (is_init_with_ea(callee_method, caller_method, C)) { | |
235 | |
236 // Escape Analysis: inline all executed constructors | |
237 | |
238 } else if (!callee_method->was_executed_more_than(MIN2(MinInliningThreshold, | |
239 CompileThreshold >> 1))) { | |
240 return "executed < MinInliningThreshold times"; | |
241 } | |
210 } | 242 } |
211 | 243 |
212 if (callee_method->should_not_inline()) { | 244 if (callee_method->should_not_inline()) { |
213 return "disallowed by CompilerOracle"; | 245 return "disallowed by CompilerOracle"; |
214 } | 246 } |
217 } | 249 } |
218 | 250 |
219 //-----------------------------try_to_inline----------------------------------- | 251 //-----------------------------try_to_inline----------------------------------- |
220 // return NULL if ok, reason for not inlining otherwise | 252 // return NULL if ok, reason for not inlining otherwise |
221 // Relocated from "InliningClosure::try_to_inline" | 253 // Relocated from "InliningClosure::try_to_inline" |
222 const char* InlineTree::try_to_inline(ciMethod* callee_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) { | 254 const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) { |
223 ciMethod* caller_method = method(); | |
224 | 255 |
225 // Old algorithm had funny accumulating BC-size counters | 256 // Old algorithm had funny accumulating BC-size counters |
226 if (UseOldInlining && ClipInlining | 257 if (UseOldInlining && ClipInlining |
227 && (int)count_inline_bcs() >= DesiredMethodLimit) { | 258 && (int)count_inline_bcs() >= DesiredMethodLimit) { |
228 return "size > DesiredMethodLimit"; | 259 return "size > DesiredMethodLimit"; |
229 } | 260 } |
230 | 261 |
231 const char *msg = NULL; | 262 const char *msg = NULL; |
232 if ((msg = shouldInline(callee_method, caller_bci, profile, wci_result)) != NULL) return msg; | 263 if ((msg = shouldInline(callee_method, caller_method, caller_bci, |
233 if ((msg = shouldNotInline(callee_method, wci_result)) != NULL) return msg; | 264 profile, wci_result)) != NULL) { |
265 return msg; | |
266 } | |
267 if ((msg = shouldNotInline(callee_method, caller_method, | |
268 wci_result)) != NULL) { | |
269 return msg; | |
270 } | |
234 | 271 |
235 bool is_accessor = InlineAccessors && callee_method->is_accessor(); | 272 bool is_accessor = InlineAccessors && callee_method->is_accessor(); |
236 | 273 |
237 // suppress a few checks for accessors and trivial methods | 274 // suppress a few checks for accessors and trivial methods |
238 if (!is_accessor && callee_method->code_size() > MaxTrivialSize) { | 275 if (!is_accessor && callee_method->code_size() > MaxTrivialSize) { |
276 | |
239 // don't inline into giant methods | 277 // don't inline into giant methods |
240 if (C->unique() > (uint)NodeCountInliningCutoff) return "NodeCountInliningCutoff"; | 278 if (C->unique() > (uint)NodeCountInliningCutoff) { |
241 | 279 return "NodeCountInliningCutoff"; |
242 // don't inline unreached call sites | 280 } |
243 if (profile.count() == 0) return "call site not reached"; | 281 |
244 } | 282 if ((!UseInterpreter || CompileTheWorld) && |
245 | 283 is_init_with_ea(callee_method, caller_method, C)) { |
246 if (!C->do_inlining() && InlineAccessors && !is_accessor) return "not an accessor"; | 284 |
247 | 285 // Escape Analysis stress testing when running Xcomp or CTW: |
248 if( inline_depth() > MaxInlineLevel ) return "inlining too deep"; | 286 // inline constructors even if they are not reached. |
287 | |
288 } else if (profile.count() == 0) { | |
289 // don't inline unreached call sites | |
290 return "call site not reached"; | |
291 } | |
292 } | |
293 | |
294 if (!C->do_inlining() && InlineAccessors && !is_accessor) { | |
295 return "not an accessor"; | |
296 } | |
297 if( inline_depth() > MaxInlineLevel ) { | |
298 return "inlining too deep"; | |
299 } | |
249 if( method() == callee_method && | 300 if( method() == callee_method && |
250 inline_depth() > MaxRecursiveInlineLevel ) return "recursively inlining too deep"; | 301 inline_depth() > MaxRecursiveInlineLevel ) { |
302 return "recursively inlining too deep"; | |
303 } | |
251 | 304 |
252 int size = callee_method->code_size(); | 305 int size = callee_method->code_size(); |
253 | 306 |
254 if (UseOldInlining && ClipInlining | 307 if (UseOldInlining && ClipInlining |
255 && (int)count_inline_bcs() + size >= DesiredMethodLimit) { | 308 && (int)count_inline_bcs() + size >= DesiredMethodLimit) { |
334 return NULL; | 387 return NULL; |
335 } | 388 } |
336 | 389 |
337 // Check if inlining policy says no. | 390 // Check if inlining policy says no. |
338 WarmCallInfo wci = *(initial_wci); | 391 WarmCallInfo wci = *(initial_wci); |
339 failure_msg = try_to_inline(callee_method, caller_bci, profile, &wci); | 392 failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci); |
340 if (failure_msg != NULL && C->log() != NULL) { | 393 if (failure_msg != NULL && C->log() != NULL) { |
341 C->log()->begin_elem("inline_fail reason='"); | 394 C->log()->begin_elem("inline_fail reason='"); |
342 C->log()->text("%s", failure_msg); | 395 C->log()->text("%s", failure_msg); |
343 C->log()->end_elem("'"); | 396 C->log()->end_elem("'"); |
344 } | 397 } |