Mercurial > hg > truffle
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; |