src/share/vm/opto/callGenerator.cpp

changeset 1573
dd57230ba8fe
parent 1572
97125851f396
child 1700
b4b440360f1e
     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 {

mercurial