src/share/vm/opto/callGenerator.cpp

changeset 2949
f918d6096e23
parent 2725
f8b038506985
child 3050
fdb992d83a87
     1.1 --- a/src/share/vm/opto/callGenerator.cpp	Wed Jun 01 23:25:31 2011 -0700
     1.2 +++ b/src/share/vm/opto/callGenerator.cpp	Thu Jun 02 13:36:11 2011 -0700
     1.3 @@ -698,6 +698,46 @@
     1.4  }
     1.5  
     1.6  
     1.7 +CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMState* jvms,
     1.8 +                                                       ciMethod* caller, ciMethod* callee, ciCallProfile profile) {
     1.9 +  if (method_handle->Opcode() == Op_ConP) {
    1.10 +    const TypeOopPtr* oop_ptr = method_handle->bottom_type()->is_oopptr();
    1.11 +    ciObject* const_oop = oop_ptr->const_oop();
    1.12 +    ciMethodHandle* method_handle = const_oop->as_method_handle();
    1.13 +
    1.14 +    // Set the callee to have access to the class and signature in
    1.15 +    // the MethodHandleCompiler.
    1.16 +    method_handle->set_callee(callee);
    1.17 +    method_handle->set_caller(caller);
    1.18 +    method_handle->set_call_profile(profile);
    1.19 +
    1.20 +    // Get an adapter for the MethodHandle.
    1.21 +    ciMethod* target_method = method_handle->get_method_handle_adapter();
    1.22 +    if (target_method != NULL) {
    1.23 +      CallGenerator* hit_cg = Compile::current()->call_generator(target_method, -1, false, jvms, true, 1);
    1.24 +      if (hit_cg != NULL && hit_cg->is_inline())
    1.25 +        return hit_cg;
    1.26 +    }
    1.27 +  } else if (method_handle->Opcode() == Op_Phi && method_handle->req() == 3 &&
    1.28 +             method_handle->in(1)->Opcode() == Op_ConP && method_handle->in(2)->Opcode() == Op_ConP) {
    1.29 +    // selectAlternative idiom merging two constant MethodHandles.
    1.30 +    // Generate a guard so that each can be inlined.  We might want to
    1.31 +    // do more inputs at later point but this gets the most common
    1.32 +    // case.
    1.33 +    const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr();
    1.34 +    ciObject* const_oop = oop_ptr->const_oop();
    1.35 +    ciMethodHandle* mh = const_oop->as_method_handle();
    1.36 +
    1.37 +    CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile);
    1.38 +    CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile);
    1.39 +    if (cg1 != NULL && cg2 != NULL) {
    1.40 +      return new PredictedDynamicCallGenerator(mh, cg2, cg1, PROB_FAIR);
    1.41 +    }
    1.42 +  }
    1.43 +  return NULL;
    1.44 +}
    1.45 +
    1.46 +
    1.47  JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) {
    1.48    GraphKit kit(jvms);
    1.49    PhaseGVN& gvn = kit.gvn();
    1.50 @@ -707,33 +747,45 @@
    1.51      log->elem("predicted_dynamic_call bci='%d'", jvms->bci());
    1.52    }
    1.53  
    1.54 -  // Get the constant pool cache from the caller class.
    1.55 -  ciMethod* caller_method = jvms->method();
    1.56 -  ciBytecodeStream str(caller_method);
    1.57 -  str.force_bci(jvms->bci());  // Set the stream to the invokedynamic bci.
    1.58 -  ciCPCache* cpcache = str.get_cpcache();
    1.59 -
    1.60 -  // Get the offset of the CallSite from the constant pool cache
    1.61 -  // pointer.
    1.62 -  int index = str.get_method_index();
    1.63 -  size_t call_site_offset = cpcache->get_f1_offset(index);
    1.64 -
    1.65 -  // Load the CallSite object from the constant pool cache.
    1.66 -  const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
    1.67 -  Node* cpcache_adr   = kit.makecon(cpcache_ptr);
    1.68 -  Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
    1.69 -  Node* call_site     = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
    1.70 -
    1.71 -  // Load the target MethodHandle from the CallSite object.
    1.72 -  Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes());
    1.73 -  Node* target_mh  = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT);
    1.74 -
    1.75 -  // Check if the MethodHandle is still the same.
    1.76    const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true);
    1.77    Node* predicted_mh = kit.makecon(predicted_mh_ptr);
    1.78  
    1.79 -  Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh));
    1.80 -  Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) );
    1.81 +  Node* bol = NULL;
    1.82 +  int bc = jvms->method()->java_code_at_bci(jvms->bci());
    1.83 +  if (bc == Bytecodes::_invokespecial) {
    1.84 +    // This is the selectAlternative idiom for guardWithTest
    1.85 +    Node* receiver = kit.argument(0);
    1.86 +
    1.87 +    // Check if the MethodHandle is the expected one
    1.88 +    Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(receiver, predicted_mh));
    1.89 +    bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) );
    1.90 +  } else {
    1.91 +    assert(bc == Bytecodes::_invokedynamic, "must be");
    1.92 +    // Get the constant pool cache from the caller class.
    1.93 +    ciMethod* caller_method = jvms->method();
    1.94 +    ciBytecodeStream str(caller_method);
    1.95 +    str.force_bci(jvms->bci());  // Set the stream to the invokedynamic bci.
    1.96 +    ciCPCache* cpcache = str.get_cpcache();
    1.97 +
    1.98 +    // Get the offset of the CallSite from the constant pool cache
    1.99 +    // pointer.
   1.100 +    int index = str.get_method_index();
   1.101 +    size_t call_site_offset = cpcache->get_f1_offset(index);
   1.102 +
   1.103 +    // Load the CallSite object from the constant pool cache.
   1.104 +    const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
   1.105 +    Node* cpcache_adr   = kit.makecon(cpcache_ptr);
   1.106 +    Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
   1.107 +    Node* call_site     = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
   1.108 +
   1.109 +    // Load the target MethodHandle from the CallSite object.
   1.110 +    Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes());
   1.111 +    Node* target_mh  = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT);
   1.112 +
   1.113 +    // Check if the MethodHandle is still the same.
   1.114 +    Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh));
   1.115 +    bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) );
   1.116 +  }
   1.117    IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN);
   1.118    kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff)));
   1.119    Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff));

mercurial