hotspot/src/share/vm/opto/library_call.cpp
changeset 42086 feac795f345d
parent 42069 4bf36a6af07b
child 42555 2676a2244888
--- a/hotspot/src/share/vm/opto/library_call.cpp	Tue Nov 01 09:19:14 2016 +0100
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Thu Oct 06 18:51:24 2016 +0200
@@ -4046,7 +4046,7 @@
       if (!stopped()) {
         newcopy = new_array(klass_node, length, 0);  // no arguments to push
 
-        ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, true,
+        ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, true, false,
                                                 load_object_klass(original), klass_node);
         if (!is_copyOfRange) {
           ac->set_copyof(validated);
@@ -4566,7 +4566,7 @@
 
   const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM;
 
-  ArrayCopyNode* ac = ArrayCopyNode::make(this, false, src, NULL, dest, NULL, countx, false);
+  ArrayCopyNode* ac = ArrayCopyNode::make(this, false, src, NULL, dest, NULL, countx, false, false);
   ac->set_clonebasic();
   Node* n = _gvn.transform(ac);
   if (n == ac) {
@@ -4703,7 +4703,7 @@
           set_control(is_obja);
           // Generate a direct call to the right arraycopy function(s).
           Node* alloc = tightly_coupled_allocation(alloc_obj, NULL);
-          ArrayCopyNode* ac = ArrayCopyNode::make(this, true, obj, intcon(0), alloc_obj, intcon(0), obj_length, alloc != NULL);
+          ArrayCopyNode* ac = ArrayCopyNode::make(this, true, obj, intcon(0), alloc_obj, intcon(0), obj_length, alloc != NULL, false);
           ac->set_cloneoop();
           Node* n = _gvn.transform(ac);
           assert(n == ac, "cannot disappear");
@@ -5100,6 +5100,8 @@
     trap_bci = alloc->jvms()->bci();
   }
 
+  bool negative_length_guard_generated = false;
+
   if (!C->too_many_traps(trap_method, trap_bci, Deoptimization::Reason_intrinsic) &&
       can_emit_guards &&
       !src->is_top() && !dest->is_top()) {
@@ -5132,6 +5134,15 @@
                          load_array_length(dest),
                          slow_region);
 
+    // (6) length must not be negative.
+    // This is also checked in generate_arraycopy() during macro expansion, but
+    // we also have to check it here for the case where the ArrayCopyNode will
+    // be eliminated by Escape Analysis.
+    if (EliminateAllocations) {
+      generate_negative_guard(length, slow_region);
+      negative_length_guard_generated = true;
+    }
+
     // (9) each element of an oop array must be assignable
     Node* src_klass  = load_object_klass(src);
     Node* dest_klass = load_object_klass(dest);
@@ -5159,7 +5170,7 @@
     return true;
   }
 
-  ArrayCopyNode* ac = ArrayCopyNode::make(this, true, src, src_offset, dest, dest_offset, length, alloc != NULL,
+  ArrayCopyNode* ac = ArrayCopyNode::make(this, true, src, src_offset, dest, dest_offset, length, alloc != NULL, negative_length_guard_generated,
                                           // Create LoadRange and LoadKlass nodes for use during macro expansion here
                                           // so the compiler has a chance to eliminate them: during macro expansion,
                                           // we have to set their control (CastPP nodes are eliminated).