< prev index next >

src/cpu/aarch64/vm/macroAssembler_aarch64.cpp

Print this page

        

*** 4479,4707 **** 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) { ! Register cnt1 = rscratch1; ! Register cnt2 = rscratch2; Register tmp2 = rscratch2; ! ! Label SAME, DIFFER, NEXT, TAIL07, TAIL03, TAIL01; ! int length_offset = arrayOopDesc::length_offset_in_bytes(); ! int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE); ! ! BLOCK_COMMENT("byte_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, 8); ! br(LT, TAIL07); ! ! BIND(NEXT); ! ldr(tmp1, Address(post(ary1, 8))); ! ldr(tmp2, Address(post(ary2, 8))); ! subs(cnt1, cnt1, 8); ! eor(tmp1, tmp1, tmp2); ! cbnz(tmp1, DIFFER); ! br(GE, NEXT); ! BIND(TAIL07); // 0-7 bytes left, cnt1 = #bytes left - 4 ! tst(cnt1, 0b100); ! br(EQ, TAIL03); ! ldrw(tmp1, Address(post(ary1, 4))); ! ldrw(tmp2, Address(post(ary2, 4))); ! cmp(tmp1, tmp2); ! br(NE, DIFFER); ! ! BIND(TAIL03); // 0-3 bytes left, cnt1 = #bytes left - 4 ! tst(cnt1, 0b10); ! br(EQ, 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); ! 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); mov(result, true); - BIND(DIFFER); // result already set ! BLOCK_COMMENT("} char_arrays_equals"); } // encode char[] to byte[] in ISO_8859_1 void MacroAssembler::encode_iso_array(Register src, Register dst, Register len, Register result, FloatRegister Vtmp1, FloatRegister Vtmp2, FloatRegister Vtmp3, FloatRegister Vtmp4) --- 4479,4609 ---- bind(DONE); BLOCK_COMMENT("} string_compare"); } + // Compare Strings or char/byte arrays. ! // is_string is true iff this is a string comparison. ! // For Strings we're passed the address of the first characters in a1 ! // and a2 and the length in cnt1. ! // For byte and char arrays we're passed the arrays themselves and we ! // have to extract length fields and do null checks here. ! // elem_size is the element size in bytes: either 1 or 2. ! // There are two implementations. For arrays >= 8 bytes, all ! // comparisons (including the final one, which may overlap) are ! // performed 8 bytes at a time. For arrays < 8 bytes, we compare a ! // halfword, then a short, and then a byte. ! void MacroAssembler::arrays_equals(Register a1, Register a2, ! Register result, Register cnt1, ! int elem_size, bool is_string) { ! Label SAME, DONE, SHORT, NEXT_WORD; ! Register tmp1 = rscratch1; Register tmp2 = rscratch2; ! Register cnt2 = tmp2; // cnt2 only used in array length compare ! int elem_per_word = wordSize/elem_size; ! int log_elem_size = exact_log2(elem_size); int length_offset = arrayOopDesc::length_offset_in_bytes(); ! int base_offset ! = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); ! assert(elem_size == 1 || elem_size == 2, "must be char or byte"); ! assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2); ! BLOCK_COMMENT(is_string ? "string_equals {" : "array_equals {"); ! mov(result, false); ! if (! is_string) { ! // if (a==a2) ! // return true; ! eor(rscratch1, a1, a2); ! cbz(rscratch1, SAME); ! // if (a==null || a2==null) ! // return false; ! cbz(a1, DONE); ! cbz(a2, DONE); ! // if (a1.length != a2.length) ! // return false; ! ldrw(cnt1, Address(a1, length_offset)); ! ldrw(cnt2, Address(a2, length_offset)); ! eorw(rscratch1, cnt1, cnt2); ! cbnzw(rscratch1, DONE); ! lea(a1, Address(a1, base_offset)); ! lea(a2, Address(a2, base_offset)); ! } ! // Check for short strings, i.e. smaller than wordSize. ! subs(cnt1, cnt1, elem_per_word); ! br(Assembler::LT, SHORT); ! ! // Main 8 byte comparison loop. ! bind(NEXT_WORD); { ! ldr(tmp1, Address(post(a1, wordSize))); ! ldr(tmp2, Address(post(a2, wordSize))); ! subs(cnt1, cnt1, elem_per_word); ! eor(tmp1, tmp1, tmp2); ! 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 == 4. ! if (log_elem_size > 0) ! lsl(cnt1, cnt1, log_elem_size); ! ldr(tmp1, Address(a1, cnt1)); ! ldr(tmp2, Address(a2, cnt1)); eor(tmp1, tmp1, tmp2); ! cbnz(tmp1, DONE); ! b(SAME); ! bind(SHORT); ! Label TAIL03, TAIL01; ! tbz(cnt1, 2 - log_elem_size, TAIL03); // 0-7 bytes left. ! { ! ldrw(tmp1, Address(post(a1, 4))); ! ldrw(tmp2, Address(post(a2, 4))); ! eorw(tmp1, tmp1, tmp2); ! cbnzw(tmp1, DONE); ! } ! bind(TAIL03); ! tbz(cnt1, 1 - log_elem_size, TAIL01); // 0-3 bytes left. ! { ! ldrh(tmp1, Address(post(a1, 2))); ! ldrh(tmp2, Address(post(a2, 2))); ! eorw(tmp1, tmp1, tmp2); ! cbnzw(tmp1, DONE); ! } ! bind(TAIL01); ! if (elem_size == 1) { // Only needed when comparing byte arrays. ! tbz(cnt1, 0, SAME); // 0-1 bytes left. ! { ! ldrb(tmp1, a1); ! ldrb(tmp2, a2); ! eorw(tmp1, tmp1, tmp2); ! cbnzw(tmp1, DONE); ! } ! } ! // Arrays are equal. ! bind(SAME); mov(result, true); ! // That's it. ! bind(DONE); ! BLOCK_COMMENT(is_string ? "} string_equals" : "} array_equals"); } + // encode char[] to byte[] in ISO_8859_1 void MacroAssembler::encode_iso_array(Register src, Register dst, Register len, Register result, FloatRegister Vtmp1, FloatRegister Vtmp2, FloatRegister Vtmp3, FloatRegister Vtmp4)
< prev index next >