src/cpu/sparc/vm/stubGenerator_sparc.cpp
Print this page
rev 146 : [mq]: mixa.layout.patch
@@ -2698,14 +2698,14 @@
}
#endif
// Load layout helper
//
- // |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();
@@ -2714,11 +2714,14 @@
if (UseCompressedOops) {
__ load_klass(dst, G4_dst_klass);
}
// Handle objArrays completely differently...
- juint 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();
__ set(objArray_lh, O5_temp);
__ cmp(G5_lh, O5_temp);
__ br(Assembler::equal, false, Assembler::pt, L_objArray);
if (UseCompressedOops) {
__ delayed()->nop();
@@ -2729,29 +2732,15 @@
// if (src->klass() != dst->klass()) return -1;
__ cmp(G3_src_klass, G4_dst_klass);
__ brx(Assembler::notEqual, false, Assembler::pn, L_failed);
__ delayed()->nop();
- // if (!src->is_Array()) return -1;
- __ cmp(G5_lh, Klass::_lh_neutral_value); // < 0
+ // if (!src->has_length_field()) return -1;
+ __ cmp(G5_lh, LayoutHelper::_neutral_value); // < 0
__ br(Assembler::greaterEqual, false, Assembler::pn, L_failed);
- // At this point, it is known to be a typeArray (array_tag 0x3).
-#ifdef ASSERT
- __ delayed()->nop();
- { Label L;
- jint lh_prim_tag_in_place = (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift);
- __ set(lh_prim_tag_in_place, O5_temp);
- __ cmp(G5_lh, O5_temp);
- __ br(Assembler::greaterEqual, false, Assembler::pt, L);
- __ delayed()->nop();
- __ stop("must be a primitive array");
- __ bind(L);
- }
-#else
__ delayed(); // match next insn to prev branch
-#endif
arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
O5_temp, G4_dst_klass, L_failed);
// typeArrayKlass
@@ -2761,15 +2750,17 @@
//
const Register G4_offset = G4_dst_klass; // array offset
const Register G3_elsize = G3_src_klass; // log2 element size
- __ srl(G5_lh, Klass::_lh_header_size_shift, G4_offset);
- __ and3(G4_offset, Klass::_lh_header_size_mask, G4_offset); // array_offset
+ assert(LayoutHelper::_header_size_shift == 0, "");
+ __ set(LayoutHelper::_header_size_mask, G4_offset);
+ __ and3(G5_lh, G4_offset, G4_offset); // array_offset
__ add(src, G4_offset, src); // src array offset
__ add(dst, G4_offset, dst); // dst array offset
- __ and3(G5_lh, Klass::_lh_log2_element_size_mask, G3_elsize); // log2 element size
+ __ srl( G5_lh, LayoutHelper::_element_size_shift, G3_elsize);
+ __ and3(G3_elsize, LayoutHelper::_element_size_mask, G3_elsize); // log2 element size
// next registers should be set before the jump to corresponding stub
const Register from = O0; // source array address
const Register to = O1; // destination array address
const Register count = O2; // elements count
@@ -2805,18 +2796,19 @@
}
#endif
__ br(Assembler::always,false,Assembler::pt,StubRoutines::_jlong_arraycopy);
__ delayed()->signx(length, count); // length
+ Label L_different_objArray, L_plain_copy, L_checkcast_copy;
+
// objArrayKlass
__ BIND(L_objArray);
// live at this point: G3_src_klass, G4_dst_klass, src[_pos], dst[_pos], length
- Label L_plain_copy, L_checkcast_copy;
// test array classes for subtyping
__ cmp(G3_src_klass, G4_dst_klass); // usual case is exact equality
- __ brx(Assembler::notEqual, true, Assembler::pn, L_checkcast_copy);
+ __ brx(Assembler::notEqual, true, Assembler::pn, L_different_objArray);
__ delayed()->lduw(G4_dst_klass, lh_offset, O5_temp); // hoisted from below
// Identically typed arrays can be copied without element-wise checks.
arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
O5_temp, G5_lh, L_failed);
@@ -2829,11 +2821,11 @@
__ add(dst, dst_pos, to); // dst_addr
__ BIND(L_plain_copy);
__ br(Assembler::always, false, Assembler::pt,StubRoutines::_oop_arraycopy);
__ delayed()->signx(length, count); // length
- __ BIND(L_checkcast_copy);
+ __ BIND(L_different_objArray);
// live at this point: G3_src_klass, G4_dst_klass
{
// Before looking at dst.length, make sure dst is also an objArray.
// lduw(G4_dst_klass, lh_offset, O5_temp); // hoisted to delay slot
__ cmp(G5_lh, O5_temp);