@@ -1409,6 +1409,14 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2,
14091409 load_chr_insn str1_load_chr = str1_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu;
14101410 load_chr_insn str2_load_chr = str2_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu;
14111411
1412+ int base_offset1 = arrayOopDesc::base_offset_in_bytes (T_BYTE);
1413+ int base_offset2 = arrayOopDesc::base_offset_in_bytes (T_CHAR);
1414+
1415+ assert ((base_offset1 % (UseCompactObjectHeaders ? 4 :
1416+ (UseCompressedClassPointers ? 8 : 4 ))) == 0 , " Must be" );
1417+ assert ((base_offset2 % (UseCompactObjectHeaders ? 4 :
1418+ (UseCompressedClassPointers ? 8 : 4 ))) == 0 , " Must be" );
1419+
14121420 BLOCK_COMMENT (" string_compare {" );
14131421
14141422 // Bizarrely, the counts are passed in bytes, regardless of whether they
@@ -1426,6 +1434,24 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2,
14261434 mv (cnt2, cnt1);
14271435 bind (L);
14281436
1437+ // Load 4 bytes once to compare for alignment before main loop. Note that this
1438+ // is only possible for LL/UU case. We need to resort to load_long_misaligned
1439+ // for both LU and UL cases.
1440+ if (str1_isL == str2_isL) { // LL or UU
1441+ beq (str1, str2, DONE);
1442+ int base_offset = isLL ? base_offset1 : base_offset2;
1443+ if (AvoidUnalignedAccesses && (base_offset % 8 ) != 0 ) {
1444+ mv (t0, minCharsInWord / 2 );
1445+ ble (cnt2, t0, SHORT_STRING);
1446+ lwu (tmp1, Address (str1));
1447+ lwu (tmp2, Address (str2));
1448+ bne (tmp1, tmp2, DIFFERENCE);
1449+ addi (str1, str1, 4 );
1450+ addi (str2, str2, 4 );
1451+ subi (cnt2, cnt2, minCharsInWord / 2 );
1452+ }
1453+ }
1454+
14291455 // A very short string
14301456 mv (t0, minCharsInWord);
14311457 ble (cnt2, t0, SHORT_STRING);
@@ -1434,8 +1460,14 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2,
14341460 // load first parts of strings and finish initialization while loading
14351461 {
14361462 if (str1_isL == str2_isL) { // LL or UU
1437- // check if str1 and str2 is same pointer
1438- beq (str1, str2, DONE);
1463+ #ifdef ASSERT
1464+ Label align_ok;
1465+ orr (t0, str1, str2);
1466+ andi (t0, t0, 0x7 );
1467+ beqz (t0, align_ok);
1468+ stop (" bad alignment" );
1469+ bind (align_ok);
1470+ #endif
14391471 // load 8 bytes once to compare
14401472 ld (tmp1, Address (str1));
14411473 ld (tmp2, Address (str2));
@@ -1452,7 +1484,7 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2,
14521484 sub (cnt2, zr, cnt2);
14531485 } else if (isLU) { // LU case
14541486 lwu (tmp1, Address (str1));
1455- ld (tmp2, Address (str2));
1487+ load_long_misaligned (tmp2, Address (str2), tmp3, (base_offset2 % 8 ) != 0 ? 4 : 8 );
14561488 mv (t0, STUB_THRESHOLD);
14571489 bge (cnt2, t0, STUB);
14581490 subi (cnt2, cnt2, 4 );
@@ -1465,11 +1497,11 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2,
14651497 sub (cnt2, zr, cnt2);
14661498 addi (cnt1, cnt1, 4 );
14671499 } else { // UL case
1468- ld (tmp1, Address (str1));
1500+ load_long_misaligned (tmp1, Address (str1), tmp3, (base_offset2 % 8 ) != 0 ? 4 : 8 );
14691501 lwu (tmp2, Address (str2));
14701502 mv (t0, STUB_THRESHOLD);
14711503 bge (cnt2, t0, STUB);
1472- addi (cnt2, cnt2, - 4 );
1504+ subi (cnt2, cnt2, 4 );
14731505 slli (t0, cnt2, 1 );
14741506 sub (cnt1, zr, t0);
14751507 add (str1, str1, t0);
@@ -1486,6 +1518,7 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2,
14861518 // main loop
14871519 bind (NEXT_WORD);
14881520 if (str1_isL == str2_isL) { // LL or UU
1521+ // both of the two loads are 8-byte aligned
14891522 add (t0, str1, cnt2);
14901523 ld (tmp1, Address (t0));
14911524 add (t0, str2, cnt2);
@@ -1495,7 +1528,7 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2,
14951528 add (t0, str1, cnt1);
14961529 lwu (tmp1, Address (t0));
14971530 add (t0, str2, cnt2);
1498- ld (tmp2, Address (t0));
1531+ load_long_misaligned (tmp2, Address (t0), tmp3, (base_offset2 % 8 ) != 0 ? 4 : 8 );
14991532 addi (cnt1, cnt1, 4 );
15001533 inflate_lo32 (tmp3, tmp1);
15011534 mv (tmp1, tmp3);
@@ -1504,7 +1537,7 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2,
15041537 add (t0, str2, cnt2);
15051538 lwu (tmp2, Address (t0));
15061539 add (t0, str1, cnt1);
1507- ld (tmp1, Address (t0));
1540+ load_long_misaligned (tmp1, Address (t0), tmp3, (base_offset2 % 8 ) != 0 ? 4 : 8 );
15081541 inflate_lo32 (tmp3, tmp2);
15091542 mv (tmp2, tmp3);
15101543 addi (cnt1, cnt1, 8 );
@@ -1637,6 +1670,9 @@ void C2_MacroAssembler::arrays_equals(Register a1, Register a2,
16371670 int length_offset = arrayOopDesc::length_offset_in_bytes ();
16381671 int base_offset = arrayOopDesc::base_offset_in_bytes (elem_size == 2 ? T_CHAR : T_BYTE);
16391672
1673+ assert ((base_offset % (UseCompactObjectHeaders ? 4 :
1674+ (UseCompressedClassPointers ? 8 : 4 ))) == 0 , " Must be" );
1675+
16401676 Register cnt1 = tmp3;
16411677 Register cnt2 = tmp1; // cnt2 only used in array length compare
16421678 Label DONE, SAME, NEXT_WORD, SHORT, TAIL03, TAIL01;
@@ -1660,10 +1696,31 @@ void C2_MacroAssembler::arrays_equals(Register a1, Register a2,
16601696
16611697 la (a1, Address (a1, base_offset));
16621698 la (a2, Address (a2, base_offset));
1699+
1700+ // Load 4 bytes once to compare for alignment before main loop.
1701+ if (AvoidUnalignedAccesses && (base_offset % 8 ) != 0 ) {
1702+ subi (cnt1, cnt1, elem_per_word / 2 );
1703+ bltz (cnt1, TAIL03);
1704+ lwu (tmp1, Address (a1));
1705+ lwu (tmp2, Address (a2));
1706+ addi (a1, a1, 4 );
1707+ addi (a2, a2, 4 );
1708+ bne (tmp1, tmp2, DONE);
1709+ }
1710+
16631711 // Check for short strings, i.e. smaller than wordSize.
16641712 subi (cnt1, cnt1, elem_per_word);
16651713 bltz (cnt1, SHORT);
16661714
1715+ #ifdef ASSERT
1716+ Label align_ok;
1717+ orr (t0, a1, a2);
1718+ andi (t0, t0, 0x7 );
1719+ beqz (t0, align_ok);
1720+ stop (" bad alignment" );
1721+ bind (align_ok);
1722+ #endif
1723+
16671724 // Main 8 byte comparison loop.
16681725 bind (NEXT_WORD); {
16691726 ld (tmp1, Address (a1));
@@ -1729,20 +1786,45 @@ void C2_MacroAssembler::arrays_equals(Register a1, Register a2,
17291786void C2_MacroAssembler::string_equals (Register a1, Register a2,
17301787 Register result, Register cnt1)
17311788{
1732- Label SAME, DONE, SHORT, NEXT_WORD;
1789+ Label SAME, DONE, SHORT, NEXT_WORD, TAIL03, TAIL01 ;
17331790 Register tmp1 = t0;
17341791 Register tmp2 = t1;
17351792
17361793 assert_different_registers (a1, a2, result, cnt1, tmp1, tmp2);
17371794
1795+ int base_offset = arrayOopDesc::base_offset_in_bytes (T_BYTE);
1796+
1797+ assert ((base_offset % (UseCompactObjectHeaders ? 4 :
1798+ (UseCompressedClassPointers ? 8 : 4 ))) == 0 , " Must be" );
1799+
17381800 BLOCK_COMMENT (" string_equals {" );
17391801
17401802 mv (result, false );
17411803
1804+ // Load 4 bytes once to compare for alignment before main loop.
1805+ if (AvoidUnalignedAccesses && (base_offset % 8 ) != 0 ) {
1806+ subi (cnt1, cnt1, 4 );
1807+ bltz (cnt1, TAIL03);
1808+ lwu (tmp1, Address (a1));
1809+ lwu (tmp2, Address (a2));
1810+ addi (a1, a1, 4 );
1811+ addi (a2, a2, 4 );
1812+ bne (tmp1, tmp2, DONE);
1813+ }
1814+
17421815 // Check for short strings, i.e. smaller than wordSize.
17431816 subi (cnt1, cnt1, wordSize);
17441817 bltz (cnt1, SHORT);
17451818
1819+ #ifdef ASSERT
1820+ Label align_ok;
1821+ orr (t0, a1, a2);
1822+ andi (t0, t0, 0x7 );
1823+ beqz (t0, align_ok);
1824+ stop (" bad alignment" );
1825+ bind (align_ok);
1826+ #endif
1827+
17461828 // Main 8 byte comparison loop.
17471829 bind (NEXT_WORD); {
17481830 ld (tmp1, Address (a1));
@@ -1757,8 +1839,6 @@ void C2_MacroAssembler::string_equals(Register a1, Register a2,
17571839 beqz (tmp1, SAME);
17581840
17591841 bind (SHORT);
1760- Label TAIL03, TAIL01;
1761-
17621842 // 0-7 bytes left.
17631843 test_bit (tmp1, cnt1, 2 );
17641844 beqz (tmp1, TAIL03);
@@ -2512,6 +2592,9 @@ void C2_MacroAssembler::arrays_equals_v(Register a1, Register a2, Register resul
25122592 int length_offset = arrayOopDesc::length_offset_in_bytes ();
25132593 int base_offset = arrayOopDesc::base_offset_in_bytes (elem_size == 2 ? T_CHAR : T_BYTE);
25142594
2595+ assert ((base_offset % (UseCompactObjectHeaders ? 4 :
2596+ (UseCompressedClassPointers ? 8 : 4 ))) == 0 , " Must be" );
2597+
25152598 BLOCK_COMMENT (" arrays_equals_v {" );
25162599
25172600 // if (a1 == a2), return true
0 commit comments