Mercurial > hg > truffle
comparison src/share/vm/opto/bytecodeInfo.cpp @ 2405:3d58a4983660
7022998: JSR 292 recursive method handle calls inline themselves infinitely
Reviewed-by: never, kvn
author | twisti |
---|---|
date | Mon, 28 Mar 2011 03:58:07 -0700 |
parents | 8033953d67ff |
children | b21ecca7ccc4 |
comparison
equal
deleted
inserted
replaced
2404:b40d4fa697bf | 2405:3d58a4983660 |
---|---|
23 */ | 23 */ |
24 | 24 |
25 #include "precompiled.hpp" | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | 26 #include "classfile/systemDictionary.hpp" |
27 #include "classfile/vmSymbols.hpp" | 27 #include "classfile/vmSymbols.hpp" |
28 #include "compiler/compileBroker.hpp" | |
28 #include "compiler/compileLog.hpp" | 29 #include "compiler/compileLog.hpp" |
29 #include "interpreter/linkResolver.hpp" | 30 #include "interpreter/linkResolver.hpp" |
30 #include "oops/objArrayKlass.hpp" | 31 #include "oops/objArrayKlass.hpp" |
31 #include "opto/callGenerator.hpp" | 32 #include "opto/callGenerator.hpp" |
32 #include "opto/parse.hpp" | 33 #include "opto/parse.hpp" |
73 { | 74 { |
74 NOT_PRODUCT(_count_inlines = 0;) | 75 NOT_PRODUCT(_count_inlines = 0;) |
75 assert(!UseOldInlining, "do not use for old stuff"); | 76 assert(!UseOldInlining, "do not use for old stuff"); |
76 } | 77 } |
77 | 78 |
78 | |
79 | |
80 static void print_indent(int depth) { | |
81 tty->print(" "); | |
82 for (int i = depth; i != 0; --i) tty->print(" "); | |
83 } | |
84 | |
85 static bool is_init_with_ea(ciMethod* callee_method, | 79 static bool is_init_with_ea(ciMethod* callee_method, |
86 ciMethod* caller_method, Compile* C) { | 80 ciMethod* caller_method, Compile* C) { |
87 // True when EA is ON and a java constructor is called or | 81 // True when EA is ON and a java constructor is called or |
88 // a super constructor is called from an inlined java constructor. | 82 // a super constructor is called from an inlined java constructor. |
89 return C->do_escape_analysis() && EliminateAllocations && | 83 return C->do_escape_analysis() && EliminateAllocations && |
98 const char* InlineTree::shouldInline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const { | 92 const char* InlineTree::shouldInline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const { |
99 // Allows targeted inlining | 93 // Allows targeted inlining |
100 if(callee_method->should_inline()) { | 94 if(callee_method->should_inline()) { |
101 *wci_result = *(WarmCallInfo::always_hot()); | 95 *wci_result = *(WarmCallInfo::always_hot()); |
102 if (PrintInlining && Verbose) { | 96 if (PrintInlining && Verbose) { |
103 print_indent(inline_depth()); | 97 CompileTask::print_inline_indent(inline_depth()); |
104 tty->print_cr("Inlined method is hot: "); | 98 tty->print_cr("Inlined method is hot: "); |
105 } | 99 } |
106 return NULL; | 100 return NULL; |
107 } | 101 } |
108 | 102 |
114 // Check for too many throws (and not too huge) | 108 // Check for too many throws (and not too huge) |
115 if(callee_method->interpreter_throwout_count() > InlineThrowCount && | 109 if(callee_method->interpreter_throwout_count() > InlineThrowCount && |
116 size < InlineThrowMaxSize ) { | 110 size < InlineThrowMaxSize ) { |
117 wci_result->set_profit(wci_result->profit() * 100); | 111 wci_result->set_profit(wci_result->profit() * 100); |
118 if (PrintInlining && Verbose) { | 112 if (PrintInlining && Verbose) { |
119 print_indent(inline_depth()); | 113 CompileTask::print_inline_indent(inline_depth()); |
120 tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count()); | 114 tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count()); |
121 } | 115 } |
122 return NULL; | 116 return NULL; |
123 } | 117 } |
124 | 118 |
136 (call_site_count >= InlineFrequencyCount) || | 130 (call_site_count >= InlineFrequencyCount) || |
137 is_init_with_ea(callee_method, caller_method, C)) { | 131 is_init_with_ea(callee_method, caller_method, C)) { |
138 | 132 |
139 max_size = C->freq_inline_size(); | 133 max_size = C->freq_inline_size(); |
140 if (size <= max_size && TraceFrequencyInlining) { | 134 if (size <= max_size && TraceFrequencyInlining) { |
141 print_indent(inline_depth()); | 135 CompileTask::print_inline_indent(inline_depth()); |
142 tty->print_cr("Inlined frequent method (freq=%d count=%d):", freq, call_site_count); | 136 tty->print_cr("Inlined frequent method (freq=%d count=%d):", freq, call_site_count); |
143 print_indent(inline_depth()); | 137 CompileTask::print_inline_indent(inline_depth()); |
144 callee_method->print(); | 138 callee_method->print(); |
145 tty->cr(); | 139 tty->cr(); |
146 } | 140 } |
147 } else { | 141 } else { |
148 // Not hot. Check for medium-sized pre-existing nmethod at cold sites. | 142 // Not hot. Check for medium-sized pre-existing nmethod at cold sites. |
313 return "not an accessor"; | 307 return "not an accessor"; |
314 } | 308 } |
315 if( inline_depth() > MaxInlineLevel ) { | 309 if( inline_depth() > MaxInlineLevel ) { |
316 return "inlining too deep"; | 310 return "inlining too deep"; |
317 } | 311 } |
318 if( method() == callee_method && | 312 |
319 inline_depth() > MaxRecursiveInlineLevel ) { | 313 // We need to detect recursive inlining of method handle targets: if |
314 // the current method is a method handle adapter and one of the | |
315 // callers is the same method as the callee, we bail out if | |
316 // MaxRecursiveInlineLevel is hit. | |
317 if (method()->is_method_handle_adapter()) { | |
318 JVMState* jvms = caller_jvms(); | |
319 int inline_level = 0; | |
320 while (jvms != NULL && jvms->has_method()) { | |
321 if (jvms->method() == callee_method) { | |
322 inline_level++; | |
323 if (inline_level > MaxRecursiveInlineLevel) | |
324 return "recursively inlining too deep"; | |
325 } | |
326 jvms = jvms->caller(); | |
327 } | |
328 } | |
329 | |
330 if (method() == callee_method && inline_depth() > MaxRecursiveInlineLevel) { | |
320 return "recursively inlining too deep"; | 331 return "recursively inlining too deep"; |
321 } | 332 } |
322 | 333 |
323 int size = callee_method->code_size(); | 334 int size = callee_method->code_size(); |
324 | 335 |
366 } | 377 } |
367 | 378 |
368 #ifndef PRODUCT | 379 #ifndef PRODUCT |
369 //------------------------------print_inlining--------------------------------- | 380 //------------------------------print_inlining--------------------------------- |
370 // Really, the failure_msg can be a success message also. | 381 // Really, the failure_msg can be a success message also. |
371 void InlineTree::print_inlining(ciMethod *callee_method, int caller_bci, const char *failure_msg) const { | 382 void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const { |
372 print_indent(inline_depth()); | 383 CompileTask::print_inlining(callee_method, inline_depth(), caller_bci, failure_msg ? failure_msg : "inline"); |
373 tty->print("@ %d ", caller_bci); | 384 if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); |
374 if( callee_method ) callee_method->print_short_name(); | 385 if (Verbose && callee_method) { |
375 else tty->print(" callee not monotonic or profiled"); | |
376 tty->print(" %s", (failure_msg ? failure_msg : "inline")); | |
377 if( Verbose && callee_method ) { | |
378 const InlineTree *top = this; | 386 const InlineTree *top = this; |
379 while( top->caller_tree() != NULL ) { top = top->caller_tree(); } | 387 while( top->caller_tree() != NULL ) { top = top->caller_tree(); } |
380 tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); | 388 tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); |
381 } | 389 } |
382 tty->cr(); | |
383 } | 390 } |
384 #endif | 391 #endif |
385 | 392 |
386 //------------------------------ok_to_inline----------------------------------- | 393 //------------------------------ok_to_inline----------------------------------- |
387 WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, ciCallProfile& profile, WarmCallInfo* initial_wci) { | 394 WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, ciCallProfile& profile, WarmCallInfo* initial_wci) { |