1.1 --- a/src/share/vm/c1/c1_GraphBuilder.cpp Tue Jan 31 09:53:46 2012 -0800 1.2 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Wed Feb 01 10:36:58 2012 +0100 1.3 @@ -1592,6 +1592,7 @@ 1.4 // this happened while running the JCK invokevirtual tests under doit. TKR 1.5 ciMethod* cha_monomorphic_target = NULL; 1.6 ciMethod* exact_target = NULL; 1.7 + Value better_receiver = NULL; 1.8 if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded() && 1.9 !target->is_method_handle_invoke()) { 1.10 Value receiver = NULL; 1.11 @@ -1653,6 +1654,18 @@ 1.12 ciInstanceKlass* singleton = NULL; 1.13 if (target->holder()->nof_implementors() == 1) { 1.14 singleton = target->holder()->implementor(0); 1.15 + 1.16 + assert(holder->is_interface(), "invokeinterface to non interface?"); 1.17 + ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder; 1.18 + // the number of implementors for decl_interface is less or 1.19 + // equal to the number of implementors for target->holder() so 1.20 + // if number of implementors of target->holder() == 1 then 1.21 + // number of implementors for decl_interface is 0 or 1. If 1.22 + // it's 0 then no class implements decl_interface and there's 1.23 + // no point in inlining. 1.24 + if (!holder->is_loaded() || decl_interface->nof_implementors() != 1) { 1.25 + singleton = NULL; 1.26 + } 1.27 } 1.28 if (singleton) { 1.29 cha_monomorphic_target = target->find_monomorphic_target(calling_klass, target->holder(), singleton); 1.30 @@ -1667,7 +1680,9 @@ 1.31 CheckCast* c = new CheckCast(klass, receiver, copy_state_for_exception()); 1.32 c->set_incompatible_class_change_check(); 1.33 c->set_direct_compare(klass->is_final()); 1.34 - append_split(c); 1.35 + // pass the result of the checkcast so that the compiler has 1.36 + // more accurate type info in the inlinee 1.37 + better_receiver = append_split(c); 1.38 } 1.39 } 1.40 } 1.41 @@ -1709,7 +1724,7 @@ 1.42 } 1.43 if (!success) { 1.44 // static binding => check if callee is ok 1.45 - success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL)); 1.46 + success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL), better_receiver); 1.47 } 1.48 CHECK_BAILOUT(); 1.49 1.50 @@ -3034,7 +3049,7 @@ 1.51 } 1.52 1.53 1.54 -bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known) { 1.55 +bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Value receiver) { 1.56 // Clear out any existing inline bailout condition 1.57 clear_inline_bailout(); 1.58 1.59 @@ -3056,7 +3071,7 @@ 1.60 } else if (callee->is_abstract()) { 1.61 INLINE_BAILOUT("abstract") 1.62 } else { 1.63 - return try_inline_full(callee, holder_known); 1.64 + return try_inline_full(callee, holder_known, NULL, receiver); 1.65 } 1.66 } 1.67 1.68 @@ -3405,7 +3420,7 @@ 1.69 } 1.70 1.71 1.72 -bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBegin* cont_block) { 1.73 +bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBegin* cont_block, Value receiver) { 1.74 assert(!callee->is_native(), "callee must not be native"); 1.75 if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) { 1.76 INLINE_BAILOUT("inlining prohibited by policy"); 1.77 @@ -3541,6 +3556,9 @@ 1.78 Value arg = caller_state->stack_at_inc(i); 1.79 // NOTE: take base() of arg->type() to avoid problems storing 1.80 // constants 1.81 + if (receiver != NULL && par_no == 0) { 1.82 + arg = receiver; 1.83 + } 1.84 store_local(callee_state, arg, arg->type()->base(), par_no); 1.85 } 1.86 } 1.87 @@ -3720,7 +3738,7 @@ 1.88 1.89 // Parse first adapter 1.90 _last = _block = one; 1.91 - if (!try_inline_full(mh1_adapter, /*holder_known=*/ true, end)) { 1.92 + if (!try_inline_full(mh1_adapter, /*holder_known=*/ true, end, NULL)) { 1.93 restore_inline_cleanup_info(); 1.94 block()->clear_end(); // remove appended iff 1.95 return false; 1.96 @@ -3729,7 +3747,7 @@ 1.97 // Parse second adapter 1.98 _last = _block = two; 1.99 _state = state_before; 1.100 - if (!try_inline_full(mh2_adapter, /*holder_known=*/ true, end)) { 1.101 + if (!try_inline_full(mh2_adapter, /*holder_known=*/ true, end, NULL)) { 1.102 restore_inline_cleanup_info(); 1.103 block()->clear_end(); // remove appended iff 1.104 return false;