650 class PredictedCallGenerator : public CallGenerator { |
650 class PredictedCallGenerator : public CallGenerator { |
651 ciKlass* _predicted_receiver; |
651 ciKlass* _predicted_receiver; |
652 CallGenerator* _if_missed; |
652 CallGenerator* _if_missed; |
653 CallGenerator* _if_hit; |
653 CallGenerator* _if_hit; |
654 float _hit_prob; |
654 float _hit_prob; |
|
655 bool _exact_check; |
655 |
656 |
656 public: |
657 public: |
657 PredictedCallGenerator(ciKlass* predicted_receiver, |
658 PredictedCallGenerator(ciKlass* predicted_receiver, |
658 CallGenerator* if_missed, |
659 CallGenerator* if_missed, |
659 CallGenerator* if_hit, float hit_prob) |
660 CallGenerator* if_hit, bool exact_check, |
|
661 float hit_prob) |
660 : CallGenerator(if_missed->method()) |
662 : CallGenerator(if_missed->method()) |
661 { |
663 { |
662 // The call profile data may predict the hit_prob as extreme as 0 or 1. |
664 // The call profile data may predict the hit_prob as extreme as 0 or 1. |
663 // Remove the extremes values from the range. |
665 // Remove the extremes values from the range. |
664 if (hit_prob > PROB_MAX) hit_prob = PROB_MAX; |
666 if (hit_prob > PROB_MAX) hit_prob = PROB_MAX; |
666 |
668 |
667 _predicted_receiver = predicted_receiver; |
669 _predicted_receiver = predicted_receiver; |
668 _if_missed = if_missed; |
670 _if_missed = if_missed; |
669 _if_hit = if_hit; |
671 _if_hit = if_hit; |
670 _hit_prob = hit_prob; |
672 _hit_prob = hit_prob; |
|
673 _exact_check = exact_check; |
671 } |
674 } |
672 |
675 |
673 virtual bool is_virtual() const { return true; } |
676 virtual bool is_virtual() const { return true; } |
674 virtual bool is_inline() const { return _if_hit->is_inline(); } |
677 virtual bool is_inline() const { return _if_hit->is_inline(); } |
675 virtual bool is_deferred() const { return _if_hit->is_deferred(); } |
678 virtual bool is_deferred() const { return _if_hit->is_deferred(); } |
680 |
683 |
681 CallGenerator* CallGenerator::for_predicted_call(ciKlass* predicted_receiver, |
684 CallGenerator* CallGenerator::for_predicted_call(ciKlass* predicted_receiver, |
682 CallGenerator* if_missed, |
685 CallGenerator* if_missed, |
683 CallGenerator* if_hit, |
686 CallGenerator* if_hit, |
684 float hit_prob) { |
687 float hit_prob) { |
685 return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, hit_prob); |
688 return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, |
686 } |
689 /*exact_check=*/true, hit_prob); |
687 |
690 } |
|
691 |
|
692 CallGenerator* CallGenerator::for_guarded_call(ciKlass* guarded_receiver, |
|
693 CallGenerator* if_missed, |
|
694 CallGenerator* if_hit) { |
|
695 return new PredictedCallGenerator(guarded_receiver, if_missed, if_hit, |
|
696 /*exact_check=*/false, PROB_ALWAYS); |
|
697 } |
688 |
698 |
689 JVMState* PredictedCallGenerator::generate(JVMState* jvms) { |
699 JVMState* PredictedCallGenerator::generate(JVMState* jvms) { |
690 GraphKit kit(jvms); |
700 GraphKit kit(jvms); |
691 kit.C->print_inlining_update(this); |
701 kit.C->print_inlining_update(this); |
692 PhaseGVN& gvn = kit.gvn(); |
702 PhaseGVN& gvn = kit.gvn(); |
693 // We need an explicit receiver null_check before checking its type. |
703 // We need an explicit receiver null_check before checking its type. |
694 // We share a map with the caller, so his JVMS gets adjusted. |
704 // We share a map with the caller, so his JVMS gets adjusted. |
695 Node* receiver = kit.argument(0); |
705 Node* receiver = kit.argument(0); |
696 CompileLog* log = kit.C->log(); |
706 CompileLog* log = kit.C->log(); |
697 if (log != NULL) { |
707 if (log != NULL) { |
698 log->elem("predicted_call bci='%d' klass='%d'", |
708 log->elem("predicted_call bci='%d' exact='%d' klass='%d'", |
699 jvms->bci(), log->identify(_predicted_receiver)); |
709 jvms->bci(), (_exact_check ? 1 : 0), log->identify(_predicted_receiver)); |
700 } |
710 } |
701 |
711 |
702 receiver = kit.null_check_receiver_before_call(method()); |
712 receiver = kit.null_check_receiver_before_call(method()); |
703 if (kit.stopped()) { |
713 if (kit.stopped()) { |
704 return kit.transfer_exceptions_into_jvms(); |
714 return kit.transfer_exceptions_into_jvms(); |
706 |
716 |
707 // Make a copy of the replaced nodes in case we need to restore them |
717 // Make a copy of the replaced nodes in case we need to restore them |
708 ReplacedNodes replaced_nodes = kit.map()->replaced_nodes(); |
718 ReplacedNodes replaced_nodes = kit.map()->replaced_nodes(); |
709 replaced_nodes.clone(); |
719 replaced_nodes.clone(); |
710 |
720 |
711 Node* exact_receiver = receiver; // will get updated in place... |
721 Node* casted_receiver = receiver; // will get updated in place... |
712 Node* slow_ctl = kit.type_check_receiver(receiver, |
722 Node* slow_ctl = NULL; |
713 _predicted_receiver, _hit_prob, |
723 if (_exact_check) { |
714 &exact_receiver); |
724 slow_ctl = kit.type_check_receiver(receiver, _predicted_receiver, _hit_prob, |
|
725 &casted_receiver); |
|
726 } else { |
|
727 slow_ctl = kit.subtype_check_receiver(receiver, _predicted_receiver, |
|
728 &casted_receiver); |
|
729 } |
715 |
730 |
716 SafePointNode* slow_map = NULL; |
731 SafePointNode* slow_map = NULL; |
717 JVMState* slow_jvms = NULL; |
732 JVMState* slow_jvms = NULL; |
718 { PreserveJVMState pjvms(&kit); |
733 { PreserveJVMState pjvms(&kit); |
719 kit.set_control(slow_ctl); |
734 kit.set_control(slow_ctl); |
734 kit.set_jvms(slow_jvms); |
749 kit.set_jvms(slow_jvms); |
735 return kit.transfer_exceptions_into_jvms(); |
750 return kit.transfer_exceptions_into_jvms(); |
736 } |
751 } |
737 |
752 |
738 // fall through if the instance exactly matches the desired type |
753 // fall through if the instance exactly matches the desired type |
739 kit.replace_in_map(receiver, exact_receiver); |
754 kit.replace_in_map(receiver, casted_receiver); |
740 |
755 |
741 // Make the hot call: |
756 // Make the hot call: |
742 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); |
757 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); |
743 if (new_jvms == NULL) { |
758 if (new_jvms == NULL) { |
744 // Inline failed, so make a direct call. |
759 // Inline failed, so make a direct call. |