Mercurial > hg > truffle
diff src/share/vm/opto/doCall.cpp @ 13086:096c224171c4
Merge with http://hg.openjdk.java.net/hsx/hsx25/hotspot/
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 20 Nov 2013 00:10:38 +0100 |
parents | b2ee5dc63353 |
children | de6a9e811145 |
line wrap: on
line diff
--- a/src/share/vm/opto/doCall.cpp Tue Nov 19 17:44:26 2013 +0100 +++ b/src/share/vm/opto/doCall.cpp Wed Nov 20 00:10:38 2013 +0100 @@ -63,7 +63,8 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool call_does_dispatch, JVMState* jvms, bool allow_inline, - float prof_factor, bool allow_intrinsics, bool delayed_forbidden) { + float prof_factor, ciKlass* speculative_receiver_type, + bool allow_intrinsics, bool delayed_forbidden) { ciMethod* caller = jvms->method(); int bci = jvms->bci(); Bytecodes::Code bytecode = caller->java_code_at_bci(bci); @@ -117,7 +118,7 @@ if (cg->is_predicted()) { // Code without intrinsic but, hopefully, inlined. CallGenerator* inline_cg = this->call_generator(callee, - vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, false); + vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, speculative_receiver_type, false); if (inline_cg != NULL) { cg = CallGenerator::for_predicted_intrinsic(cg, inline_cg); } @@ -212,8 +213,24 @@ // The major receiver's count >= TypeProfileMajorReceiverPercent of site_count. bool have_major_receiver = (100.*profile.receiver_prob(0) >= (float)TypeProfileMajorReceiverPercent); ciMethod* receiver_method = NULL; - if (have_major_receiver || profile.morphism() == 1 || - (profile.morphism() == 2 && UseBimorphicInlining)) { + + int morphism = profile.morphism(); + if (speculative_receiver_type != NULL) { + // We have a speculative type, we should be able to resolve + // the call. We do that before looking at the profiling at + // this invoke because it may lead to bimorphic inlining which + // a speculative type should help us avoid. + receiver_method = callee->resolve_invoke(jvms->method()->holder(), + speculative_receiver_type); + if (receiver_method == NULL) { + speculative_receiver_type = NULL; + } else { + morphism = 1; + } + } + if (receiver_method == NULL && + (have_major_receiver || morphism == 1 || + (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(), @@ -227,7 +244,7 @@ // Look up second receiver. CallGenerator* next_hit_cg = NULL; ciMethod* next_receiver_method = NULL; - if (profile.morphism() == 2 && UseBimorphicInlining) { + if (morphism == 2 && UseBimorphicInlining) { next_receiver_method = callee->resolve_invoke(jvms->method()->holder(), profile.receiver(1)); if (next_receiver_method != NULL) { @@ -242,11 +259,10 @@ } } CallGenerator* miss_cg; - Deoptimization::DeoptReason reason = (profile.morphism() == 2) ? + Deoptimization::DeoptReason reason = morphism == 2 ? Deoptimization::Reason_bimorphic : Deoptimization::Reason_class_check; - if (( profile.morphism() == 1 || - (profile.morphism() == 2 && next_hit_cg != NULL) ) && + if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) && !too_many_traps(jvms->method(), jvms->bci(), reason) ) { // Generate uncommon trap for class check failure path @@ -260,6 +276,7 @@ } if (miss_cg != NULL) { 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)); // We don't need to record dependency on a receiver here and below. // Whenever we inline, the dependency is added by Parse::Parse(). @@ -267,7 +284,9 @@ } if (miss_cg != NULL) { trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), receiver_method, profile.receiver(0), site_count, receiver_count); - CallGenerator* cg = CallGenerator::for_predicted_call(profile.receiver(0), miss_cg, hit_cg, profile.receiver_prob(0)); + ciKlass* k = speculative_receiver_type != NULL ? speculative_receiver_type : profile.receiver(0); + float hit_prob = speculative_receiver_type != NULL ? 1.0 : profile.receiver_prob(0); + CallGenerator* cg = CallGenerator::for_predicted_call(k, miss_cg, hit_cg, hit_prob); if (cg != NULL) return cg; } } @@ -446,13 +465,16 @@ int vtable_index = Method::invalid_vtable_index; bool call_does_dispatch = false; + // Speculative type of the receiver if any + ciKlass* speculative_receiver_type = NULL; if (is_virtual_or_interface) { - Node* receiver_node = stack(sp() - nargs); + Node* receiver_node = stack(sp() - nargs); const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr(); // call_does_dispatch and vtable_index are out-parameters. They might be changed. callee = C->optimize_virtual_call(method(), bci(), klass, orig_callee, receiver_type, is_virtual, call_does_dispatch, vtable_index); // out-parameters + speculative_receiver_type = receiver_type != NULL ? receiver_type->speculative_type() : NULL; } // Note: It's OK to try to inline a virtual call. @@ -468,7 +490,7 @@ // Decide call tactic. // This call checks with CHA, the interpreter profile, intrinsics table, etc. // It decides whether inlining is desirable or not. - CallGenerator* cg = C->call_generator(callee, vtable_index, call_does_dispatch, jvms, try_inline, prof_factor()); + CallGenerator* cg = C->call_generator(callee, vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type); // NOTE: Don't use orig_callee and callee after this point! Use cg->method() instead. orig_callee = callee = NULL; @@ -477,6 +499,10 @@ // Round double arguments before call round_double_arguments(cg->method()); + // Feed profiling data for arguments to the type system so it can + // propagate it as speculative types + record_profiled_arguments_for_speculation(cg->method(), bc()); + #ifndef PRODUCT // bump global counters for calls count_compiled_calls(/*at_method_entry*/ false, cg->is_inline()); @@ -491,11 +517,18 @@ // save across call, for a subsequent cast_not_null. Node* receiver = has_receiver ? argument(0) : NULL; + // The extra CheckCastPP for speculative types mess with PhaseStringOpts + if (receiver != NULL && !call_does_dispatch && !cg->is_string_late_inline()) { + // Feed profiling data for a single receiver to the type system so + // it can propagate it as a speculative type + receiver = record_profiled_receiver_for_speculation(receiver); + } + // Bump method data counters (We profile *before* the call is made // because exceptions don't return to the call site.) profile_call(receiver); - JVMState* new_jvms = cg->generate(jvms); + JVMState* new_jvms = cg->generate(jvms, this); if (new_jvms == NULL) { // When inlining attempt fails (e.g., too many arguments), // it may contaminate the current compile state, making it @@ -508,8 +541,8 @@ // the call site, perhaps because it did not match a pattern the // intrinsic was expecting to optimize. Should always be possible to // get a normal java call that may inline in that case - cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), /* allow_intrinsics= */ false); - if ((new_jvms = cg->generate(jvms)) == NULL) { + cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type, /* allow_intrinsics= */ false); + if ((new_jvms = cg->generate(jvms, this)) == NULL) { guarantee(failing(), "call failed to generate: calls should work"); return; } @@ -607,6 +640,16 @@ null_assert(peek()); set_bci(iter().cur_bci()); // put it back } + BasicType ct = ctype->basic_type(); + if (ct == T_OBJECT || ct == T_ARRAY) { + ciKlass* better_type = method()->return_profiled_type(bci()); + if (UseTypeSpeculation && better_type != NULL) { + // If profiling reports a single type for the return value, + // feed it to the type system so it can propagate it as a + // speculative type + record_profile_for_speculation(stack(sp()-1), better_type); + } + } } // Restart record of parsing work after possible inlining of call