# HG changeset patch # User twisti # Date 1380938732 25200 # Node ID 5f1241525a01e447bf88c66e5a58f236b52e9669 # Parent 1e814e391ee8a3ff348635f2e3ddf3645c9cd31b# Parent 0c4c40f5c399ee59143ddf30f88759be7ea7c21b Merge diff -r 1e814e391ee8 -r 5f1241525a01 src/share/vm/opto/bytecodeInfo.cpp --- a/src/share/vm/opto/bytecodeInfo.cpp Fri Oct 04 09:19:13 2013 +0200 +++ b/src/share/vm/opto/bytecodeInfo.cpp Fri Oct 04 19:05:32 2013 -0700 @@ -197,6 +197,7 @@ // negative filter: should callee NOT be inlined? bool InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* caller_method, + JVMState* jvms, WarmCallInfo* wci_result) { const char* fail_msg = NULL; @@ -226,7 +227,7 @@ // don't inline exception code unless the top method belongs to an // exception class if (callee_method->holder()->is_subclass_of(C->env()->Throwable_klass())) { - ciMethod* top_method = caller_jvms() ? caller_jvms()->of_depth(1)->method() : method(); + ciMethod* top_method = jvms->caller() != NULL ? jvms->caller()->of_depth(1)->method() : method(); if (!top_method->holder()->is_subclass_of(C->env()->Throwable_klass())) { wci_result->set_profit(wci_result->profit() * 0.1); } @@ -328,7 +329,7 @@ // return true if ok // Relocated from "InliningClosure::try_to_inline" bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, - int caller_bci, ciCallProfile& profile, + int caller_bci, JVMState* jvms, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay) { // Old algorithm had funny accumulating BC-size counters @@ -346,7 +347,7 @@ wci_result)) { return false; } - if (should_not_inline(callee_method, caller_method, wci_result)) { + if (should_not_inline(callee_method, caller_method, jvms, wci_result)) { return false; } @@ -397,24 +398,35 @@ } // detect direct and indirect recursive inlining - if (!callee_method->is_compiled_lambda_form()) { + { // count the current method and the callee - int inline_level = (method() == callee_method) ? 1 : 0; - if (inline_level > MaxRecursiveInlineLevel) { - set_msg("recursively inlining too deep"); - return false; + const bool is_compiled_lambda_form = callee_method->is_compiled_lambda_form(); + int inline_level = 0; + if (!is_compiled_lambda_form) { + if (method() == callee_method) { + inline_level++; + } } // count callers of current method and callee - JVMState* jvms = caller_jvms(); - while (jvms != NULL && jvms->has_method()) { - if (jvms->method() == callee_method) { - inline_level++; - if (inline_level > MaxRecursiveInlineLevel) { - set_msg("recursively inlining too deep"); - return false; + Node* callee_argument0 = is_compiled_lambda_form ? jvms->map()->argument(jvms, 0)->uncast() : NULL; + for (JVMState* j = jvms->caller(); j != NULL && j->has_method(); j = j->caller()) { + if (j->method() == callee_method) { + if (is_compiled_lambda_form) { + // Since compiled lambda forms are heavily reused we allow recursive inlining. If it is truly + // a recursion (using the same "receiver") we limit inlining otherwise we can easily blow the + // compiler stack. + Node* caller_argument0 = j->map()->argument(j, 0)->uncast(); + if (caller_argument0 == callee_argument0) { + inline_level++; + } + } else { + inline_level++; } } - jvms = jvms->caller(); + } + if (inline_level > MaxRecursiveInlineLevel) { + set_msg("recursive inlining is too deep"); + return false; } } @@ -536,7 +548,7 @@ // Check if inlining policy says no. WarmCallInfo wci = *(initial_wci); bool success = try_to_inline(callee_method, caller_method, caller_bci, - profile, &wci, should_delay); + jvms, profile, &wci, should_delay); #ifndef PRODUCT if (UseOldInlining && InlineWarmCalls diff -r 1e814e391ee8 -r 5f1241525a01 src/share/vm/opto/parse.hpp --- a/src/share/vm/opto/parse.hpp Fri Oct 04 09:19:13 2013 +0200 +++ b/src/share/vm/opto/parse.hpp Fri Oct 04 19:05:32 2013 -0700 @@ -73,6 +73,7 @@ bool try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, + JVMState* jvms, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay); @@ -83,6 +84,7 @@ WarmCallInfo* wci_result); bool should_not_inline(ciMethod* callee_method, ciMethod* caller_method, + JVMState* jvms, WarmCallInfo* wci_result); void print_inlining(ciMethod* callee_method, int caller_bci, bool success) const;