652 } |
652 } |
653 return kit.transfer_exceptions_into_jvms(); |
653 return kit.transfer_exceptions_into_jvms(); |
654 } |
654 } |
655 |
655 |
656 |
656 |
657 //------------------------PredictedDynamicCallGenerator----------------------- |
657 CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* caller, ciMethod* callee) { |
658 // Internal class which handles all out-of-line calls checking receiver type. |
658 assert(callee->is_method_handle_intrinsic() || |
659 class PredictedDynamicCallGenerator : public CallGenerator { |
659 callee->is_compiled_lambda_form(), "for_method_handle_call mismatch"); |
660 ciMethodHandle* _predicted_method_handle; |
660 CallGenerator* cg = CallGenerator::for_method_handle_inline(jvms, caller, callee); |
661 CallGenerator* _if_missed; |
|
662 CallGenerator* _if_hit; |
|
663 float _hit_prob; |
|
664 |
|
665 public: |
|
666 PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle, |
|
667 CallGenerator* if_missed, |
|
668 CallGenerator* if_hit, |
|
669 float hit_prob) |
|
670 : CallGenerator(if_missed->method()), |
|
671 _predicted_method_handle(predicted_method_handle), |
|
672 _if_missed(if_missed), |
|
673 _if_hit(if_hit), |
|
674 _hit_prob(hit_prob) |
|
675 {} |
|
676 |
|
677 virtual bool is_inline() const { return _if_hit->is_inline(); } |
|
678 virtual bool is_deferred() const { return _if_hit->is_deferred(); } |
|
679 |
|
680 virtual JVMState* generate(JVMState* jvms); |
|
681 }; |
|
682 |
|
683 |
|
684 CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle, |
|
685 CallGenerator* if_missed, |
|
686 CallGenerator* if_hit, |
|
687 float hit_prob) { |
|
688 return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob); |
|
689 } |
|
690 |
|
691 |
|
692 CallGenerator* CallGenerator::for_method_handle_call(Node* method_handle, JVMState* jvms, |
|
693 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { |
|
694 assert(callee->is_method_handle_invoke() || callee->is_method_handle_adapter(), "for_method_handle_call mismatch"); |
|
695 CallGenerator* cg = CallGenerator::for_method_handle_inline(method_handle, jvms, caller, callee, profile); |
|
696 if (cg != NULL) |
661 if (cg != NULL) |
697 return cg; |
662 return cg; |
698 return CallGenerator::for_direct_call(callee); |
663 return CallGenerator::for_direct_call(callee); |
699 } |
664 } |
700 |
665 |
701 CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMState* jvms, |
666 CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee) { |
702 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { |
667 GraphKit kit(jvms); |
703 if (method_handle->Opcode() == Op_ConP) { |
668 PhaseGVN& gvn = kit.gvn(); |
704 const TypeOopPtr* oop_ptr = method_handle->bottom_type()->is_oopptr(); |
669 Compile* C = kit.C; |
705 ciObject* const_oop = oop_ptr->const_oop(); |
670 vmIntrinsics::ID iid = callee->intrinsic_id(); |
706 ciMethodHandle* method_handle = const_oop->as_method_handle(); |
671 switch (iid) { |
707 |
672 case vmIntrinsics::_invokeBasic: |
708 // Set the callee to have access to the class and signature in |
673 { |
709 // the MethodHandleCompiler. |
674 // get MethodHandle receiver |
710 method_handle->set_callee(callee); |
675 Node* receiver = kit.argument(0); |
711 method_handle->set_caller(caller); |
676 if (receiver->Opcode() == Op_ConP) { |
712 method_handle->set_call_profile(profile); |
677 const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr(); |
713 |
678 ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget(); |
714 // Get an adapter for the MethodHandle. |
679 guarantee(!target->is_method_handle_intrinsic(), "should not happen"); // XXX remove |
715 ciMethod* target_method = method_handle->get_method_handle_adapter(); |
680 const int vtable_index = methodOopDesc::invalid_vtable_index; |
716 if (target_method != NULL) { |
681 CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS); |
717 CallGenerator* cg = Compile::current()->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); |
682 if (cg != NULL && cg->is_inline()) |
718 if (cg != NULL && cg->is_inline()) |
683 return cg; |
719 return cg; |
684 } else { |
720 } |
685 if (PrintInlining) CompileTask::print_inlining(callee, jvms->depth() - 1, jvms->bci(), "receiver not constant"); |
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 float prob = PROB_FAIR; |
|
724 Node* meth_region = method_handle->in(0); |
|
725 if (meth_region->is_Region() && |
|
726 meth_region->in(1)->is_Proj() && meth_region->in(2)->is_Proj() && |
|
727 meth_region->in(1)->in(0) == meth_region->in(2)->in(0) && |
|
728 meth_region->in(1)->in(0)->is_If()) { |
|
729 // If diamond, so grab the probability of the test to drive the inlining below |
|
730 prob = meth_region->in(1)->in(0)->as_If()->_prob; |
|
731 if (meth_region->in(1)->is_IfTrue()) { |
|
732 prob = 1 - prob; |
|
733 } |
686 } |
734 } |
687 } |
735 |
688 break; |
736 // selectAlternative idiom merging two constant MethodHandles. |
689 |
737 // Generate a guard so that each can be inlined. We might want to |
690 case vmIntrinsics::_linkToVirtual: |
738 // do more inputs at later point but this gets the most common |
691 case vmIntrinsics::_linkToStatic: |
739 // case. |
692 case vmIntrinsics::_linkToSpecial: |
740 CallGenerator* cg1 = for_method_handle_call(method_handle->in(1), jvms, caller, callee, profile.rescale(1.0 - prob)); |
693 case vmIntrinsics::_linkToInterface: |
741 CallGenerator* cg2 = for_method_handle_call(method_handle->in(2), jvms, caller, callee, profile.rescale(prob)); |
694 { |
742 if (cg1 != NULL && cg2 != NULL) { |
695 // pop MemberName argument |
743 const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr(); |
696 Node* member_name = kit.argument(callee->arg_size() - 1); |
744 ciObject* const_oop = oop_ptr->const_oop(); |
697 if (member_name->Opcode() == Op_ConP) { |
745 ciMethodHandle* mh = const_oop->as_method_handle(); |
698 const TypeOopPtr* oop_ptr = member_name->bottom_type()->is_oopptr(); |
746 return new PredictedDynamicCallGenerator(mh, cg2, cg1, prob); |
699 ciMethod* target = oop_ptr->const_oop()->as_member_name()->get_vmtarget(); |
747 } |
700 |
|
701 // In lamda forms we erase signature types to avoid resolving issues |
|
702 // involving class loaders. When we optimize a method handle invoke |
|
703 // to a direct call we must cast the receiver and arguments to its |
|
704 // actual types. |
|
705 ciSignature* signature = target->signature(); |
|
706 const int receiver_skip = target->is_static() ? 0 : 1; |
|
707 // Cast receiver to its type. |
|
708 if (!target->is_static()) { |
|
709 Node* arg = kit.argument(0); |
|
710 const TypeOopPtr* arg_type = arg->bottom_type()->isa_oopptr(); |
|
711 const Type* sig_type = TypeOopPtr::make_from_klass(signature->accessing_klass()); |
|
712 if (arg_type != NULL && !arg_type->higher_equal(sig_type)) { |
|
713 Node* cast_obj = gvn.transform(new (C, 2) CheckCastPPNode(kit.control(), arg, sig_type)); |
|
714 kit.set_argument(0, cast_obj); |
|
715 } |
|
716 } |
|
717 // Cast reference arguments to its type. |
|
718 for (int i = 0; i < signature->count(); i++) { |
|
719 ciType* t = signature->type_at(i); |
|
720 if (t->is_klass()) { |
|
721 Node* arg = kit.argument(receiver_skip + i); |
|
722 const TypeOopPtr* arg_type = arg->bottom_type()->isa_oopptr(); |
|
723 const Type* sig_type = TypeOopPtr::make_from_klass(t->as_klass()); |
|
724 if (arg_type != NULL && !arg_type->higher_equal(sig_type)) { |
|
725 Node* cast_obj = gvn.transform(new (C, 2) CheckCastPPNode(kit.control(), arg, sig_type)); |
|
726 kit.set_argument(receiver_skip + i, cast_obj); |
|
727 } |
|
728 } |
|
729 } |
|
730 const int vtable_index = methodOopDesc::invalid_vtable_index; |
|
731 const bool call_is_virtual = target->is_abstract(); // FIXME workaround |
|
732 CallGenerator* cg = C->call_generator(target, vtable_index, call_is_virtual, jvms, true, PROB_ALWAYS); |
|
733 if (cg != NULL && cg->is_inline()) |
|
734 return cg; |
|
735 } |
|
736 } |
|
737 break; |
|
738 |
|
739 default: |
|
740 fatal(err_msg("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid))); |
|
741 break; |
748 } |
742 } |
749 return NULL; |
743 return NULL; |
750 } |
|
751 |
|
752 CallGenerator* CallGenerator::for_invokedynamic_call(JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile) { |
|
753 assert(callee->is_method_handle_invoke() || callee->is_method_handle_adapter(), "for_invokedynamic_call mismatch"); |
|
754 // Get the CallSite object. |
|
755 ciBytecodeStream str(caller); |
|
756 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. |
|
757 ciCallSite* call_site = str.get_call_site(); |
|
758 CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, callee, profile); |
|
759 if (cg != NULL) |
|
760 return cg; |
|
761 return CallGenerator::for_dynamic_call(callee); |
|
762 } |
|
763 |
|
764 CallGenerator* CallGenerator::for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms, |
|
765 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { |
|
766 ciMethodHandle* method_handle = call_site->get_target(); |
|
767 |
|
768 // Set the callee to have access to the class and signature in the |
|
769 // MethodHandleCompiler. |
|
770 method_handle->set_callee(callee); |
|
771 method_handle->set_caller(caller); |
|
772 method_handle->set_call_profile(profile); |
|
773 |
|
774 // Get an adapter for the MethodHandle. |
|
775 ciMethod* target_method = method_handle->get_invokedynamic_adapter(); |
|
776 if (target_method != NULL) { |
|
777 Compile *C = Compile::current(); |
|
778 CallGenerator* cg = C->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); |
|
779 if (cg != NULL && cg->is_inline()) { |
|
780 // Add a dependence for invalidation of the optimization. |
|
781 if (!call_site->is_constant_call_site()) { |
|
782 C->dependencies()->assert_call_site_target_value(call_site, method_handle); |
|
783 } |
|
784 return cg; |
|
785 } |
|
786 } |
|
787 return NULL; |
|
788 } |
|
789 |
|
790 |
|
791 JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) { |
|
792 GraphKit kit(jvms); |
|
793 Compile* C = kit.C; |
|
794 PhaseGVN& gvn = kit.gvn(); |
|
795 |
|
796 CompileLog* log = C->log(); |
|
797 if (log != NULL) { |
|
798 log->elem("predicted_dynamic_call bci='%d'", jvms->bci()); |
|
799 } |
|
800 |
|
801 const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true); |
|
802 Node* predicted_mh = kit.makecon(predicted_mh_ptr); |
|
803 |
|
804 Node* bol = NULL; |
|
805 int bc = jvms->method()->java_code_at_bci(jvms->bci()); |
|
806 if (bc != Bytecodes::_invokedynamic) { |
|
807 // This is the selectAlternative idiom for guardWithTest or |
|
808 // similar idioms. |
|
809 Node* receiver = kit.argument(0); |
|
810 |
|
811 // Check if the MethodHandle is the expected one |
|
812 Node* cmp = gvn.transform(new (C, 3) CmpPNode(receiver, predicted_mh)); |
|
813 bol = gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq) ); |
|
814 } else { |
|
815 // Get the constant pool cache from the caller class. |
|
816 ciMethod* caller_method = jvms->method(); |
|
817 ciBytecodeStream str(caller_method); |
|
818 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. |
|
819 ciCPCache* cpcache = str.get_cpcache(); |
|
820 |
|
821 // Get the offset of the CallSite from the constant pool cache |
|
822 // pointer. |
|
823 int index = str.get_method_index(); |
|
824 size_t call_site_offset = cpcache->get_f1_offset(index); |
|
825 |
|
826 // Load the CallSite object from the constant pool cache. |
|
827 const TypeOopPtr* cpcache_type = TypeOopPtr::make_from_constant(cpcache); // returns TypeAryPtr of type T_OBJECT |
|
828 const TypeOopPtr* call_site_type = TypeOopPtr::make_from_klass(C->env()->CallSite_klass()); |
|
829 Node* cpcache_adr = kit.makecon(cpcache_type); |
|
830 Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, call_site_offset); |
|
831 // The oops in the constant pool cache are not compressed; load then as raw pointers. |
|
832 Node* call_site = kit.make_load(kit.control(), call_site_adr, call_site_type, T_ADDRESS, Compile::AliasIdxRaw); |
|
833 |
|
834 // Load the target MethodHandle from the CallSite object. |
|
835 const TypeOopPtr* target_type = TypeOopPtr::make_from_klass(C->env()->MethodHandle_klass()); |
|
836 Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes()); |
|
837 Node* target_mh = kit.make_load(kit.control(), target_adr, target_type, T_OBJECT); |
|
838 |
|
839 // Check if the MethodHandle is still the same. |
|
840 Node* cmp = gvn.transform(new (C, 3) CmpPNode(target_mh, predicted_mh)); |
|
841 bol = gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq) ); |
|
842 } |
|
843 IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN); |
|
844 kit.set_control( gvn.transform(new (C, 1) IfTrueNode (iff))); |
|
845 Node* slow_ctl = gvn.transform(new (C, 1) IfFalseNode(iff)); |
|
846 |
|
847 SafePointNode* slow_map = NULL; |
|
848 JVMState* slow_jvms; |
|
849 { PreserveJVMState pjvms(&kit); |
|
850 kit.set_control(slow_ctl); |
|
851 if (!kit.stopped()) { |
|
852 slow_jvms = _if_missed->generate(kit.sync_jvms()); |
|
853 if (kit.failing()) |
|
854 return NULL; // might happen because of NodeCountInliningCutoff |
|
855 assert(slow_jvms != NULL, "must be"); |
|
856 kit.add_exception_states_from(slow_jvms); |
|
857 kit.set_map(slow_jvms->map()); |
|
858 if (!kit.stopped()) |
|
859 slow_map = kit.stop(); |
|
860 } |
|
861 } |
|
862 |
|
863 if (kit.stopped()) { |
|
864 // Instance exactly does not matches the desired type. |
|
865 kit.set_jvms(slow_jvms); |
|
866 return kit.transfer_exceptions_into_jvms(); |
|
867 } |
|
868 |
|
869 // Make the hot call: |
|
870 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); |
|
871 if (new_jvms == NULL) { |
|
872 // Inline failed, so make a direct call. |
|
873 assert(_if_hit->is_inline(), "must have been a failed inline"); |
|
874 CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method()); |
|
875 new_jvms = cg->generate(kit.sync_jvms()); |
|
876 } |
|
877 kit.add_exception_states_from(new_jvms); |
|
878 kit.set_jvms(new_jvms); |
|
879 |
|
880 // Need to merge slow and fast? |
|
881 if (slow_map == NULL) { |
|
882 // The fast path is the only path remaining. |
|
883 return kit.transfer_exceptions_into_jvms(); |
|
884 } |
|
885 |
|
886 if (kit.stopped()) { |
|
887 // Inlined method threw an exception, so it's just the slow path after all. |
|
888 kit.set_jvms(slow_jvms); |
|
889 return kit.transfer_exceptions_into_jvms(); |
|
890 } |
|
891 |
|
892 // Finish the diamond. |
|
893 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization |
|
894 RegionNode* region = new (C, 3) RegionNode(3); |
|
895 region->init_req(1, kit.control()); |
|
896 region->init_req(2, slow_map->control()); |
|
897 kit.set_control(gvn.transform(region)); |
|
898 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); |
|
899 iophi->set_req(2, slow_map->i_o()); |
|
900 kit.set_i_o(gvn.transform(iophi)); |
|
901 kit.merge_memory(slow_map->merged_memory(), region, 2); |
|
902 uint tos = kit.jvms()->stkoff() + kit.sp(); |
|
903 uint limit = slow_map->req(); |
|
904 for (uint i = TypeFunc::Parms; i < limit; i++) { |
|
905 // Skip unused stack slots; fast forward to monoff(); |
|
906 if (i == tos) { |
|
907 i = kit.jvms()->monoff(); |
|
908 if( i >= limit ) break; |
|
909 } |
|
910 Node* m = kit.map()->in(i); |
|
911 Node* n = slow_map->in(i); |
|
912 if (m != n) { |
|
913 const Type* t = gvn.type(m)->meet(gvn.type(n)); |
|
914 Node* phi = PhiNode::make(region, m, t); |
|
915 phi->set_req(2, n); |
|
916 kit.map()->set_req(i, gvn.transform(phi)); |
|
917 } |
|
918 } |
|
919 return kit.transfer_exceptions_into_jvms(); |
|
920 } |
744 } |
921 |
745 |
922 |
746 |
923 //-------------------------UncommonTrapCallGenerator----------------------------- |
747 //-------------------------UncommonTrapCallGenerator----------------------------- |
924 // Internal class which handles all out-of-line calls checking receiver type. |
748 // Internal class which handles all out-of-line calls checking receiver type. |