diff --git a/src/hotspot/share/ci/ciCallProfile.hpp b/src/hotspot/share/ci/ciCallProfile.hpp index 081014954db..55dd5303405 100644 --- a/src/hotspot/share/ci/ciCallProfile.hpp +++ b/src/hotspot/share/ci/ciCallProfile.hpp @@ -38,7 +38,7 @@ class ciCallProfile : StackObj { friend class ciMethod; friend class ciMethodHandle; - enum { MorphismLimit = 2 }; // Max call site's morphism we care about + enum { MorphismLimit = 8 }; // Max call site's morphism we care about int _limit; // number of receivers have been determined int _morphism; // determined call site's morphism int _count; // # times has this call been executed diff --git a/src/hotspot/share/ci/ciMethod.cpp b/src/hotspot/share/ci/ciMethod.cpp index b7f82ec09b5..f0ee597ea34 100644 --- a/src/hotspot/share/ci/ciMethod.cpp +++ b/src/hotspot/share/ci/ciMethod.cpp @@ -348,6 +348,12 @@ bool ciMethod::has_balanced_monitors() { } +/* +char* ciMethod::get_name() { + name()-> +} +*/ + // ------------------------------------------------------------------ // ciMethod::get_flow_analysis ciTypeFlow* ciMethod::get_flow_analysis() { @@ -468,7 +474,7 @@ const BitMap& ciMethod::bci_block_start() { ciCallProfile ciMethod::call_profile_at_bci(int bci) { ResourceMark rm; ciCallProfile result; - if (method_data() != NULL && method_data()->is_mature()) { + if (method_data() != NULL && (method_data()->is_mature() || PolymorphicInlining)) { ciProfileData* data = method_data()->bci_to_data(bci); if (data != NULL && data->is_CounterData()) { // Every profiled call site has a counter. @@ -515,8 +521,8 @@ ciCallProfile ciMethod::call_profile_at_bci(int bci) { // The call site count is > 0 in the case of a polymorphic virtual call. if (morphism > 0 && morphism == result._limit) { // The morphism <= MorphismLimit. - if ((morphism < ciCallProfile::MorphismLimit) || - (morphism == ciCallProfile::MorphismLimit && count == 0)) { + if ((morphism == 1) || + (morphism <= ciCallProfile::MorphismLimit && count == 0)) { #ifdef ASSERT if (count > 0) { this->print_short_name(tty); diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 7aaa2337248..27bed36fee1 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1678,9 +1678,9 @@ void CodeCache::print_summary(outputStream* st, bool detailed) { } if (detailed) { - st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT + st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT " nonprofiled nmethods=" UINT32_FORMAT " adapters=" UINT32_FORMAT, - blob_count(), nmethod_count(), adapter_count()); + blob_count(), nmethod_count(), nmethod_count(CodeBlobType::MethodNonProfiled), adapter_count()); st->print_cr(" compilation: %s", CompileBroker::should_compile_new_jobs() ? "enabled" : Arguments::mode() == Arguments::_int ? "disabled (interpreter mode)" : diff --git a/src/hotspot/share/opto/bytecodeInfo.cpp b/src/hotspot/share/opto/bytecodeInfo.cpp index c0026cf6932..11e3e11f116 100644 --- a/src/hotspot/share/opto/bytecodeInfo.cpp +++ b/src/hotspot/share/opto/bytecodeInfo.cpp @@ -114,7 +114,7 @@ static bool is_unboxing_method(ciMethod* callee_method, Compile* C) { // positive filter: should callee be inlined? bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, - WarmCallInfo* wci_result) { + WarmCallInfo* wci_result, int receiver_index) { // Allows targeted inlining if (C->directive()->should_inline(callee_method)) { *wci_result = *(WarmCallInfo::always_hot()); @@ -166,6 +166,11 @@ bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, assert(invoke_count != 0, "require invocation count greater than zero"); double freq = (double)call_site_count / (double)invoke_count; + if (InlineFreqOnReceiver && receiver_index != -1) { + guarantee(profile.has_receiver(receiver_index), "sanity"); + freq = freq * profile.receiver_prob(receiver_index); + } + // bump the max size if the call is frequent if ((freq >= InlineFrequencyRatio) || is_unboxing_method(callee_method, C) || @@ -332,7 +337,7 @@ bool InlineTree::should_not_inline(ciMethod *callee_method, // Relocated from "InliningClosure::try_to_inline" bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, JVMState* jvms, ciCallProfile& profile, - WarmCallInfo* wci_result, bool& should_delay) { + WarmCallInfo* wci_result, bool& should_delay, int receiver_index) { if (ClipInlining && (int)count_inline_bcs() >= DesiredMethodLimit) { if (!callee_method->force_inline() || !IncrementalInline) { @@ -345,7 +350,7 @@ bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, _forced_inline = false; // Reset if (!should_inline(callee_method, caller_method, caller_bci, profile, - wci_result)) { + wci_result, receiver_index)) { return false; } if (should_not_inline(callee_method, caller_method, jvms, wci_result)) { @@ -543,7 +548,7 @@ void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, } //------------------------------ok_to_inline----------------------------------- -WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, ciCallProfile& profile, WarmCallInfo* initial_wci, bool& should_delay) { +WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, ciCallProfile& profile, WarmCallInfo* initial_wci, bool& should_delay, int receiver_index) { assert(callee_method != NULL, "caller checks for optimized virtual!"); assert(!should_delay, "should be initialized to false"); #ifdef ASSERT @@ -576,7 +581,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, // Check if inlining policy says no. WarmCallInfo wci = *(initial_wci); bool success = try_to_inline(callee_method, caller_method, caller_bci, - jvms, profile, &wci, should_delay); + jvms, profile, &wci, should_delay, receiver_index); #ifndef PRODUCT if (InlineWarmCalls && (PrintOpto || C->print_inlining())) { diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index fd2ffb932b4..7560abeed0c 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -423,7 +423,7 @@ \ /* controls for heat-based inlining */ \ \ - develop(intx, NodeCountInliningCutoff, 18000, \ + product (intx, NodeCountInliningCutoff, 18000, \ "If parser node generation exceeds limit stop inlining") \ range(0, max_jint) \ \ diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index efa10d29fcc..50575496c74 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -1043,7 +1043,7 @@ class Compile : public Phase { // The profile factor is a discount to apply to this site's interp. profile. CallGenerator* call_generator(ciMethod* call_method, int vtable_index, bool call_does_dispatch, JVMState* jvms, bool allow_inline, float profile_factor, ciKlass* speculative_receiver_type = NULL, - bool allow_intrinsics = true, bool delayed_forbidden = false); + bool allow_intrinsics = true, bool delayed_forbidden = false, int receiver_index = -1); bool should_delay_inlining(ciMethod* call_method, JVMState* jvms) { return should_delay_string_inlining(call_method, jvms) || should_delay_boxing_inlining(call_method, jvms) || diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp index 9031251107d..815c03ac4a2 100644 --- a/src/hotspot/share/opto/doCall.cpp +++ b/src/hotspot/share/opto/doCall.cpp @@ -33,6 +33,7 @@ #include "opto/callGenerator.hpp" #include "opto/castnode.hpp" #include "opto/cfgnode.hpp" +#include "opto/library_call.hpp" #include "opto/mulnode.hpp" #include "opto/parse.hpp" #include "opto/rootnode.hpp" @@ -65,7 +66,7 @@ void trace_type_profile(Compile* C, ciMethod *method, int depth, int bci, ciMeth CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool call_does_dispatch, JVMState* jvms, bool allow_inline, float prof_factor, ciKlass* speculative_receiver_type, - bool allow_intrinsics, bool delayed_forbidden) { + bool allow_intrinsics, bool delayed_forbidden, int receiver_index) { ciMethod* caller = jvms->method(); int bci = jvms->bci(); Bytecodes::Code bytecode = caller->java_code_at_bci(bci); @@ -170,7 +171,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool InlineTree* ilt = InlineTree::find_subtree_from_root(this->ilt(), jvms->caller(), jvms->method()); WarmCallInfo scratch_ci; bool should_delay = false; - WarmCallInfo* ci = ilt->ok_to_inline(callee, jvms, profile, &scratch_ci, should_delay); + WarmCallInfo* ci = ilt->ok_to_inline(callee, jvms, profile, &scratch_ci, should_delay, receiver_index); assert(ci != &scratch_ci, "do not let this pointer escape"); bool allow_inline = (ci != NULL && !ci->is_cold()); bool require_inline = (allow_inline && ci->is_hot()); @@ -209,9 +210,11 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool if (call_does_dispatch && site_count > 0 && UseTypeProfile) { // The major receiver's count >= TypeProfileMajorReceiverPercent of site_count. bool have_major_receiver = profile.has_receiver(0) && (100.*profile.receiver_prob(0) >= (float)TypeProfileMajorReceiverPercent); + ciMethod* receiver_method = NULL; int morphism = profile.morphism(); + if (speculative_receiver_type != NULL) { if (!too_many_traps_or_recompiles(caller, bci, Deoptimization::Reason_speculate_class_check)) { // We have a speculative type, we should be able to resolve @@ -231,23 +234,76 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool speculative_receiver_type = NULL; } } + + bool inline0 = false; + bool inline1 = false; + bool devirtual0 = false; + bool devirtual1 = false; + bool devirtual2 = false; + bool devirtual3 = false; + bool devirtual4 = false; + bool devirtual5 = false; + bool devirtual6 = false; + bool devirtual7 = false; + if (PolymorphicInlining && morphism != 1) { + double site_ratio = (double)caller->scale_count(site_count)/ caller->interpreter_invocation_count(); + if (site_ratio >= PolymorphicCallSiteRatio) { + inline0 = profile.has_receiver(0) && profile.receiver_prob(0) > PolymorphicRecv0InlineRatio; + inline1 = profile.has_receiver(1) && profile.receiver_prob(1) > PolymorphicRecv1InlineRatio; + if (morphism >= 2) { + devirtual0 = true; + devirtual1 = true; + } + if (morphism >= 3) { devirtual2 = true; } + if (morphism >= 4) { devirtual3 = true; } + if (morphism >= 5) { devirtual4 = true; } + if (morphism >= 6) { devirtual5 = true; } + if (morphism >= 7) { devirtual6 = true; } + if (morphism >= 8) { devirtual7 = true; } + + if (morphism == 0) { + devirtual0 = profile.has_receiver(0) && profile.receiver_prob(0) > PolymorphicDevirtualizeRatio; + devirtual1 = profile.has_receiver(1) && profile.receiver_prob(1) > PolymorphicDevirtualizeRatio; + devirtual2 = profile.has_receiver(2) && profile.receiver_prob(2) > PolymorphicDevirtualizeRatio; + devirtual3 = profile.has_receiver(3) && profile.receiver_prob(3) > PolymorphicDevirtualizeRatio; + devirtual4 = profile.has_receiver(4) && profile.receiver_prob(4) > PolymorphicDevirtualizeRatio; + devirtual5 = profile.has_receiver(5) && profile.receiver_prob(5) > PolymorphicDevirtualizeRatio; + devirtual6 = profile.has_receiver(6) && profile.receiver_prob(6) > PolymorphicDevirtualizeRatio; + devirtual7 = profile.has_receiver(7) && profile.receiver_prob(7) > PolymorphicDevirtualizeRatio; + } + inline0 = (have_major_receiver || morphism == 2); + } + } + if (receiver_method == NULL && - (have_major_receiver || morphism == 1 || + (have_major_receiver || morphism == 1 || inline0 || devirtual0 || (morphism == 2 && UseBimorphicInlining))) { // receiver_method = profile.method(); // Profiles do not suggest methods now. Look it up in the major receiver. receiver_method = callee->resolve_invoke(jvms->method()->holder(), profile.receiver(0)); } - if (receiver_method != NULL) { + + if (receiver_method != NULL && !(receiver_method->is_native() && cg_intrinsic)) { // The single majority receiver sufficiently outweighs the minority. CallGenerator* hit_cg = this->call_generator(receiver_method, - vtable_index, !call_does_dispatch, jvms, allow_inline, prof_factor); + vtable_index, !call_does_dispatch, jvms, allow_inline && !(!inline0 && devirtual0), prof_factor, + NULL, true, false, -1); if (hit_cg != NULL) { // Look up second receiver. CallGenerator* next_hit_cg = NULL; ciMethod* next_receiver_method = NULL; - if (morphism == 2 && UseBimorphicInlining) { + + if (inline1 || devirtual1) { + next_receiver_method = callee->resolve_invoke(jvms->method()->holder(), + profile.receiver(1)); + if (next_receiver_method != NULL && !(next_receiver_method->is_native() && cg_intrinsic)) { + next_hit_cg = this->call_generator(next_receiver_method, + vtable_index, !call_does_dispatch, jvms, + allow_inline && inline1, prof_factor, + NULL, true, false, 1); + } + } else if (morphism == 2 && UseBimorphicInlining) { next_receiver_method = callee->resolve_invoke(jvms->method()->holder(), profile.receiver(1)); if (next_receiver_method != NULL) { @@ -261,11 +317,101 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool } } } + CallGenerator* hit_cg2 = NULL; + ciMethod* receiver_method2 = NULL; + if (devirtual2) { + receiver_method2 = callee->resolve_invoke(jvms->method()->holder(), + profile.receiver(2)); + if (receiver_method2 != NULL && !(receiver_method2->is_native() && cg_intrinsic)) { + hit_cg2 = this->call_generator(receiver_method2, + vtable_index, !call_does_dispatch, jvms, + false, prof_factor, + NULL, true, false, 2); + } + } + + CallGenerator* hit_cg3 = NULL; + ciMethod* receiver_method3 = NULL; + if (devirtual3) { + receiver_method3 = callee->resolve_invoke(jvms->method()->holder(), + profile.receiver(3)); + if (receiver_method3 != NULL && !(receiver_method3->is_native() && cg_intrinsic)) { + hit_cg3 = this->call_generator(receiver_method3, + vtable_index, !call_does_dispatch, jvms, + false, prof_factor, + NULL, true, false, 3); + } + } + CallGenerator* hit_cg4 = NULL; + ciMethod* receiver_method4 = NULL; + if (devirtual4) { + receiver_method4 = callee->resolve_invoke(jvms->method()->holder(), + profile.receiver(4)); + if (receiver_method4 != NULL && !(receiver_method4->is_native() && cg_intrinsic)) { + hit_cg4 = this->call_generator(receiver_method4, + vtable_index, !call_does_dispatch, jvms, + false, prof_factor, + NULL, true, false, 4); + } + } + CallGenerator* hit_cg5 = NULL; + ciMethod* receiver_method5 = NULL; + if (devirtual5) { + receiver_method5 = callee->resolve_invoke(jvms->method()->holder(), + profile.receiver(5)); + if (receiver_method5 != NULL && !(receiver_method5->is_native() && cg_intrinsic)) { + hit_cg5 = this->call_generator(receiver_method5, + vtable_index, !call_does_dispatch, jvms, + false, prof_factor, + NULL, true, false, 5); + } + } + CallGenerator* hit_cg6 = NULL; + ciMethod* receiver_method6 = NULL; + if (devirtual6) { + receiver_method6 = callee->resolve_invoke(jvms->method()->holder(), + profile.receiver(6)); + if (receiver_method6 != NULL && !(receiver_method6 != NULL && cg_intrinsic)) { + hit_cg6 = this->call_generator(receiver_method6, + vtable_index, !call_does_dispatch, jvms, + false, prof_factor, + NULL, true, false, 6); + } + } + CallGenerator* hit_cg7 = NULL; + ciMethod* receiver_method7 = NULL; + if (devirtual7) { + receiver_method7 = callee->resolve_invoke(jvms->method()->holder(), + profile.receiver(7)); + if (receiver_method7 != NULL && !(receiver_method7 != NULL && cg_intrinsic)) { + hit_cg7 = this->call_generator(receiver_method7, + vtable_index, !call_does_dispatch, jvms, + false, prof_factor, + NULL, true, false, 7); + } + } CallGenerator* miss_cg; Deoptimization::DeoptReason reason = (morphism == 2 ? Deoptimization::Reason_bimorphic : Deoptimization::reason_class_check(speculative_receiver_type != NULL)); - if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) && + bool polymorphic_recompile = false; + if (PolymorphicInlining) { + if (morphism == 3 && next_hit_cg != NULL && hit_cg2 != NULL) { + polymorphic_recompile = true; + } else if (morphism == 4 && next_hit_cg != NULL && hit_cg2 != NULL && hit_cg3 != NULL) { + polymorphic_recompile = true; + } else if (morphism == 5 && next_hit_cg != NULL && hit_cg2 != NULL && hit_cg3 != NULL && hit_cg4 != NULL) { + polymorphic_recompile = true; + } else if (morphism == 6 && next_hit_cg != NULL && hit_cg2 != NULL && hit_cg3 != NULL && hit_cg4 != NULL && hit_cg5 != NULL) { + polymorphic_recompile = true; + } else if (morphism == 7 && next_hit_cg != NULL && hit_cg2 != NULL && hit_cg3 != NULL && hit_cg4 != NULL && hit_cg5 != NULL && hit_cg6 != NULL) { + polymorphic_recompile = true; + } else if (morphism == 8 && next_hit_cg != NULL && hit_cg2 != NULL && hit_cg3 != NULL && hit_cg4 != NULL && hit_cg5 != NULL && hit_cg6 != NULL && hit_cg7 != NULL) { + polymorphic_recompile = true; + } + } + + if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL) || polymorphic_recompile) && !too_many_traps_or_recompiles(caller, bci, reason) ) { // Generate uncommon trap for class check failure path @@ -275,9 +421,59 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool } else { // Generate virtual call for class check failure path // in case of polymorphic virtual call site. - miss_cg = CallGenerator::for_virtual_call(callee, vtable_index); + if (PolymorphicInlining && cg_intrinsic != NULL) { + miss_cg = cg_intrinsic; + } else { + miss_cg = CallGenerator::for_virtual_call(callee, vtable_index); + } } if (miss_cg != NULL) { + if (hit_cg7 != NULL) { + assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation"); + trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(7), site_count, profile.receiver_count(7)); + // We don't need to record dependency on a receiver here and below. + // Whenever we inline, the dependency is added by Parse::Parse(). + miss_cg = CallGenerator::for_predicted_call(profile.receiver(7), miss_cg, hit_cg7, PROB_MAX); + } + if (hit_cg6 != NULL) { + assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation"); + trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(6), site_count, profile.receiver_count(6)); + // We don't need to record dependency on a receiver here and below. + // Whenever we inline, the dependency is added by Parse::Parse(). + miss_cg = CallGenerator::for_predicted_call(profile.receiver(6), miss_cg, hit_cg6, PROB_MAX); + } + + if (hit_cg5 != NULL) { + assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation"); + trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(5), site_count, profile.receiver_count(5)); + // We don't need to record dependency on a receiver here and below. + // Whenever we inline, the dependency is added by Parse::Parse(). + miss_cg = CallGenerator::for_predicted_call(profile.receiver(5), miss_cg, hit_cg5, PROB_MAX); + } + if (hit_cg4 != NULL) { + assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation"); + trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(4), site_count, profile.receiver_count(4)); + // We don't need to record dependency on a receiver here and below. + // Whenever we inline, the dependency is added by Parse::Parse(). + miss_cg = CallGenerator::for_predicted_call(profile.receiver(4), miss_cg, hit_cg4, PROB_MAX); + } + + if (hit_cg3 != NULL) { + assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation"); + trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(3), site_count, profile.receiver_count(3)); + // We don't need to record dependency on a receiver here and below. + // Whenever we inline, the dependency is added by Parse::Parse(). + miss_cg = CallGenerator::for_predicted_call(profile.receiver(3), miss_cg, hit_cg3, PROB_MAX); + } + + if (hit_cg2 != NULL) { + assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation"); + trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(2), site_count, profile.receiver_count(2)); + // We don't need to record dependency on a receiver here and below. + // Whenever we inline, the dependency is added by Parse::Parse(). + miss_cg = CallGenerator::for_predicted_call(profile.receiver(2), miss_cg, hit_cg2, PROB_MAX); + } + if (next_hit_cg != NULL) { assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation"); trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(1), site_count, profile.receiver_count(1)); @@ -359,6 +555,9 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool const char* msg = "virtual call"; if (C->print_inlining()) { print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg); + if (!profile.has_receiver(0)) { + print_inlining(callee, jvms->depth() - 1, jvms->bci(), "no receiver"); + } } C->log_inline_failure(msg); return CallGenerator::for_virtual_call(callee, vtable_index); diff --git a/src/hotspot/share/opto/parse.hpp b/src/hotspot/share/opto/parse.hpp index aa13e886337..3ccf5170ef9 100644 --- a/src/hotspot/share/opto/parse.hpp +++ b/src/hotspot/share/opto/parse.hpp @@ -78,12 +78,12 @@ class InlineTree : public ResourceObj { JVMState* jvms, ciCallProfile& profile, WarmCallInfo* wci_result, - bool& should_delay); + bool& should_delay, int receiver_index); bool should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, - WarmCallInfo* wci_result); + WarmCallInfo* wci_result, int receiver_index); bool should_not_inline(ciMethod* callee_method, ciMethod* caller_method, JVMState* jvms, @@ -117,7 +117,7 @@ class InlineTree : public ResourceObj { // and may be accessed by find_subtree_from_root. // The call_method is the dest_method for a special or static invocation. // The call_method is an optimized virtual method candidate otherwise. - WarmCallInfo* ok_to_inline(ciMethod *call_method, JVMState* caller_jvms, ciCallProfile& profile, WarmCallInfo* wci, bool& should_delay); + WarmCallInfo* ok_to_inline(ciMethod *call_method, JVMState* caller_jvms, ciCallProfile& profile, WarmCallInfo* wci, bool& should_delay, int receiver_index); // Information about inlined method JVMState* caller_jvms() const { return _caller_jvms; } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 42ba54439c7..d7e86e998b1 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1764,7 +1764,7 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G); "allocate (for testing only)") \ range(0, max_uintx) \ \ - product(intx, TypeProfileWidth, 2, \ + product(intx, TypeProfileWidth, 8, \ "Number of receiver types to record in call/cast profile") \ range(0, 8) \ \ @@ -1795,7 +1795,7 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G); experimental(intx, SpecTrapLimitExtraEntries, 3, \ "Extra method data trap entries for speculation") \ \ - develop(double, InlineFrequencyRatio, 0.25, \ + product(double, InlineFrequencyRatio, 0.25, \ "Ratio of call site execution to caller method invocation") \ range(0.0, DBL_MAX) \ \ diff --git a/src/hotspot/share/runtime/globals_ext.hpp b/src/hotspot/share/runtime/globals_ext.hpp index 1a54881c4f5..3559ce82ccf 100644 --- a/src/hotspot/share/runtime/globals_ext.hpp +++ b/src/hotspot/share/runtime/globals_ext.hpp @@ -96,6 +96,24 @@ product(bool, UseBigDecimalOpt, true, \ "use binary search in zero stripping of BigDecimal") \ \ + product(bool, InlineFreqOnReceiver, false, \ + "Verify classpath order between the dump phase and replay phase") \ + \ + product(bool, PolymorphicInlining, true, \ + "Inline caching multiple type of receivers") \ + \ + product(double, PolymorphicCallSiteRatio, 0.0, \ + "Call site calling ratio for polymorphic inline ") \ + \ + product(double, PolymorphicRecv0InlineRatio, 0.15, \ + "Receiver calling ratio for polymorphic inline ") \ + \ + product(double, PolymorphicRecv1InlineRatio, 0.35, \ + "Receiver calling ratio for polymorphic inline ") \ + \ + product(double, PolymorphicDevirtualizeRatio, 0.15, \ + "Receiver calling ratio for polymorphic inline ") \ + \ //add new AJDK specific flags here