hotspot/src/share/vm/opto/macro.cpp
changeset 30629 b6e5ad2f18d5
parent 30248 5c6dacbd17ae
child 32370 38b7b5772b4f
--- a/hotspot/src/share/vm/opto/macro.cpp	Mon May 11 09:44:07 2015 +0200
+++ b/hotspot/src/share/vm/opto/macro.cpp	Tue May 12 10:27:50 2015 +0200
@@ -26,6 +26,7 @@
 #include "compiler/compileLog.hpp"
 #include "libadt/vectset.hpp"
 #include "opto/addnode.hpp"
+#include "opto/arraycopynode.hpp"
 #include "opto/callnode.hpp"
 #include "opto/castnode.hpp"
 #include "opto/cfgnode.hpp"
@@ -613,7 +614,10 @@
         for (DUIterator_Fast kmax, k = use->fast_outs(kmax);
                                    k < kmax && can_eliminate; k++) {
           Node* n = use->fast_out(k);
-          if (!n->is_Store() && n->Opcode() != Op_CastP2X) {
+          if (!n->is_Store() && n->Opcode() != Op_CastP2X &&
+              !(n->is_ArrayCopy() &&
+                n->as_ArrayCopy()->is_clonebasic() &&
+                n->in(ArrayCopyNode::Dest) == use)) {
             DEBUG_ONLY(disq_node = n;)
             if (n->is_Load() || n->is_LoadStore()) {
               NOT_PRODUCT(fail_eliminate = "Field load";)
@@ -623,6 +627,12 @@
             can_eliminate = false;
           }
         }
+      } else if (use->is_ArrayCopy() &&
+                 (use->as_ArrayCopy()->is_arraycopy_validated() ||
+                  use->as_ArrayCopy()->is_copyof_validated() ||
+                  use->as_ArrayCopy()->is_copyofrange_validated()) &&
+                 use->in(ArrayCopyNode::Dest) == res) {
+        // ok to eliminate
       } else if (use->is_SafePoint()) {
         SafePointNode* sfpt = use->as_SafePoint();
         if (sfpt->is_Call() && sfpt->as_Call()->has_non_debug_use(res)) {
@@ -887,11 +897,49 @@
             }
 #endif
             _igvn.replace_node(n, n->in(MemNode::Memory));
+          } else if (n->is_ArrayCopy()) {
+            // Disconnect ArrayCopy node
+            ArrayCopyNode* ac = n->as_ArrayCopy();
+            assert(ac->is_clonebasic(), "unexpected array copy kind");
+            Node* ctl_proj = ac->proj_out(TypeFunc::Control);
+            Node* mem_proj = ac->proj_out(TypeFunc::Memory);
+            if (ctl_proj != NULL) {
+              _igvn.replace_node(ctl_proj, n->in(0));
+            }
+            if (mem_proj != NULL) {
+              _igvn.replace_node(mem_proj, n->in(TypeFunc::Memory));
+            }
           } else {
             eliminate_card_mark(n);
           }
           k -= (oc2 - use->outcnt());
         }
+      } else if (use->is_ArrayCopy()) {
+        // Disconnect ArrayCopy node
+        ArrayCopyNode* ac = use->as_ArrayCopy();
+        assert(ac->is_arraycopy_validated() ||
+               ac->is_copyof_validated() ||
+               ac->is_copyofrange_validated(), "unsupported");
+        CallProjections callprojs;
+        ac->extract_projections(&callprojs, true);
+
+        _igvn.replace_node(callprojs.fallthrough_ioproj, ac->in(TypeFunc::I_O));
+        _igvn.replace_node(callprojs.fallthrough_memproj, ac->in(TypeFunc::Memory));
+        _igvn.replace_node(callprojs.fallthrough_catchproj, ac->in(TypeFunc::Control));
+
+        // Set control to top. IGVN will remove the remaining projections
+        ac->set_req(0, top());
+        ac->replace_edge(res, top());
+
+        // Disconnect src right away: it can help find new
+        // opportunities for allocation elimination
+        Node* src = ac->in(ArrayCopyNode::Src);
+        ac->replace_edge(src, top());
+        if (src->outcnt() == 0) {
+          _igvn.remove_dead_node(src);
+        }
+
+        _igvn._worklist.push(ac);
       } else {
         eliminate_card_mark(use);
       }