24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "compiler/compileLog.hpp" |
26 #include "compiler/compileLog.hpp" |
27 #include "libadt/vectset.hpp" |
27 #include "libadt/vectset.hpp" |
28 #include "opto/addnode.hpp" |
28 #include "opto/addnode.hpp" |
|
29 #include "opto/arraycopynode.hpp" |
29 #include "opto/callnode.hpp" |
30 #include "opto/callnode.hpp" |
30 #include "opto/castnode.hpp" |
31 #include "opto/castnode.hpp" |
31 #include "opto/cfgnode.hpp" |
32 #include "opto/cfgnode.hpp" |
32 #include "opto/compile.hpp" |
33 #include "opto/compile.hpp" |
33 #include "opto/convertnode.hpp" |
34 #include "opto/convertnode.hpp" |
611 break; |
612 break; |
612 } |
613 } |
613 for (DUIterator_Fast kmax, k = use->fast_outs(kmax); |
614 for (DUIterator_Fast kmax, k = use->fast_outs(kmax); |
614 k < kmax && can_eliminate; k++) { |
615 k < kmax && can_eliminate; k++) { |
615 Node* n = use->fast_out(k); |
616 Node* n = use->fast_out(k); |
616 if (!n->is_Store() && n->Opcode() != Op_CastP2X) { |
617 if (!n->is_Store() && n->Opcode() != Op_CastP2X && |
|
618 !(n->is_ArrayCopy() && |
|
619 n->as_ArrayCopy()->is_clonebasic() && |
|
620 n->in(ArrayCopyNode::Dest) == use)) { |
617 DEBUG_ONLY(disq_node = n;) |
621 DEBUG_ONLY(disq_node = n;) |
618 if (n->is_Load() || n->is_LoadStore()) { |
622 if (n->is_Load() || n->is_LoadStore()) { |
619 NOT_PRODUCT(fail_eliminate = "Field load";) |
623 NOT_PRODUCT(fail_eliminate = "Field load";) |
620 } else { |
624 } else { |
621 NOT_PRODUCT(fail_eliminate = "Not store field referrence";) |
625 NOT_PRODUCT(fail_eliminate = "Not store field referrence";) |
622 } |
626 } |
623 can_eliminate = false; |
627 can_eliminate = false; |
624 } |
628 } |
625 } |
629 } |
|
630 } else if (use->is_ArrayCopy() && |
|
631 (use->as_ArrayCopy()->is_arraycopy_validated() || |
|
632 use->as_ArrayCopy()->is_copyof_validated() || |
|
633 use->as_ArrayCopy()->is_copyofrange_validated()) && |
|
634 use->in(ArrayCopyNode::Dest) == res) { |
|
635 // ok to eliminate |
626 } else if (use->is_SafePoint()) { |
636 } else if (use->is_SafePoint()) { |
627 SafePointNode* sfpt = use->as_SafePoint(); |
637 SafePointNode* sfpt = use->as_SafePoint(); |
628 if (sfpt->is_Call() && sfpt->as_Call()->has_non_debug_use(res)) { |
638 if (sfpt->is_Call() && sfpt->as_Call()->has_non_debug_use(res)) { |
629 // Object is passed as argument. |
639 // Object is passed as argument. |
630 DEBUG_ONLY(disq_node = use;) |
640 DEBUG_ONLY(disq_node = use;) |
885 mb->in(MemBarNode::Precedent) != n, |
895 mb->in(MemBarNode::Precedent) != n, |
886 "MemBarVolatile should be eliminated for non-escaping object"); |
896 "MemBarVolatile should be eliminated for non-escaping object"); |
887 } |
897 } |
888 #endif |
898 #endif |
889 _igvn.replace_node(n, n->in(MemNode::Memory)); |
899 _igvn.replace_node(n, n->in(MemNode::Memory)); |
|
900 } else if (n->is_ArrayCopy()) { |
|
901 // Disconnect ArrayCopy node |
|
902 ArrayCopyNode* ac = n->as_ArrayCopy(); |
|
903 assert(ac->is_clonebasic(), "unexpected array copy kind"); |
|
904 Node* ctl_proj = ac->proj_out(TypeFunc::Control); |
|
905 Node* mem_proj = ac->proj_out(TypeFunc::Memory); |
|
906 if (ctl_proj != NULL) { |
|
907 _igvn.replace_node(ctl_proj, n->in(0)); |
|
908 } |
|
909 if (mem_proj != NULL) { |
|
910 _igvn.replace_node(mem_proj, n->in(TypeFunc::Memory)); |
|
911 } |
890 } else { |
912 } else { |
891 eliminate_card_mark(n); |
913 eliminate_card_mark(n); |
892 } |
914 } |
893 k -= (oc2 - use->outcnt()); |
915 k -= (oc2 - use->outcnt()); |
894 } |
916 } |
|
917 } else if (use->is_ArrayCopy()) { |
|
918 // Disconnect ArrayCopy node |
|
919 ArrayCopyNode* ac = use->as_ArrayCopy(); |
|
920 assert(ac->is_arraycopy_validated() || |
|
921 ac->is_copyof_validated() || |
|
922 ac->is_copyofrange_validated(), "unsupported"); |
|
923 CallProjections callprojs; |
|
924 ac->extract_projections(&callprojs, true); |
|
925 |
|
926 _igvn.replace_node(callprojs.fallthrough_ioproj, ac->in(TypeFunc::I_O)); |
|
927 _igvn.replace_node(callprojs.fallthrough_memproj, ac->in(TypeFunc::Memory)); |
|
928 _igvn.replace_node(callprojs.fallthrough_catchproj, ac->in(TypeFunc::Control)); |
|
929 |
|
930 // Set control to top. IGVN will remove the remaining projections |
|
931 ac->set_req(0, top()); |
|
932 ac->replace_edge(res, top()); |
|
933 |
|
934 // Disconnect src right away: it can help find new |
|
935 // opportunities for allocation elimination |
|
936 Node* src = ac->in(ArrayCopyNode::Src); |
|
937 ac->replace_edge(src, top()); |
|
938 if (src->outcnt() == 0) { |
|
939 _igvn.remove_dead_node(src); |
|
940 } |
|
941 |
|
942 _igvn._worklist.push(ac); |
895 } else { |
943 } else { |
896 eliminate_card_mark(use); |
944 eliminate_card_mark(use); |
897 } |
945 } |
898 j -= (oc1 - res->outcnt()); |
946 j -= (oc1 - res->outcnt()); |
899 } |
947 } |