src/cpu/x86/vm/stubGenerator_x86_32.cpp

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

@@ -1462,10 +1462,11 @@
   //
   // Examines the alignment of the operands and dispatches
   // to a long, int, short, or byte copy loop.
   //
   address generate_unsafe_copy(const char *name,
+                               address* entry,
                                address byte_copy_entry,
                                address short_copy_entry,
                                address int_copy_entry,
                                address long_copy_entry) {
 

@@ -1492,10 +1493,13 @@
     __ movl(count, count_arg);
 
     // bump this on entry, not on exit:
     inc_counter_np(SharedRuntime::_unsafe_array_copy_ctr);
 
+    *entry = __ pc(); // Entry point from generic arraycopy stub.
+    BLOCK_COMMENT("Entry:");
+
     const Register bits = rsi;
     __ movl(bits, from);
     __ orl(bits, to);
     __ orl(bits, count);
 

@@ -1573,10 +1577,11 @@
                                 address entry_jbyte_arraycopy,
                                 address entry_jshort_arraycopy,
                                 address entry_jint_arraycopy,
                                 address entry_oop_arraycopy,
                                 address entry_jlong_arraycopy,
+                                address entry_unsafe_arraycopy,
                                 address entry_checkcast_arraycopy) {
     Label L_failed, L_failed_0, L_objArray;
 
     { int modulus = CodeEntryAlignment;
       int target  = modulus - 5; // 5 = sizeof jmp(L_failed)

@@ -1674,47 +1679,40 @@
     }
 #endif //ASSERT
 
     // 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();
     Address src_klass_lh_addr(rcx_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(src_klass_lh_addr, objArray_lh);
     __ jcc(Assembler::equal, L_objArray);
 
     //  if (src->klass() != dst->klass()) return -1;
     __ cmpl(rcx_src_klass, dst_klass_addr);
-    __ jccb(Assembler::notEqual, L_failed_0);
+    __ jcc(Assembler::notEqual, L_failed_0);
 
     const Register rcx_lh = rcx;  // layout helper
     assert(rcx_lh == rcx_src_klass, "known alias");
     __ movl(rcx_lh, src_klass_lh_addr);
 
-    //  if (!src->is_Array()) return -1;
-    __ cmpl(rcx_lh, Klass::_lh_neutral_value);
+    //  if (!src->has_length_field()) return -1;
+    __ cmpl(rcx_lh, LayoutHelper::_neutral_value);
     __ jcc(Assembler::greaterEqual, L_failed_0); // signed cmp
 
-    // At this point, it is known to be a typeArray (array_tag 0x3).
-#ifdef ASSERT
-    { Label L;
-      __ cmpl(rcx_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
-      __ jcc(Assembler::greaterEqual, L); // signed cmp
-      __ stop("must be a primitive array");
-      __ bind(L);
-    }
-#endif
-
     assert_different_registers(src, src_pos, dst, dst_pos, rcx_lh);
     arraycopy_range_checks(src, src_pos, dst, dst_pos, LENGTH, L_failed);
 
     // typeArrayKlass
     //

@@ -1725,15 +1723,16 @@
     const Register src_array  = src; // src array offset
     const Register dst_array  = dst; // dst array offset
     const Register rdi_elsize = rdi; // log2 element size
 
     __ movl(rsi_offset, rcx_lh);
-    __ shrl(rsi_offset, Klass::_lh_header_size_shift);
-    __ andl(rsi_offset, Klass::_lh_header_size_mask);   // array_offset
+    assert(LayoutHelper::_header_size_shift == 0, "");
+    __ andl(rsi_offset, LayoutHelper::_header_size_mask);   // array_offset
     __ addl(src_array, rsi_offset);  // src array offset
     __ addl(dst_array, rsi_offset);  // dst array offset
-    __ andl(rcx_lh, Klass::_lh_log2_element_size_mask); // log2 elsize
+    __ shrl(rcx_lh, LayoutHelper::_element_size_shift);
+    __ andl(rcx_lh, LayoutHelper::_element_size_mask); // log2 elsize
 
     // next registers should be set before the jump to corresponding stub
     const Register from       = src; // source array address
     const Register to         = dst; // destination array address
     const Register count      = rcx; // elements count

@@ -1745,16 +1744,15 @@
     BLOCK_COMMENT("scale indexes to element size");
     __ movl(rsi, SRC_POS);  // src_pos
     __ shll(rsi); // src_pos << rcx (log2 elsize)
     assert(src_array == from, "");
     __ addl(from, rsi);     // from = src_array + SRC_POS << log2 elsize
-    __ movl(rdi, DST_POS);  // dst_pos
-    __ shll(rdi); // dst_pos << rcx (log2 elsize)
+    __ movl(rsi, DST_POS);  // dst_pos (reuse rsi for a temp)
+    __ shll(rsi); // dst_pos << rcx (log2 elsize)
     assert(dst_array == to, "");
-    __ addl(to,  rdi);      // to   = dst_array + DST_POS << log2 elsize
+    __ addl(to,  rsi);      // to   = dst_array + DST_POS << log2 elsize
     __ movl(FROM, from);    // src_addr
-    __ movl(rdi_elsize, rcx_lh); // log2 elsize
     __ movl(count, LENGTH); // elements count
 
     BLOCK_COMMENT("choose copy loop based on element size");
     __ cmpl(rdi_elsize, 0);
 

@@ -1777,18 +1775,19 @@
     __ popl(rdi);
     __ popl(rsi);
     __ leave(); // required for proper stackwalking of RuntimeStub frame
     __ ret(0);
 
+    Label L_different_objArray, L_plain_copy, L_checkcast_copy;
+
     // objArrayKlass
   __ BIND(L_objArray);
     // live at this point:  rcx_src_klass, src[_pos], dst[_pos]
 
-    Label L_plain_copy, L_checkcast_copy;
     //  test array classes for subtyping
     __ cmpl(rcx_src_klass, dst_klass_addr); // usual case is exact equality
-    __ jccb(Assembler::notEqual, L_checkcast_copy);
+    __ jccb(Assembler::notEqual, L_different_objArray);
 
     // Identically typed arrays can be copied without element-wise checks.
     assert_different_registers(src, src_pos, dst, dst_pos, rcx_src_klass);
     arraycopy_range_checks(src, src_pos, dst, dst_pos, LENGTH, L_failed);
 

@@ -1803,11 +1802,11 @@
     __ movl(FROM,  from);   // src_addr
     __ movl(TO,    to);     // dst_addr
     __ movl(COUNT, count);  // count
     __ jump(RuntimeAddress(entry_oop_arraycopy));
 
-  __ BIND(L_checkcast_copy);
+  __ BIND(L_different_objArray);
     // live at this point:  rcx_src_klass, dst[_pos], src[_pos]
     {
       // Handy offsets:
       int  ek_offset = (klassOopDesc::header_size() * HeapWordSize +
                         objArrayKlass::element_klass_offset_in_bytes());

@@ -1821,11 +1820,11 @@
       Address dst_klass_lh_addr(rsi_dst_klass, lh_offset);
 
       // Before looking at dst.length, make sure dst is also an objArray.
       __ movl(rsi_dst_klass, dst_klass_addr);
       __ cmpl(dst_klass_lh_addr, objArray_lh);
-      __ jccb(Assembler::notEqual, L_failed);
+      __ jcc(Assembler::notEqual, L_failed);
 
       // It is safe to examine both src.length and dst.length.
       __ movl(src_pos, SRC_POS);        // reload rsi
       arraycopy_range_checks(src, src_pos, dst, dst_pos, LENGTH, L_failed);
       // (Now src_pos and dst_pos are killed, but not src and dst.)

@@ -1895,10 +1894,11 @@
     address entry_jbyte_arraycopy;
     address entry_jshort_arraycopy;
     address entry_jint_arraycopy;
     address entry_oop_arraycopy;
     address entry_jlong_arraycopy;
+    address entry_unsafe_arraycopy;
     address entry_checkcast_arraycopy;
 
     StubRoutines::_arrayof_jbyte_disjoint_arraycopy =
         generate_disjoint_copy(T_BYTE,  true, Address::times_1, &entry,
                                "arrayof_jbyte_disjoint_arraycopy");

@@ -1961,10 +1961,11 @@
         generate_checkcast_copy("checkcast_arraycopy",
                                   &entry_checkcast_arraycopy);
 
     StubRoutines::_unsafe_arraycopy =
         generate_unsafe_copy("unsafe_arraycopy",
+                               &entry_unsafe_arraycopy,
                                entry_jbyte_arraycopy,
                                entry_jshort_arraycopy,
                                entry_jint_arraycopy,
                                entry_jlong_arraycopy);
 

@@ -1973,10 +1974,11 @@
                                entry_jbyte_arraycopy,
                                entry_jshort_arraycopy,
                                entry_jint_arraycopy,
                                entry_oop_arraycopy,
                                entry_jlong_arraycopy,
+                               entry_unsafe_arraycopy,
                                entry_checkcast_arraycopy);
   }
 
  public:
   // Information about frame layout at time of blocking runtime call.