Mercurial > hg > graal-jvmci-8
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. |