comparison src/share/vm/opto/callGenerator.cpp @ 3752:f918d6096e23

7050554: JSR 292 - need optimization for selectAlternative Reviewed-by: kvn, jrose
author never
date Thu, 02 Jun 2011 13:36:11 -0700
parents f8b038506985
children fdb992d83a87
comparison
equal deleted inserted replaced
3745:a93146d0e4be 3752:f918d6096e23
696 float hit_prob) { 696 float hit_prob) {
697 return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob); 697 return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob);
698 } 698 }
699 699
700 700
701 CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMState* jvms,
702 ciMethod* caller, ciMethod* callee, ciCallProfile profile) {
703 if (method_handle->Opcode() == Op_ConP) {
704 const TypeOopPtr* oop_ptr = method_handle->bottom_type()->is_oopptr();
705 ciObject* const_oop = oop_ptr->const_oop();
706 ciMethodHandle* method_handle = const_oop->as_method_handle();
707
708 // Set the callee to have access to the class and signature in
709 // the MethodHandleCompiler.
710 method_handle->set_callee(callee);
711 method_handle->set_caller(caller);
712 method_handle->set_call_profile(profile);
713
714 // Get an adapter for the MethodHandle.
715 ciMethod* target_method = method_handle->get_method_handle_adapter();
716 if (target_method != NULL) {
717 CallGenerator* hit_cg = Compile::current()->call_generator(target_method, -1, false, jvms, true, 1);
718 if (hit_cg != NULL && hit_cg->is_inline())
719 return hit_cg;
720 }
721 } else if (method_handle->Opcode() == Op_Phi && method_handle->req() == 3 &&
722 method_handle->in(1)->Opcode() == Op_ConP && method_handle->in(2)->Opcode() == Op_ConP) {
723 // selectAlternative idiom merging two constant MethodHandles.
724 // Generate a guard so that each can be inlined. We might want to
725 // do more inputs at later point but this gets the most common
726 // case.
727 const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr();
728 ciObject* const_oop = oop_ptr->const_oop();
729 ciMethodHandle* mh = const_oop->as_method_handle();
730
731 CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile);
732 CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile);
733 if (cg1 != NULL && cg2 != NULL) {
734 return new PredictedDynamicCallGenerator(mh, cg2, cg1, PROB_FAIR);
735 }
736 }
737 return NULL;
738 }
739
740
701 JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) { 741 JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) {
702 GraphKit kit(jvms); 742 GraphKit kit(jvms);
703 PhaseGVN& gvn = kit.gvn(); 743 PhaseGVN& gvn = kit.gvn();
704 744
705 CompileLog* log = kit.C->log(); 745 CompileLog* log = kit.C->log();
706 if (log != NULL) { 746 if (log != NULL) {
707 log->elem("predicted_dynamic_call bci='%d'", jvms->bci()); 747 log->elem("predicted_dynamic_call bci='%d'", jvms->bci());
708 } 748 }
709 749
710 // Get the constant pool cache from the caller class.
711 ciMethod* caller_method = jvms->method();
712 ciBytecodeStream str(caller_method);
713 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
714 ciCPCache* cpcache = str.get_cpcache();
715
716 // Get the offset of the CallSite from the constant pool cache
717 // pointer.
718 int index = str.get_method_index();
719 size_t call_site_offset = cpcache->get_f1_offset(index);
720
721 // Load the CallSite object from the constant pool cache.
722 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
723 Node* cpcache_adr = kit.makecon(cpcache_ptr);
724 Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
725 Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
726
727 // Load the target MethodHandle from the CallSite object.
728 Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes());
729 Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT);
730
731 // Check if the MethodHandle is still the same.
732 const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true); 750 const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true);
733 Node* predicted_mh = kit.makecon(predicted_mh_ptr); 751 Node* predicted_mh = kit.makecon(predicted_mh_ptr);
734 752
735 Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh)); 753 Node* bol = NULL;
736 Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); 754 int bc = jvms->method()->java_code_at_bci(jvms->bci());
755 if (bc == Bytecodes::_invokespecial) {
756 // This is the selectAlternative idiom for guardWithTest
757 Node* receiver = kit.argument(0);
758
759 // Check if the MethodHandle is the expected one
760 Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(receiver, predicted_mh));
761 bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) );
762 } else {
763 assert(bc == Bytecodes::_invokedynamic, "must be");
764 // Get the constant pool cache from the caller class.
765 ciMethod* caller_method = jvms->method();
766 ciBytecodeStream str(caller_method);
767 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
768 ciCPCache* cpcache = str.get_cpcache();
769
770 // Get the offset of the CallSite from the constant pool cache
771 // pointer.
772 int index = str.get_method_index();
773 size_t call_site_offset = cpcache->get_f1_offset(index);
774
775 // Load the CallSite object from the constant pool cache.
776 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
777 Node* cpcache_adr = kit.makecon(cpcache_ptr);
778 Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
779 Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
780
781 // Load the target MethodHandle from the CallSite object.
782 Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes());
783 Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT);
784
785 // Check if the MethodHandle is still the same.
786 Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh));
787 bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) );
788 }
737 IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN); 789 IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN);
738 kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff))); 790 kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff)));
739 Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff)); 791 Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff));
740 792
741 SafePointNode* slow_map = NULL; 793 SafePointNode* slow_map = NULL;