comparison src/share/vm/opto/callGenerator.cpp @ 20312:922c87c9aed4

8035605: Expand functionality of PredictedIntrinsicGenerator Summary: Allow several predicates and separate intrinsic methods per one intrinsified (virtual) method. Reviewed-by: roland
author kvn
date Tue, 10 Jun 2014 12:28:06 -0700
parents dda2ae6f9557
children 411e30e5fbb8
comparison
equal deleted inserted replaced
20311:b1bc1af04c6e 20312:922c87c9aed4
708 region->init_req(2, slow_map->control()); 708 region->init_req(2, slow_map->control());
709 kit.set_control(gvn.transform(region)); 709 kit.set_control(gvn.transform(region));
710 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); 710 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
711 iophi->set_req(2, slow_map->i_o()); 711 iophi->set_req(2, slow_map->i_o());
712 kit.set_i_o(gvn.transform(iophi)); 712 kit.set_i_o(gvn.transform(iophi));
713 // Merge memory
713 kit.merge_memory(slow_map->merged_memory(), region, 2); 714 kit.merge_memory(slow_map->merged_memory(), region, 2);
715 // Transform new memory Phis.
716 for (MergeMemStream mms(kit.merged_memory()); mms.next_non_empty();) {
717 Node* phi = mms.memory();
718 if (phi->is_Phi() && phi->in(0) == region) {
719 mms.set_memory(gvn.transform(phi));
720 }
721 }
714 uint tos = kit.jvms()->stkoff() + kit.sp(); 722 uint tos = kit.jvms()->stkoff() + kit.sp();
715 uint limit = slow_map->req(); 723 uint limit = slow_map->req();
716 for (uint i = TypeFunc::Parms; i < limit; i++) { 724 for (uint i = TypeFunc::Parms; i < limit; i++) {
717 // Skip unused stack slots; fast forward to monoff(); 725 // Skip unused stack slots; fast forward to monoff();
718 if (i == tos) { 726 if (i == tos) {
862 } 870 }
863 return NULL; 871 return NULL;
864 } 872 }
865 873
866 874
867 //------------------------PredictedIntrinsicGenerator------------------------------ 875 //------------------------PredicatedIntrinsicGenerator------------------------------
868 // Internal class which handles all predicted Intrinsic calls. 876 // Internal class which handles all predicated Intrinsic calls.
869 class PredictedIntrinsicGenerator : public CallGenerator { 877 class PredicatedIntrinsicGenerator : public CallGenerator {
870 CallGenerator* _intrinsic; 878 CallGenerator* _intrinsic;
871 CallGenerator* _cg; 879 CallGenerator* _cg;
872 880
873 public: 881 public:
874 PredictedIntrinsicGenerator(CallGenerator* intrinsic, 882 PredicatedIntrinsicGenerator(CallGenerator* intrinsic,
875 CallGenerator* cg) 883 CallGenerator* cg)
876 : CallGenerator(cg->method()) 884 : CallGenerator(cg->method())
877 { 885 {
878 _intrinsic = intrinsic; 886 _intrinsic = intrinsic;
879 _cg = cg; 887 _cg = cg;
880 } 888 }
885 893
886 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); 894 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
887 }; 895 };
888 896
889 897
890 CallGenerator* CallGenerator::for_predicted_intrinsic(CallGenerator* intrinsic, 898 CallGenerator* CallGenerator::for_predicated_intrinsic(CallGenerator* intrinsic,
891 CallGenerator* cg) { 899 CallGenerator* cg) {
892 return new PredictedIntrinsicGenerator(intrinsic, cg); 900 return new PredicatedIntrinsicGenerator(intrinsic, cg);
893 } 901 }
894 902
895 903
896 JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_parser) { 904 JVMState* PredicatedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_parser) {
905 // The code we want to generate here is:
906 // if (receiver == NULL)
907 // uncommon_Trap
908 // if (predicate(0))
909 // do_intrinsic(0)
910 // else
911 // if (predicate(1))
912 // do_intrinsic(1)
913 // ...
914 // else
915 // do_java_comp
916
897 GraphKit kit(jvms); 917 GraphKit kit(jvms);
898 PhaseGVN& gvn = kit.gvn(); 918 PhaseGVN& gvn = kit.gvn();
899 919
900 CompileLog* log = kit.C->log(); 920 CompileLog* log = kit.C->log();
901 if (log != NULL) { 921 if (log != NULL) {
902 log->elem("predicted_intrinsic bci='%d' method='%d'", 922 log->elem("predicated_intrinsic bci='%d' method='%d'",
903 jvms->bci(), log->identify(method())); 923 jvms->bci(), log->identify(method()));
904 } 924 }
905 925
906 Node* slow_ctl = _intrinsic->generate_predicate(kit.sync_jvms()); 926 if (!method()->is_static()) {
907 if (kit.failing()) 927 // We need an explicit receiver null_check before checking its type in predicate.
908 return NULL; // might happen because of NodeCountInliningCutoff 928 // We share a map with the caller, so his JVMS gets adjusted.
909 929 Node* receiver = kit.null_check_receiver_before_call(method());
910 SafePointNode* slow_map = NULL; 930 if (kit.stopped()) {
911 JVMState* slow_jvms; 931 return kit.transfer_exceptions_into_jvms();
912 if (slow_ctl != NULL) { 932 }
933 }
934
935 int n_predicates = _intrinsic->predicates_count();
936 assert(n_predicates > 0, "sanity");
937
938 JVMState** result_jvms = NEW_RESOURCE_ARRAY(JVMState*, (n_predicates+1));
939
940 // Region for normal compilation code if intrinsic failed.
941 Node* slow_region = new (kit.C) RegionNode(1);
942
943 int results = 0;
944 for (int predicate = 0; (predicate < n_predicates) && !kit.stopped(); predicate++) {
945 #ifdef ASSERT
946 JVMState* old_jvms = kit.jvms();
947 SafePointNode* old_map = kit.map();
948 Node* old_io = old_map->i_o();
949 Node* old_mem = old_map->memory();
950 Node* old_exc = old_map->next_exception();
951 #endif
952 Node* else_ctrl = _intrinsic->generate_predicate(kit.sync_jvms(), predicate);
953 #ifdef ASSERT
954 // Assert(no_new_memory && no_new_io && no_new_exceptions) after generate_predicate.
955 assert(old_jvms == kit.jvms(), "generate_predicate should not change jvm state");
956 SafePointNode* new_map = kit.map();
957 assert(old_io == new_map->i_o(), "generate_predicate should not change i_o");
958 assert(old_mem == new_map->memory(), "generate_predicate should not change memory");
959 assert(old_exc == new_map->next_exception(), "generate_predicate should not add exceptions");
960 #endif
961 if (!kit.stopped()) {
962 PreserveJVMState pjvms(&kit);
963 // Generate intrinsic code:
964 JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms(), parent_parser);
965 if (new_jvms == NULL) {
966 // Intrinsic failed, use normal compilation path for this predicate.
967 slow_region->add_req(kit.control());
968 } else {
969 kit.add_exception_states_from(new_jvms);
970 kit.set_jvms(new_jvms);
971 if (!kit.stopped()) {
972 result_jvms[results++] = kit.jvms();
973 }
974 }
975 }
976 if (else_ctrl == NULL) {
977 else_ctrl = kit.C->top();
978 }
979 kit.set_control(else_ctrl);
980 }
981 if (!kit.stopped()) {
982 // Final 'else' after predicates.
983 slow_region->add_req(kit.control());
984 }
985 if (slow_region->req() > 1) {
913 PreserveJVMState pjvms(&kit); 986 PreserveJVMState pjvms(&kit);
914 kit.set_control(slow_ctl); 987 // Generate normal compilation code:
988 kit.set_control(gvn.transform(slow_region));
989 JVMState* new_jvms = _cg->generate(kit.sync_jvms(), parent_parser);
990 if (kit.failing())
991 return NULL; // might happen because of NodeCountInliningCutoff
992 assert(new_jvms != NULL, "must be");
993 kit.add_exception_states_from(new_jvms);
994 kit.set_jvms(new_jvms);
915 if (!kit.stopped()) { 995 if (!kit.stopped()) {
916 slow_jvms = _cg->generate(kit.sync_jvms(), parent_parser); 996 result_jvms[results++] = kit.jvms();
917 if (kit.failing()) 997 }
918 return NULL; // might happen because of NodeCountInliningCutoff 998 }
919 assert(slow_jvms != NULL, "must be"); 999
920 kit.add_exception_states_from(slow_jvms); 1000 if (results == 0) {
921 kit.set_map(slow_jvms->map()); 1001 // All paths ended in uncommon traps.
922 if (!kit.stopped()) 1002 (void) kit.stop();
923 slow_map = kit.stop();
924 }
925 }
926
927 if (kit.stopped()) {
928 // Predicate is always false.
929 kit.set_jvms(slow_jvms);
930 return kit.transfer_exceptions_into_jvms(); 1003 return kit.transfer_exceptions_into_jvms();
931 } 1004 }
932 1005
933 // Generate intrinsic code: 1006 if (results == 1) { // Only one path
934 JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms(), parent_parser); 1007 kit.set_jvms(result_jvms[0]);
935 if (new_jvms == NULL) { 1008 return kit.transfer_exceptions_into_jvms();
936 // Intrinsic failed, so use slow code or make a direct call. 1009 }
937 if (slow_map == NULL) { 1010
938 CallGenerator* cg = CallGenerator::for_direct_call(method()); 1011 // Merge all paths.
939 new_jvms = cg->generate(kit.sync_jvms(), parent_parser); 1012 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
1013 RegionNode* region = new (kit.C) RegionNode(results + 1);
1014 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
1015 for (int i = 0; i < results; i++) {
1016 JVMState* jvms = result_jvms[i];
1017 int path = i + 1;
1018 SafePointNode* map = jvms->map();
1019 region->init_req(path, map->control());
1020 iophi->set_req(path, map->i_o());
1021 if (i == 0) {
1022 kit.set_jvms(jvms);
940 } else { 1023 } else {
941 kit.set_jvms(slow_jvms); 1024 kit.merge_memory(map->merged_memory(), region, path);
942 return kit.transfer_exceptions_into_jvms(); 1025 }
943 } 1026 }
944 }
945 kit.add_exception_states_from(new_jvms);
946 kit.set_jvms(new_jvms);
947
948 // Need to merge slow and fast?
949 if (slow_map == NULL) {
950 // The fast path is the only path remaining.
951 return kit.transfer_exceptions_into_jvms();
952 }
953
954 if (kit.stopped()) {
955 // Intrinsic method threw an exception, so it's just the slow path after all.
956 kit.set_jvms(slow_jvms);
957 return kit.transfer_exceptions_into_jvms();
958 }
959
960 // Finish the diamond.
961 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
962 RegionNode* region = new (kit.C) RegionNode(3);
963 region->init_req(1, kit.control());
964 region->init_req(2, slow_map->control());
965 kit.set_control(gvn.transform(region)); 1027 kit.set_control(gvn.transform(region));
966 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
967 iophi->set_req(2, slow_map->i_o());
968 kit.set_i_o(gvn.transform(iophi)); 1028 kit.set_i_o(gvn.transform(iophi));
969 kit.merge_memory(slow_map->merged_memory(), region, 2); 1029 // Transform new memory Phis.
1030 for (MergeMemStream mms(kit.merged_memory()); mms.next_non_empty();) {
1031 Node* phi = mms.memory();
1032 if (phi->is_Phi() && phi->in(0) == region) {
1033 mms.set_memory(gvn.transform(phi));
1034 }
1035 }
1036
1037 // Merge debug info.
1038 Node** ins = NEW_RESOURCE_ARRAY(Node*, results);
970 uint tos = kit.jvms()->stkoff() + kit.sp(); 1039 uint tos = kit.jvms()->stkoff() + kit.sp();
971 uint limit = slow_map->req(); 1040 Node* map = kit.map();
1041 uint limit = map->req();
972 for (uint i = TypeFunc::Parms; i < limit; i++) { 1042 for (uint i = TypeFunc::Parms; i < limit; i++) {
973 // Skip unused stack slots; fast forward to monoff(); 1043 // Skip unused stack slots; fast forward to monoff();
974 if (i == tos) { 1044 if (i == tos) {
975 i = kit.jvms()->monoff(); 1045 i = kit.jvms()->monoff();
976 if( i >= limit ) break; 1046 if( i >= limit ) break;
977 } 1047 }
978 Node* m = kit.map()->in(i); 1048 Node* n = map->in(i);
979 Node* n = slow_map->in(i); 1049 ins[0] = n;
980 if (m != n) { 1050 const Type* t = gvn.type(n);
981 const Type* t = gvn.type(m)->meet_speculative(gvn.type(n)); 1051 bool needs_phi = false;
982 Node* phi = PhiNode::make(region, m, t); 1052 for (int j = 1; j < results; j++) {
983 phi->set_req(2, n); 1053 JVMState* jvms = result_jvms[j];
984 kit.map()->set_req(i, gvn.transform(phi)); 1054 Node* jmap = jvms->map();
985 } 1055 Node* m = NULL;
986 } 1056 if (jmap->req() > i) {
1057 m = jmap->in(i);
1058 if (m != n) {
1059 needs_phi = true;
1060 t = t->meet_speculative(gvn.type(m));
1061 }
1062 }
1063 ins[j] = m;
1064 }
1065 if (needs_phi) {
1066 Node* phi = PhiNode::make(region, n, t);
1067 for (int j = 1; j < results; j++) {
1068 phi->set_req(j + 1, ins[j]);
1069 }
1070 map->set_req(i, gvn.transform(phi));
1071 }
1072 }
1073
987 return kit.transfer_exceptions_into_jvms(); 1074 return kit.transfer_exceptions_into_jvms();
988 } 1075 }
989 1076
990 //-------------------------UncommonTrapCallGenerator----------------------------- 1077 //-------------------------UncommonTrapCallGenerator-----------------------------
991 // Internal class which handles all out-of-line calls checking receiver type. 1078 // Internal class which handles all out-of-line calls checking receiver type.