1.1 --- a/src/share/vm/opto/callGenerator.cpp Fri Dec 21 10:27:49 2012 -0800 1.2 +++ b/src/share/vm/opto/callGenerator.cpp Sun Dec 23 17:08:22 2012 +0100 1.3 @@ -262,8 +262,11 @@ 1.4 1.5 // Allow inlining decisions to be delayed 1.6 class LateInlineCallGenerator : public DirectCallGenerator { 1.7 + protected: 1.8 CallGenerator* _inline_cg; 1.9 1.10 + virtual bool do_late_inline_check(JVMState* jvms) { return true; } 1.11 + 1.12 public: 1.13 LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) : 1.14 DirectCallGenerator(method, true), _inline_cg(inline_cg) {} 1.15 @@ -279,7 +282,9 @@ 1.16 1.17 // Record that this call site should be revisited once the main 1.18 // parse is finished. 1.19 - Compile::current()->add_late_inline(this); 1.20 + if (!is_mh_late_inline()) { 1.21 + C->add_late_inline(this); 1.22 + } 1.23 1.24 // Emit the CallStaticJava and request separate projections so 1.25 // that the late inlining logic can distinguish between fall 1.26 @@ -287,15 +292,34 @@ 1.27 // as is done for allocations and macro expansion. 1.28 return DirectCallGenerator::generate(jvms); 1.29 } 1.30 + 1.31 + virtual void print_inlining_late(const char* msg) { 1.32 + CallNode* call = call_node(); 1.33 + Compile* C = Compile::current(); 1.34 + C->print_inlining_insert(this); 1.35 + C->print_inlining(method(), call->jvms()->depth()-1, call->jvms()->bci(), msg); 1.36 + } 1.37 + 1.38 }; 1.39 1.40 - 1.41 void LateInlineCallGenerator::do_late_inline() { 1.42 // Can't inline it 1.43 if (call_node() == NULL || call_node()->outcnt() == 0 || 1.44 call_node()->in(0) == NULL || call_node()->in(0)->is_top()) 1.45 return; 1.46 1.47 + for (int i1 = 0; i1 < method()->arg_size(); i1++) { 1.48 + if (call_node()->in(TypeFunc::Parms + i1)->is_top()) { 1.49 + assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); 1.50 + return; 1.51 + } 1.52 + } 1.53 + 1.54 + if (call_node()->in(TypeFunc::Memory)->is_top()) { 1.55 + assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); 1.56 + return; 1.57 + } 1.58 + 1.59 CallStaticJavaNode* call = call_node(); 1.60 1.61 // Make a clone of the JVMState that appropriate to use for driving a parse 1.62 @@ -324,6 +348,11 @@ 1.63 } 1.64 } 1.65 1.66 + if (!do_late_inline_check(jvms)) { 1.67 + map->disconnect_inputs(NULL, C); 1.68 + return; 1.69 + } 1.70 + 1.71 C->print_inlining_insert(this); 1.72 1.73 CompileLog* log = C->log(); 1.74 @@ -360,6 +389,10 @@ 1.75 result = (result_size == 1) ? kit.pop() : kit.pop_pair(); 1.76 } 1.77 1.78 + C->set_has_loops(C->has_loops() || _inline_cg->method()->has_loops()); 1.79 + C->env()->notice_inlined_method(_inline_cg->method()); 1.80 + C->set_inlining_progress(true); 1.81 + 1.82 kit.replace_call(call, result); 1.83 } 1.84 1.85 @@ -368,6 +401,83 @@ 1.86 return new LateInlineCallGenerator(method, inline_cg); 1.87 } 1.88 1.89 +class LateInlineMHCallGenerator : public LateInlineCallGenerator { 1.90 + ciMethod* _caller; 1.91 + int _attempt; 1.92 + bool _input_not_const; 1.93 + 1.94 + virtual bool do_late_inline_check(JVMState* jvms); 1.95 + virtual bool already_attempted() const { return _attempt > 0; } 1.96 + 1.97 + public: 1.98 + LateInlineMHCallGenerator(ciMethod* caller, ciMethod* callee, bool input_not_const) : 1.99 + LateInlineCallGenerator(callee, NULL), _caller(caller), _attempt(0), _input_not_const(input_not_const) {} 1.100 + 1.101 + virtual bool is_mh_late_inline() const { return true; } 1.102 + 1.103 + virtual JVMState* generate(JVMState* jvms) { 1.104 + JVMState* new_jvms = LateInlineCallGenerator::generate(jvms); 1.105 + if (_input_not_const) { 1.106 + // inlining won't be possible so no need to enqueue right now. 1.107 + call_node()->set_generator(this); 1.108 + } else { 1.109 + Compile::current()->add_late_inline(this); 1.110 + } 1.111 + return new_jvms; 1.112 + } 1.113 + 1.114 + virtual void print_inlining_late(const char* msg) { 1.115 + if (!_input_not_const) return; 1.116 + LateInlineCallGenerator::print_inlining_late(msg); 1.117 + } 1.118 +}; 1.119 + 1.120 +bool LateInlineMHCallGenerator::do_late_inline_check(JVMState* jvms) { 1.121 + 1.122 + CallGenerator* cg = for_method_handle_inline(jvms, _caller, method(), _input_not_const); 1.123 + 1.124 + if (!_input_not_const) { 1.125 + _attempt++; 1.126 + } 1.127 + 1.128 + if (cg != NULL) { 1.129 + assert(!cg->is_late_inline() && cg->is_inline(), "we're doing late inlining"); 1.130 + _inline_cg = cg; 1.131 + Compile::current()->dec_number_of_mh_late_inlines(); 1.132 + return true; 1.133 + } 1.134 + 1.135 + call_node()->set_generator(this); 1.136 + return false; 1.137 +} 1.138 + 1.139 +CallGenerator* CallGenerator::for_mh_late_inline(ciMethod* caller, ciMethod* callee, bool input_not_const) { 1.140 + Compile::current()->inc_number_of_mh_late_inlines(); 1.141 + CallGenerator* cg = new LateInlineMHCallGenerator(caller, callee, input_not_const); 1.142 + return cg; 1.143 +} 1.144 + 1.145 +class LateInlineStringCallGenerator : public LateInlineCallGenerator { 1.146 + 1.147 + public: 1.148 + LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) : 1.149 + LateInlineCallGenerator(method, inline_cg) {} 1.150 + 1.151 + virtual JVMState* generate(JVMState* jvms) { 1.152 + Compile *C = Compile::current(); 1.153 + C->print_inlining_skip(this); 1.154 + 1.155 + C->add_string_late_inline(this); 1.156 + 1.157 + JVMState* new_jvms = DirectCallGenerator::generate(jvms); 1.158 + return new_jvms; 1.159 + } 1.160 +}; 1.161 + 1.162 +CallGenerator* CallGenerator::for_string_late_inline(ciMethod* method, CallGenerator* inline_cg) { 1.163 + return new LateInlineStringCallGenerator(method, inline_cg); 1.164 +} 1.165 + 1.166 1.167 //---------------------------WarmCallGenerator-------------------------------- 1.168 // Internal class which handles initial deferral of inlining decisions. 1.169 @@ -586,35 +696,52 @@ 1.170 } 1.171 1.172 1.173 -CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* caller, ciMethod* callee) { 1.174 +CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool delayed_forbidden) { 1.175 assert(callee->is_method_handle_intrinsic() || 1.176 callee->is_compiled_lambda_form(), "for_method_handle_call mismatch"); 1.177 - CallGenerator* cg = CallGenerator::for_method_handle_inline(jvms, caller, callee); 1.178 - if (cg != NULL) 1.179 - return cg; 1.180 - return CallGenerator::for_direct_call(callee); 1.181 + bool input_not_const; 1.182 + CallGenerator* cg = CallGenerator::for_method_handle_inline(jvms, caller, callee, input_not_const); 1.183 + Compile* C = Compile::current(); 1.184 + if (cg != NULL) { 1.185 + if (!delayed_forbidden && AlwaysIncrementalInline) { 1.186 + return CallGenerator::for_late_inline(callee, cg); 1.187 + } else { 1.188 + return cg; 1.189 + } 1.190 + } 1.191 + int bci = jvms->bci(); 1.192 + ciCallProfile profile = caller->call_profile_at_bci(bci); 1.193 + int call_site_count = caller->scale_count(profile.count()); 1.194 + 1.195 + if (IncrementalInline && call_site_count > 0 && 1.196 + (input_not_const || !C->inlining_incrementally() || C->over_inlining_cutoff())) { 1.197 + return CallGenerator::for_mh_late_inline(caller, callee, input_not_const); 1.198 + } else { 1.199 + return CallGenerator::for_direct_call(callee); 1.200 + } 1.201 } 1.202 1.203 -CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee) { 1.204 +CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool& input_not_const) { 1.205 GraphKit kit(jvms); 1.206 PhaseGVN& gvn = kit.gvn(); 1.207 Compile* C = kit.C; 1.208 vmIntrinsics::ID iid = callee->intrinsic_id(); 1.209 + input_not_const = true; 1.210 switch (iid) { 1.211 case vmIntrinsics::_invokeBasic: 1.212 { 1.213 // Get MethodHandle receiver: 1.214 Node* receiver = kit.argument(0); 1.215 if (receiver->Opcode() == Op_ConP) { 1.216 + input_not_const = false; 1.217 const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr(); 1.218 ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget(); 1.219 guarantee(!target->is_method_handle_intrinsic(), "should not happen"); // XXX remove 1.220 const int vtable_index = Method::invalid_vtable_index; 1.221 - CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS); 1.222 + CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, true, true); 1.223 + assert (!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); 1.224 if (cg != NULL && cg->is_inline()) 1.225 return cg; 1.226 - } else { 1.227 - if (PrintInlining) C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), "receiver not constant"); 1.228 } 1.229 } 1.230 break; 1.231 @@ -627,6 +754,7 @@ 1.232 // Get MemberName argument: 1.233 Node* member_name = kit.argument(callee->arg_size() - 1); 1.234 if (member_name->Opcode() == Op_ConP) { 1.235 + input_not_const = false; 1.236 const TypeOopPtr* oop_ptr = member_name->bottom_type()->is_oopptr(); 1.237 ciMethod* target = oop_ptr->const_oop()->as_member_name()->get_vmtarget(); 1.238 1.239 @@ -661,7 +789,8 @@ 1.240 } 1.241 const int vtable_index = Method::invalid_vtable_index; 1.242 const bool call_is_virtual = target->is_abstract(); // FIXME workaround 1.243 - CallGenerator* cg = C->call_generator(target, vtable_index, call_is_virtual, jvms, true, PROB_ALWAYS); 1.244 + CallGenerator* cg = C->call_generator(target, vtable_index, call_is_virtual, jvms, true, PROB_ALWAYS, true, true); 1.245 + assert (!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); 1.246 if (cg != NULL && cg->is_inline()) 1.247 return cg; 1.248 }