--- old/src/cpu/x86/vm/stubGenerator_x86_64.cpp	2008-07-12 17:47:21.000000000 -0700
+++ new/src/cpu/x86/vm/stubGenerator_x86_64.cpp	2008-07-12 17:47:20.000000000 -0700
@@ -1044,6 +1044,7 @@
   static address oop_copy_entry;
 
   static address checkcast_copy_entry;
+  static address unsafe_copy_entry;
 
   //
   // Verify that a register contains clean 32-bits positive value
@@ -2328,6 +2329,9 @@
 
     __ enter(); // required for proper stackwalking of RuntimeStub frame
 
+    checkcast_copy_entry  = __ pc();
+    BLOCK_COMMENT("Entry:");
+
     // bump this on entry, not on exit:
     inc_counter_np(SharedRuntime::_unsafe_array_copy_ctr);
 
@@ -2515,10 +2519,10 @@
 
     // Load layout helper (32-bits)
     //
-    //  |array_tag|     | header_size | element_type |     |log2_element_size|
-    // 32        30    24            16              8     2                 0
+    //  | array_tag | element_type | log2_element_size | header_size |
+    // 32          28             24                  16             0
     //
-    //   array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
+    //   array_tag: typeArray = 0xF, objArray = 0xD, normal instance = 0x0
     //
 
     int lh_offset = klassOopDesc::header_size() * HeapWordSize +
@@ -2529,7 +2533,10 @@
     __ movl(rax_lh, Address(r10_src_klass, lh_offset));
 
     // Handle objArrays completely differently...
-    jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
+    // This is necessary because they have covariant element types.
+    // The next type check (for src.klass == dst.klass), can get a
+    // false negative in the case of object arrays.
+    jint objArray_lh = LayoutHelper::for_array(T_OBJECT).as_int();
     __ cmpl(rax_lh, objArray_lh);
     __ jcc(Assembler::equal, L_objArray);
 
@@ -2538,20 +2545,10 @@
     __ cmpq(r10_src_klass, r9_dst_klass);
     __ jcc(Assembler::notEqual, L_failed);
 
-    //  if (!src->is_Array()) return -1;
-    __ cmpl(rax_lh, Klass::_lh_neutral_value);
+    //  if (!src->has_length_field()) return -1;
+    __ cmpl(rax_lh, LayoutHelper::_neutral_value);
     __ jcc(Assembler::greaterEqual, L_failed);
 
-    // At this point, it is known to be a typeArray (array_tag 0x3).
-#ifdef ASSERT
-    { Label L;
-      __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
-      __ jcc(Assembler::greaterEqual, L);
-      __ stop("must be a primitive array");
-      __ bind(L);
-    }
-#endif
-
     arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
                            r10, L_failed);
 
@@ -2565,12 +2562,13 @@
     const Register rax_elsize = rax_lh; // element size
 
     __ movl(r10_offset, rax_lh);
-    __ shrl(r10_offset, Klass::_lh_header_size_shift);
-    __ andq(r10_offset, Klass::_lh_header_size_mask);   // array_offset
+    assert(LayoutHelper::_header_size_shift == 0, "");
+    __ andl(r10_offset, LayoutHelper::_header_size_mask);   // array_offset
     __ addq(src, r10_offset);           // src array offset
     __ addq(dst, r10_offset);           // dst array offset
     BLOCK_COMMENT("choose copy loop based on element size");
-    __ andl(rax_lh, Klass::_lh_log2_element_size_mask); // rax_lh -> rax_elsize
+    __ shrl(rax_lh, LayoutHelper::_element_size_shift);
+    __ andl(rax_lh, LayoutHelper::_element_size_mask); // rax_lh -> rax_elsize
 
     // next registers should be set before the jump to corresponding stub
     const Register from     = c_rarg0;  // source array address
@@ -2618,15 +2616,16 @@
     __ movslq(count, r11_length); // length
     __ jump(RuntimeAddress(long_copy_entry));
 
+    Label L_different_objArray, L_plain_copy, L_checkcast_copy;
+
     // objArrayKlass
   __ BIND(L_objArray);
     // live at this point:  r10_src_klass, src[_pos], dst[_pos]
 
-    Label L_plain_copy, L_checkcast_copy;
     //  test array classes for subtyping
     __ load_klass(r9_dst_klass, dst);
     __ cmpq(r10_src_klass, r9_dst_klass); // usual case is exact equality
-    __ jcc(Assembler::notEqual, L_checkcast_copy);
+    __ jcc(Assembler::notEqual, L_different_objArray);
 
     // Identically typed arrays can be copied without element-wise checks.
     arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
@@ -2640,7 +2639,7 @@
   __ BIND(L_plain_copy);
     __ jump(RuntimeAddress(oop_copy_entry));
 
-  __ BIND(L_checkcast_copy);
+  __ BIND(L_different_objArray);
     // live at this point:  r10_src_klass, !r11_length
     {
       // assert(r11_length == C_RARG4); // will reload from here
