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