src/cpu/x86/vm/stubGenerator_x86_64.cpp

Print this page
rev 146 : [mq]: mixa.layout.patch

@@ -1042,10 +1042,11 @@
   static address int_copy_entry;
   static address long_copy_entry;
   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
   // (high 32-bits are 0) so it could be used in 64-bits shifts.
   //

@@ -2326,10 +2327,13 @@
     StubCodeMark mark(this, "StubRoutines", name);
     address start = __ pc();
 
     __ 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);
 
     __ movq(bits, from);
     __ orq(bits, to);

@@ -2513,47 +2517,40 @@
     }
 #endif
 
     // 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 +
                     Klass::layout_helper_offset_in_bytes();
 
     const Register rax_lh = rax;  // layout helper
 
     __ 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);
 
     //  if (src->klass() != dst->klass()) return -1;
     __ load_klass(r9_dst_klass, dst);
     __ 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);
 
     // typeArrayKlass
     //

@@ -2563,16 +2560,17 @@
 
     const Register r10_offset = r10;    // array offset
     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
     const Register to       = c_rarg1;  // destination array address
     const Register count    = c_rarg2;  // elements count

@@ -2616,19 +2614,20 @@
     __ leaq(from, Address(src, src_pos, Address::times_8, 0));// src_addr
     __ leaq(to,   Address(dst, dst_pos, Address::times_8, 0));// dst_addr
     __ 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,
                            r10, L_failed);
 

@@ -2638,11 +2637,11 @@
                   arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
     __ movslq(count, r11_length); // length
   __ 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
       Register r11_dst_klass = r11;
       __ load_klass(r11_dst_klass, dst);