src/share/vm/opto/callGenerator.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/vm/opto/callGenerator.cpp	Wed Jun  1 14:37:21 2011
--- new/src/share/vm/opto/callGenerator.cpp	Wed Jun  1 14:37:20 2011

*** 696,714 **** --- 696,768 ---- float hit_prob) { return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob); } + CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMState* jvms, + ciMethod* caller, ciMethod* callee, ciCallProfile profile) { + if (method_handle->Opcode() == Op_ConP) { + const TypeOopPtr* oop_ptr = method_handle->bottom_type()->is_oopptr(); + ciObject* const_oop = oop_ptr->const_oop(); + ciMethodHandle* method_handle = const_oop->as_method_handle(); + + // Set the callee to have access to the class and signature in + // the MethodHandleCompiler. + method_handle->set_callee(callee); + method_handle->set_caller(caller); + method_handle->set_call_profile(profile); + + // Get an adapter for the MethodHandle. + ciMethod* target_method = method_handle->get_method_handle_adapter(); + if (target_method != NULL) { + CallGenerator* hit_cg = Compile::current()->call_generator(target_method, -1, false, jvms, true, 1); + if (hit_cg != NULL && hit_cg->is_inline()) + return hit_cg; + } + } else if (method_handle->Opcode() == Op_Phi && method_handle->req() == 3 && + method_handle->in(1)->Opcode() == Op_ConP && method_handle->in(2)->Opcode() == Op_ConP) { + // selectAlternative idiom merging two constant MethodHandles. + // Generate a guard so that each can be inlined. We might want to + // do more inputs at later point but this gets the most common + // case. + const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr(); + ciObject* const_oop = oop_ptr->const_oop(); + ciMethodHandle* mh = const_oop->as_method_handle(); + + CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile); + CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile); + if (cg1 != NULL && cg2 != NULL) { + return new PredictedDynamicCallGenerator(mh, cg2, cg1, PROB_FAIR); + } + } + return NULL; + } + + JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) { GraphKit kit(jvms); PhaseGVN& gvn = kit.gvn(); CompileLog* log = kit.C->log(); if (log != NULL) { log->elem("predicted_dynamic_call bci='%d'", jvms->bci()); } + const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true); + Node* predicted_mh = kit.makecon(predicted_mh_ptr); + + Node* bol = NULL; + int bc = jvms->method()->java_code_at_bci(jvms->bci()); + if (bc == Bytecodes::_invokespecial) { + // This is the selectAlternative idiom for guardWithTest + Node* receiver = kit.argument(0); + + // Check if the MethodHandle is the expected one + Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(receiver, predicted_mh)); + bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); + } else { + assert(bc == Bytecodes::_invokedynamic, "must be"); // Get the constant pool cache from the caller class. ciMethod* caller_method = jvms->method(); ciBytecodeStream str(caller_method); str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. ciCPCache* cpcache = str.get_cpcache();
*** 727,741 **** --- 781,793 ---- // Load the target MethodHandle from the CallSite object. Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes()); Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT); // Check if the MethodHandle is still the same. const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true); Node* predicted_mh = kit.makecon(predicted_mh_ptr); Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh)); ! Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); ! bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); + } IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN); kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff))); Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff)); SafePointNode* slow_map = NULL;

src/share/vm/opto/callGenerator.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File