1.1 --- a/src/share/vm/opto/callGenerator.cpp Tue Jan 05 13:05:58 2010 +0100 1.2 +++ b/src/share/vm/opto/callGenerator.cpp Tue Jan 05 15:21:25 2010 +0100 1.3 @@ -148,7 +148,7 @@ 1.4 } 1.5 1.6 //---------------------------DynamicCallGenerator----------------------------- 1.7 -// Internal class which handles all out-of-line dynamic calls. 1.8 +// Internal class which handles all out-of-line invokedynamic calls. 1.9 class DynamicCallGenerator : public CallGenerator { 1.10 public: 1.11 DynamicCallGenerator(ciMethod* method) 1.12 @@ -179,25 +179,25 @@ 1.13 1.14 // Load the CallSite object from the constant pool cache. 1.15 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); 1.16 - Node* cpc = kit.makecon(cpcache_ptr); 1.17 - Node* adr = kit.basic_plus_adr(cpc, cpc, call_site_offset); 1.18 - Node* call_site = kit.make_load(kit.control(), adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); 1.19 + Node* cpcache_adr = kit.makecon(cpcache_ptr); 1.20 + Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset); 1.21 + Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); 1.22 1.23 - // Load the MethodHandle (target) from the CallSite object. 1.24 - Node* mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); 1.25 - Node* mh = kit.make_load(kit.control(), mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); 1.26 + // Load the target MethodHandle from the CallSite object. 1.27 + Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); 1.28 + Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); 1.29 1.30 - address stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); 1.31 + address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); 1.32 1.33 - CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), stub, method(), kit.bci()); 1.34 + CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci()); 1.35 // invokedynamic is treated as an optimized invokevirtual. 1.36 call->set_optimized_virtual(true); 1.37 // Take extra care (in the presence of argument motion) not to trash the SP: 1.38 call->set_method_handle_invoke(true); 1.39 1.40 - // Pass the MethodHandle as first argument and shift the other 1.41 - // arguments. 1.42 - call->init_req(0 + TypeFunc::Parms, mh); 1.43 + // Pass the target MethodHandle as first argument and shift the 1.44 + // other arguments. 1.45 + call->init_req(0 + TypeFunc::Parms, target_mh); 1.46 uint nargs = call->method()->arg_size(); 1.47 for (uint i = 1; i < nargs; i++) { 1.48 Node* arg = kit.argument(i - 1); 1.49 @@ -647,6 +647,155 @@ 1.50 } 1.51 1.52 1.53 +//------------------------PredictedDynamicCallGenerator----------------------- 1.54 +// Internal class which handles all out-of-line calls checking receiver type. 1.55 +class PredictedDynamicCallGenerator : public CallGenerator { 1.56 + ciMethodHandle* _predicted_method_handle; 1.57 + CallGenerator* _if_missed; 1.58 + CallGenerator* _if_hit; 1.59 + float _hit_prob; 1.60 + 1.61 +public: 1.62 + PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle, 1.63 + CallGenerator* if_missed, 1.64 + CallGenerator* if_hit, 1.65 + float hit_prob) 1.66 + : CallGenerator(if_missed->method()), 1.67 + _predicted_method_handle(predicted_method_handle), 1.68 + _if_missed(if_missed), 1.69 + _if_hit(if_hit), 1.70 + _hit_prob(hit_prob) 1.71 + {} 1.72 + 1.73 + virtual bool is_inline() const { return _if_hit->is_inline(); } 1.74 + virtual bool is_deferred() const { return _if_hit->is_deferred(); } 1.75 + 1.76 + virtual JVMState* generate(JVMState* jvms); 1.77 +}; 1.78 + 1.79 + 1.80 +CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle, 1.81 + CallGenerator* if_missed, 1.82 + CallGenerator* if_hit, 1.83 + float hit_prob) { 1.84 + return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob); 1.85 +} 1.86 + 1.87 + 1.88 +JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) { 1.89 + GraphKit kit(jvms); 1.90 + PhaseGVN& gvn = kit.gvn(); 1.91 + 1.92 + CompileLog* log = kit.C->log(); 1.93 + if (log != NULL) { 1.94 + log->elem("predicted_dynamic_call bci='%d'", jvms->bci()); 1.95 + } 1.96 + 1.97 + // Get the constant pool cache from the caller class. 1.98 + ciMethod* caller_method = jvms->method(); 1.99 + ciBytecodeStream str(caller_method); 1.100 + str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. 1.101 + ciCPCache* cpcache = str.get_cpcache(); 1.102 + 1.103 + // Get the offset of the CallSite from the constant pool cache 1.104 + // pointer. 1.105 + int index = str.get_method_index(); 1.106 + size_t call_site_offset = cpcache->get_f1_offset(index); 1.107 + 1.108 + // Load the CallSite object from the constant pool cache. 1.109 + const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); 1.110 + Node* cpcache_adr = kit.makecon(cpcache_ptr); 1.111 + Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset); 1.112 + Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); 1.113 + 1.114 + // Load the target MethodHandle from the CallSite object. 1.115 + Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); 1.116 + Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT); 1.117 + 1.118 + // Check if the MethodHandle is still the same. 1.119 + const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true); 1.120 + Node* predicted_mh = kit.makecon(predicted_mh_ptr); 1.121 + 1.122 + Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh)); 1.123 + Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); 1.124 + IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN); 1.125 + kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff))); 1.126 + Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff)); 1.127 + 1.128 + SafePointNode* slow_map = NULL; 1.129 + JVMState* slow_jvms; 1.130 + { PreserveJVMState pjvms(&kit); 1.131 + kit.set_control(slow_ctl); 1.132 + if (!kit.stopped()) { 1.133 + slow_jvms = _if_missed->generate(kit.sync_jvms()); 1.134 + assert(slow_jvms != NULL, "miss path must not fail to generate"); 1.135 + kit.add_exception_states_from(slow_jvms); 1.136 + kit.set_map(slow_jvms->map()); 1.137 + if (!kit.stopped()) 1.138 + slow_map = kit.stop(); 1.139 + } 1.140 + } 1.141 + 1.142 + if (kit.stopped()) { 1.143 + // Instance exactly does not matches the desired type. 1.144 + kit.set_jvms(slow_jvms); 1.145 + return kit.transfer_exceptions_into_jvms(); 1.146 + } 1.147 + 1.148 + // Make the hot call: 1.149 + JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); 1.150 + if (new_jvms == NULL) { 1.151 + // Inline failed, so make a direct call. 1.152 + assert(_if_hit->is_inline(), "must have been a failed inline"); 1.153 + CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method()); 1.154 + new_jvms = cg->generate(kit.sync_jvms()); 1.155 + } 1.156 + kit.add_exception_states_from(new_jvms); 1.157 + kit.set_jvms(new_jvms); 1.158 + 1.159 + // Need to merge slow and fast? 1.160 + if (slow_map == NULL) { 1.161 + // The fast path is the only path remaining. 1.162 + return kit.transfer_exceptions_into_jvms(); 1.163 + } 1.164 + 1.165 + if (kit.stopped()) { 1.166 + // Inlined method threw an exception, so it's just the slow path after all. 1.167 + kit.set_jvms(slow_jvms); 1.168 + return kit.transfer_exceptions_into_jvms(); 1.169 + } 1.170 + 1.171 + // Finish the diamond. 1.172 + kit.C->set_has_split_ifs(true); // Has chance for split-if optimization 1.173 + RegionNode* region = new (kit.C, 3) RegionNode(3); 1.174 + region->init_req(1, kit.control()); 1.175 + region->init_req(2, slow_map->control()); 1.176 + kit.set_control(gvn.transform(region)); 1.177 + Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); 1.178 + iophi->set_req(2, slow_map->i_o()); 1.179 + kit.set_i_o(gvn.transform(iophi)); 1.180 + kit.merge_memory(slow_map->merged_memory(), region, 2); 1.181 + uint tos = kit.jvms()->stkoff() + kit.sp(); 1.182 + uint limit = slow_map->req(); 1.183 + for (uint i = TypeFunc::Parms; i < limit; i++) { 1.184 + // Skip unused stack slots; fast forward to monoff(); 1.185 + if (i == tos) { 1.186 + i = kit.jvms()->monoff(); 1.187 + if( i >= limit ) break; 1.188 + } 1.189 + Node* m = kit.map()->in(i); 1.190 + Node* n = slow_map->in(i); 1.191 + if (m != n) { 1.192 + const Type* t = gvn.type(m)->meet(gvn.type(n)); 1.193 + Node* phi = PhiNode::make(region, m, t); 1.194 + phi->set_req(2, n); 1.195 + kit.map()->set_req(i, gvn.transform(phi)); 1.196 + } 1.197 + } 1.198 + return kit.transfer_exceptions_into_jvms(); 1.199 +} 1.200 + 1.201 + 1.202 //-------------------------UncommonTrapCallGenerator----------------------------- 1.203 // Internal class which handles all out-of-line calls checking receiver type. 1.204 class UncommonTrapCallGenerator : public CallGenerator {