< prev index next >
src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
Print this page
rev 10236 : 8149733: AArch64: refactor array_equals/string_equals
Summary: combine similar code for string_equals/char_array_equals/byte_array_equals into same implemenation
Reviewed-by: duke
@@ -4479,227 +4479,123 @@
bind(DONE);
BLOCK_COMMENT("} string_compare");
}
-
-void MacroAssembler::string_equals(Register str1, Register str2,
- Register cnt, Register result,
- Register tmp1) {
- Label SAME_CHARS, DONE, SHORT_LOOP, SHORT_STRING,
- NEXT_WORD;
-
- const Register tmp2 = rscratch1;
- assert_different_registers(str1, str2, cnt, result, tmp1, tmp2, rscratch2);
-
- BLOCK_COMMENT("string_equals {");
-
- // Start by assuming that the strings are not equal.
- mov(result, zr);
-
- // A very short string
- cmpw(cnt, 4);
- br(Assembler::LT, SHORT_STRING);
-
- // Check if the strings start at the same location.
- cmp(str1, str2);
- br(Assembler::EQ, SAME_CHARS);
-
- // Compare longwords
- {
- subw(cnt, cnt, 4); // The last longword is a special case
-
- // Move both string pointers to the last longword of their
- // strings, negate the remaining count, and convert it to bytes.
- lea(str1, Address(str1, cnt, Address::uxtw(1)));
- lea(str2, Address(str2, cnt, Address::uxtw(1)));
- sub(cnt, zr, cnt, LSL, 1);
-
- // Loop, loading longwords and comparing them into rscratch2.
- bind(NEXT_WORD);
- ldr(tmp1, Address(str1, cnt));
- ldr(tmp2, Address(str2, cnt));
- adds(cnt, cnt, wordSize);
- eor(rscratch2, tmp1, tmp2);
- cbnz(rscratch2, DONE);
- br(Assembler::LT, NEXT_WORD);
-
- // Last longword. In the case where length == 4 we compare the
- // same longword twice, but that's still faster than another
- // conditional branch.
-
- ldr(tmp1, Address(str1));
- ldr(tmp2, Address(str2));
- eor(rscratch2, tmp1, tmp2);
- cbz(rscratch2, SAME_CHARS);
- b(DONE);
- }
-
- bind(SHORT_STRING);
- // Is the length zero?
- cbz(cnt, SAME_CHARS);
-
- bind(SHORT_LOOP);
- load_unsigned_short(tmp1, Address(post(str1, 2)));
- load_unsigned_short(tmp2, Address(post(str2, 2)));
- subw(tmp1, tmp1, tmp2);
- cbnz(tmp1, DONE);
- sub(cnt, cnt, 1);
- cbnz(cnt, SHORT_LOOP);
-
- // Strings are equal.
- bind(SAME_CHARS);
- mov(result, true);
-
- // That's it
- bind(DONE);
-
- BLOCK_COMMENT("} string_equals");
-}
-
-
-void MacroAssembler::byte_arrays_equals(Register ary1, Register ary2,
- Register result, Register tmp1)
+// for string equals tmp1 is string length, stepSize is 2, is_array_equal false
+// for array equals byte tmp1 is temp, stepSize is 1, is_string_equal false
+// for array equals char tmp1 is temp, stepSize is 2, is_string_equal false
+// if is_string_equal is true, ary1 and ary2 are string's value array element 0 address.
+//
+// current two implenetaions
+// 1. current string eqauls, comapre 8 bytes at last ieration
+// 2. current array equals, split compre for tail
+//
+// New implemenation in this method is
+// 1. for array length GE 8 bytes, compare main body and tail both in 8 bytes
+// 2. for array length LT 8 bytes, compare in test-ld-cmp sequence
+// only support string equals, char array equals and byte array equals now.
+void MacroAssembler::generic_arrays_equals(Register ary1, Register ary2,
+ Register result, Register tmp,
+ int step_size, bool is_string_equal)
{
- Register cnt1 = rscratch1;
- Register cnt2 = rscratch2;
+ Label SAME, DONE, SHORT, NEXT_WORD;
+ Register cnt1 = tmp;
+ Register tmp1 = rscratch1;
Register tmp2 = rscratch2;
-
- Label SAME, DIFFER, NEXT, TAIL07, TAIL03, TAIL01;
-
+ int elem_per_word = wordSize/step_size;
+ int exact_log = exact_log2(step_size);
int length_offset = arrayOopDesc::length_offset_in_bytes();
- int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE);
+ int base_offset = -1;
+ switch (step_size) {
+ case 1:
+ base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE);
+ break;
+ case 2:
+ base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
+ break;
+ default:
+ assert(false, "unexpected step size\n");
+ }
+ assert_different_registers(ary1, ary2, result, cnt1, rscratch1, rscratch2);
- BLOCK_COMMENT("byte_arrays_equals {");
+ BLOCK_COMMENT("generic_arrays_equals {");
- // different until proven equal
- mov(result, false);
-
- // same array?
+ // same array check
cmp(ary1, ary2);
+ mov(result, false);
br(Assembler::EQ, SAME);
- // ne if either null
- cbz(ary1, DIFFER);
- cbz(ary2, DIFFER);
-
+ // extra length/NULL compare for array equals
+ if (is_string_equal == false) {
+ cbz(ary1, DONE);
+ cbz(ary2, DONE);
// lengths ne?
ldrw(cnt1, Address(ary1, length_offset));
- ldrw(cnt2, Address(ary2, length_offset));
- cmp(cnt1, cnt2);
- br(Assembler::NE, DIFFER);
-
+ ldrw(tmp2, Address(ary2, length_offset));
+ cmp(cnt1, tmp2);
+ br(Assembler::NE, DONE);
lea(ary1, Address(ary1, base_offset));
lea(ary2, Address(ary2, base_offset));
+ }
- subs(cnt1, cnt1, 8);
- br(LT, TAIL07);
+ // check short compare
+ subs(cnt1, cnt1, elem_per_word); // The last longword is a special case
+ br(Assembler::LT, SHORT);
- BIND(NEXT);
- ldr(tmp1, Address(post(ary1, 8)));
- ldr(tmp2, Address(post(ary2, 8)));
- subs(cnt1, cnt1, 8);
+ // 8 bytes compare
+ bind(NEXT_WORD);
+ ldr(tmp1, Address(post(ary1, wordSize)));
+ ldr(tmp2, Address(post(ary2, wordSize)));
+ subs(cnt1, cnt1, elem_per_word);
eor(tmp1, tmp1, tmp2);
- cbnz(tmp1, DIFFER);
- br(GE, NEXT);
+ cbnz(tmp1, DONE);
+ br(GT, NEXT_WORD);
+ // Last longword. In the case where length == 4 we compare the
+ // same longword twice, but that's still faster than another
+ // conditional branch.
+ // cnt1 could be 0,-1,-2,-3,-4 for chars,-4 only happens when length is 4
+ if (exact_log >0 ) {
+ add(cnt1, zr, cnt1, Assembler::LSL, exact_log);
+ }
+ ldr(tmp1, Address(ary1, cnt1));
+ ldr(tmp2, Address(ary2, cnt1));
+ eor(tmp1, tmp1, tmp2);
+ cbnz(tmp1, DONE);
+ b(SAME);
- BIND(TAIL07); // 0-7 bytes left, cnt1 = #bytes left - 4
- tst(cnt1, 0b100);
- br(EQ, TAIL03);
+ bind(SHORT);
+ Label TAIL03, TAIL01;
+
+ tbz(cnt1, 2-exact_log, TAIL03);
ldrw(tmp1, Address(post(ary1, 4)));
ldrw(tmp2, Address(post(ary2, 4)));
cmp(tmp1, tmp2);
- br(NE, DIFFER);
+ br(NE, DONE);
- BIND(TAIL03); // 0-3 bytes left, cnt1 = #bytes left - 4
- tst(cnt1, 0b10);
- br(EQ, TAIL01);
+ bind(TAIL03);
+ tbz(cnt1, 1-exact_log, TAIL01);
ldrh(tmp1, Address(post(ary1, 2)));
ldrh(tmp2, Address(post(ary2, 2)));
cmp(tmp1, tmp2);
- br(NE, DIFFER);
- BIND(TAIL01); // 0-1 byte left
- tst(cnt1, 0b01);
- br(EQ, SAME);
+ br(NE, DONE);
+
+ bind(TAIL01);
+ if (step_size == 1) {
+ tbz(cnt1, 0, SAME);
ldrb(tmp1, ary1);
ldrb(tmp2, ary2);
cmp(tmp1, tmp2);
- br(NE, DIFFER);
-
- BIND(SAME);
- mov(result, true);
- BIND(DIFFER); // result already set
-
- BLOCK_COMMENT("} byte_arrays_equals");
-}
-
-// Compare char[] arrays aligned to 4 bytes
-void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
- Register result, Register tmp1)
-{
- Register cnt1 = rscratch1;
- Register cnt2 = rscratch2;
- Register tmp2 = rscratch2;
-
- Label SAME, DIFFER, NEXT, TAIL03, TAIL01;
-
- int length_offset = arrayOopDesc::length_offset_in_bytes();
- int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
-
- BLOCK_COMMENT("char_arrays_equals {");
-
- // different until proven equal
- mov(result, false);
-
- // same array?
- cmp(ary1, ary2);
- br(Assembler::EQ, SAME);
-
- // ne if either null
- cbz(ary1, DIFFER);
- cbz(ary2, DIFFER);
-
- // lengths ne?
- ldrw(cnt1, Address(ary1, length_offset));
- ldrw(cnt2, Address(ary2, length_offset));
- cmp(cnt1, cnt2);
- br(Assembler::NE, DIFFER);
-
- lea(ary1, Address(ary1, base_offset));
- lea(ary2, Address(ary2, base_offset));
-
- subs(cnt1, cnt1, 4);
- br(LT, TAIL03);
-
- BIND(NEXT);
- ldr(tmp1, Address(post(ary1, 8)));
- ldr(tmp2, Address(post(ary2, 8)));
- subs(cnt1, cnt1, 4);
- eor(tmp1, tmp1, tmp2);
- cbnz(tmp1, DIFFER);
- br(GE, NEXT);
-
- BIND(TAIL03); // 0-3 chars left, cnt1 = #chars left - 4
- tst(cnt1, 0b10);
- br(EQ, TAIL01);
- ldrw(tmp1, Address(post(ary1, 4)));
- ldrw(tmp2, Address(post(ary2, 4)));
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
- BIND(TAIL01); // 0-1 chars left
- tst(cnt1, 0b01);
- br(EQ, SAME);
- ldrh(tmp1, ary1);
- ldrh(tmp2, ary2);
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
-
- BIND(SAME);
+ br(NE, DONE);
+ }
+ // same
+ bind(SAME);
mov(result, true);
- BIND(DIFFER); // result already set
- BLOCK_COMMENT("} char_arrays_equals");
+ // That's it
+ bind(DONE);
+ BLOCK_COMMENT("} generic_arrays_equals");
}
// encode char[] to byte[] in ISO_8859_1
void MacroAssembler::encode_iso_array(Register src, Register dst,
Register len, Register result,
< prev index next >