< prev index next >

src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp

Print this page


   1 /*
   2  * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.


4844     b(MATCH);
4845 
4846   BIND(DO1_SHORT);
4847     mov(result_tmp, cnt1);
4848     lea(str1, Address(str1, cnt1, Address::uxtw(1)));
4849     sub(cnt1_neg, zr, cnt1, LSL, 1);
4850   BIND(DO1_LOOP);
4851     ldrh(ch1, Address(str1, cnt1_neg));
4852     cmpw(ch, ch1);
4853     br(EQ, MATCH);
4854     adds(cnt1_neg, cnt1_neg, 2);
4855     br(LT, DO1_LOOP);
4856   BIND(NOMATCH);
4857     mov(result, -1);
4858     b(DONE);
4859   BIND(MATCH);
4860     add(result, result_tmp, cnt1_neg, ASR, 1);
4861   BIND(DONE);
4862 }
4863 
4864 // Compare strings.




































































































































































































































































































































4865 void MacroAssembler::string_compare(Register str1, Register str2,
4866     Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2,
4867     FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, int ae) {
4868   Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB,
4869       DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT,
4870       SHORT_LOOP_START, TAIL_CHECK;
4871 
4872   const u1 STUB_THRESHOLD = 64 + 8;
4873   bool isLL = ae == StrIntrinsicNode::LL;
4874   bool isLU = ae == StrIntrinsicNode::LU;
4875   bool isUL = ae == StrIntrinsicNode::UL;
4876 
4877   bool str1_isL = isLL || isLU;
4878   bool str2_isL = isLL || isUL;
4879 
4880   int str1_chr_shift = str1_isL ? 0 : 1;
4881   int str2_chr_shift = str2_isL ? 0 : 1;
4882   int str1_chr_size = str1_isL ? 1 : 2;
4883   int str2_chr_size = str2_isL ? 1 : 2;
4884   int minCharsInWord = isLL ? wordSize : wordSize/2;


   1 /*
   2  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.


4844     b(MATCH);
4845 
4846   BIND(DO1_SHORT);
4847     mov(result_tmp, cnt1);
4848     lea(str1, Address(str1, cnt1, Address::uxtw(1)));
4849     sub(cnt1_neg, zr, cnt1, LSL, 1);
4850   BIND(DO1_LOOP);
4851     ldrh(ch1, Address(str1, cnt1_neg));
4852     cmpw(ch, ch1);
4853     br(EQ, MATCH);
4854     adds(cnt1_neg, cnt1_neg, 2);
4855     br(LT, DO1_LOOP);
4856   BIND(NOMATCH);
4857     mov(result, -1);
4858     b(DONE);
4859   BIND(MATCH);
4860     add(result, result_tmp, cnt1_neg, ASR, 1);
4861   BIND(DONE);
4862 }
4863 
4864 // Summary: Compare strings intrinsic implementation. All combinations of UTF-16
4865 //          and Latin1 encodings for both strings are considered. Comparison
4866 //          is performed in lexical order.
4867 //
4868 // Input:   str1: pointer to 1st string
4869 //          str2: pointer to 2nd string
4870 //          cnt1: number of bytes in 1st string
4871 //          cnt2: number of bytes in 2nd string
4872 //
4873 // Algorithm parameter:
4874 //          ae: encodings used in 1st and 2nd strings
4875 //
4876 // Temporary registers:
4877 //          tmp1, tmp2, rscratch1, rscratch2: always used
4878 //          vtmp1, vtmp2, vtmp3: used in case encodings are different
4879 //
4880 // Output:  result - return 0 if strings are equal. Returns positive value
4881 //          if 1st string > 2nd string in lexical order. Returns
4882 //          negative value if 1st string < 2nd string.
4883 //
4884 // Side effects: str1, str2, cnt1, cnt2, tmp1, tmp2, rscratch1, rscratch2: clobbered.
4885 //               vtmp1, vtmp2, vtmp2: clobbered if encodings are different
4886 //
4887 // Additional data: boolean values: isLL, isLU, isUL, str1_isL, str2_isL and
4888 // int minCharInWords are derived from ae parameter based on encodings used
4889 // in strings. Different code is generated depending of these values:
4890 //
4891 // isLL = both strings are Latin1
4892 // isLU = 1st string is Latin1, 2nd string is UTF-16
4893 // isUL = 1st string is UTF-16, 2nd string is Latin1
4894 // str1_isL = 1st string is Latin1
4895 // str2_isL = 2nd string is Latin1
4896 // str1_chr_shift = shift value to convert between characters counter to byte counter for 1st string
4897 // str2_chr_shift = shift value to convert between characters counter to byte counter for 2nd string
4898 // minCharInWords = minimum number of characters that fit in register (8 for LL case, 4 otherwise)
4899 //
4900 //
4901 // PSEUDO CODE:
4902 //
4903 // // N.B.: this pseudo-code doesn't strictly follow implementation details.
4904 // // It is here to help understand the basics. Detailed implementation
4905 // // description is listed after this code.
4906 //
4907 // <convert byte counters cnt1, cnt2 into character counters if UTF-16 encoding is used>;
4908 // result = cnt1 - cnt2; // length difference. Used in if all min(cnt1, cnt2) characters are same
4909 // cnt2 = min(cnt1, cnt2); // amount of characters to check
4910 // if (result <= minCharInWords) { // <= wordSize bytes should be loaded for comparison
4911 //   if (cnt2 == 0) return result;
4912 //   while (cnt2 != 0) {
4913 //     char str1char = str1[0];
4914 //     char str2char = str2[0];
4915 //     str1 += 1 << str1_chr_shift; // advance pointer by size of str1 character
4916 //     str2 += 1 << str2_chr_shift; // advance pointer by size of str2 character
4917 //     if (str1[0] != str2[0]) return str1[0] - str2[0];
4918 //     cnt2--;
4919 //   }
4920 // } else { // > wordSize bytes should be loaded for comparison
4921 //     // This code checks string in 8-byte blocks. If encodings are
4922 //     // different, Latin1 string will be loaded via 4-byte blocks and then
4923 //     // each block will be converted to 8-byte UTF-16 equivalent. Then 8 byte
4924 //     // blocks are compared. Each load is 8 characters for LL case and 4
4925 //     // characters for LU/UL/UU.
4926 //     // This set of instructions (load 8 Latin1 character OR load 4 Latin1
4927 //     // characters and convert it to 4 UTF-16 character OR load 4 UTF-16
4928 //     // character) is referred as <load-and-probably-convert ...> below.
4929 //
4930 //     // First iteration in the loop is unrolled to add initialization.
4931 //
4932 //     // The code below calculates addresses of each string last load: addresses
4933 //     // of last 8 characters for LL case and last 4 characters otherwise.
4934 //     // Then offsets from the addresses to the beginning of the strings are
4935 //     // calculated. Offset is then use as loop counter. When offset is >= 0, then
4936 //     // only last loads (possible overlapped) are left to be checked.
4937 //     // N.B.: in case of same encodings, offsets are the same for both strings.
4938 //     // Then offset for 2nd string is used for both strings.
4939 //
4940 //     tmp1 = <load-and-probably-convert str1>;
4941 //     if (str1 == str2) return result;
4942 //     tmp2 = <load-and-probably-convert str2>;
4943 //
4944 //     // use special implementation optimized for large strings. See detailed code and stub comments.
4945 //     if (cnt2 >= 72) return compare_long_string_implementation(<args>);
4946 //
4947 //     cnt2 -= <amount of loaded characters>; // 8 for isLL case. 4 otherwise.
4948 //
4949 //     if (str1_isL == str2_isL) {
4950 //       // Optional optimization for same encoding cases. Can be applied for all
4951 //       // cases, but is faster in same encoding cases only. Without this branch
4952 //       // smallest string (8 character for LL and 4 characters for others) would
4953 //       // be checked twice.
4954 //       if (cnt2 == 0) goto TAIL_CHECK; // no more characters to be loaded. Just check already loaded data.
4955 //     }
4956 //
4957 //     // calculate addresses of last loads. use str1 and str2 pointers for that
4958 //     str1 = str1 + cnt2 << str1_chr_shift;
4959 //     str2 = str2 + cnt2 << str2_chr_shift;
4960 //
4961 //     // calculate offsets for both strings. cnt1 and cnt2 can be reused
4962 //     if (str1_isL != str2_isL) cnt1 = - (cnt2 << str1_chr_shift);
4963 //     cnt2 = - (cnt2 << str2_chr_shift);
4964 //
4965 //     // increment calculated offsets by the number of already loaded bytes
4966 //     if (isLU) cnt1 += 4;
4967 //     if (isUL) cnt1 += 8;
4968 //     cnt2 += isUL ? 4 : 8;
4969 //
4970 //     if (cnt2 >= 0) goto TAIL; // only last loads remains. Still need to check currently loaded data.
4971 //
4972 //     rscratch2 = tmp1 BIT_XOR tmp2;
4973 //     if (rscratch2 != 0) goto DIFFERENCE;
4974 //
4975 //     // main loop. Label = NEXT_WORD
4976 //     do {
4977 //       tmp1 = <load-and-probably-convert str1 at offset of (str1_isL == str2_isL ? cnt2 : cnt1)>;
4978 //       tmp2 = <load-and-probably-convert str2 at offset of cnt2>;
4979 //
4980 //       // update offsets by the number of loaded bytes
4981 //       cnt2 += isUL ? 4 : 8;
4982 //       if (isLU) cnt1 += 4;
4983 //       if (isUL) cnt1 += 8;
4984 //
4985 //       if (cnt2 >= 0) goto TAIL; // last block left to be loaded. Still need to check currently loaded block.
4986 //       rscratch2 = tmp1 BIT_XOR tmp2;
4987 //     } while (rscratch2 == 0);
4988 //     goto DIFFERENCE:
4989 //
4990 //   TAIL: // last block left to be loaded. Still need to check currently loaded block.
4991 //     rscratch2 = tmp1 BIT_XOR tmp2;
4992 //     if (rscratch2 != 0) goto DIFFERENCE;
4993 //     tmp1 = <load-and-probably-convert str1>;
4994 //     tmp2 = <load-and-probably-convert str2>;
4995 //     // fallthrough to TAIL_CHECK
4996 //   TAIL_CHECK:
4997 //     rscratch2 = tmp1 BIT_XOR tmp2;
4998 //     if (rscratch2 == 0) return result;
4999 //   DIFFERENCE: // different character found. Find it and compute difference
5000 //     // tmp1 and tmp2 have current data with at least 1 different character.
5001 //     // Find index of first such character.
5002 //     rscratch2 = REVERSE_BITS(rscratch2);
5003 //     rscratch2 = COUNT_LEADING_ZEROES(rscratch2); // position of different bit in current 8 bytes
5004 //     rscratch2 = rscratch2 & (isLL ? -8 : -16); // number of bits until (possibly converted) different characters in tmp1 and tmp2
5005 //     tmp1 = tmp1 >> rscratch2; // now first character in tmp1 is the one sought for
5006 //     tmp1 = tmp1 & (isLL ? 0xFF : 0xFFFF); // only first different character left
5007 //     tmp2 = tmp2 >> rscratch2; // now first character in tmp2 is the one sought for
5008 //     tmp2 = tmp2 & (isLL ? 0xFF : 0xFFFF); // only first different character left
5009 //     result = tmp1 - tmp2;
5010 // }
5011 // return result;
5012 //
5013 //
5014 //
5015 // DETAILED CODE:
5016 //
5017 //  if (!str1_isL) cnt1 = cnt1 >> 1;                // counter for 1st string (in characters)
5018 //  if (!str2_isL) cnt2 = cnt2 >> 1;                // counter for 2nd string (in characters)
5019 //  result = cnt1 - cnt2;                           // keep in flags the result of operation
5020 //  cnt2 = min(cnt1, cnt2);                         // implemented as csel instruction using stored flag value above
5021 //  bool shortStringsCase = cnt2 <= minCharInWords; // kept in flag
5022 //  if (shortStringsCase) goto SHORT_STRING;        // separate code for short strings
5023 //  if (str1_isL == str2_isL) {                     // same encoding case
5024 //    tmp1 = LOAD8BYTES(str1);
5025 //    bool sameString = str1 == str2;               // kept in flags
5026 //    if (sameString) goto DONE;                    // the string is the same, return
5027 //    tmp2 = LOAD8BYTES(str2);
5028 //    bool largeStrings = cnt2 >= 72;               // kept in flags
5029 //    if (largeStrings) goto STUB;                  // handled in separate stub implementation for large strings
5030 //    cnt2 = cnt2 - minCharsInWord;                 // decrement counter by the number of loaded characters
5031 //    bool noMoreLoadsAvailable = cnt2 == 0;        // kept in flags
5032 //    if (noMoreLoadsAvailable) goto TAIL_CHECK;
5033 //    str2 = str2 + cnt2 << str2_chr_shift;         // address of str2 last load
5034 //    str1 = str1 + cnt2 << str1_chr_shift;         // address of str1 last load
5035 //    cnt2 = -(cnt2 << str2_chr_shift);             // byte offset to 1st character in each string
5036 //  } else if (isLU) {
5037 //    vtmp = LOAD4BYTES(str1);
5038 //    bool sameString = str1 == str2;               // kept in flags
5039 //    if (sameString) goto DONE;                    // return
5040 //    tmp2 = LOAD8BYTES(str2);
5041 //    bool largeStrings = cnt2 >= 72;               // kept in flags
5042 //    if (largeStrings) goto STUB;                  // handled in separate stub implementation for large strings
5043 //    cnt2 = cnt2 - 4;                              // decrement counter by the number  of loaded characters
5044 //    vtmpz = 0;                                    // implemented as eor
5045 //    str1 = str1 + cnt2 << str1_chr_shift;         // address of str1 last load
5046 //    str2 = str2 + cnt2 << str2_chr_shift;         // address of str2 last load
5047 //    vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz);  // convert Latin1 to UTF16 because it'll be compared with UTF16. Implemented as zip instruction
5048 //    cnt1 = -(cnt2 << str1_chr_shift);             // byte offset to 1st character in 1st string
5049 //    cnt2 = -(cnt2 << str2_chr_shift);             // byte offset to 1st character in 2nd string
5050 //    cnt1 = cnt1 + 4;                              // advance 1st string offset by the number of loaded bytes
5051 //    tmp1 = vtmp;                                  // move converted characters from FPU register to GPR
5052 //  } else { // UL
5053 //    tmp1 = LOAD8BYTES(str1);
5054 //    bool sameString = str1 == str2;               // kept in flags
5055 //    if (sameString) goto DONE;                    // return
5056 //    vtmp = LOAD4BYTES(str2);
5057 //    bool largeStrings = cnt2 >= 72;               // kept in flags
5058 //    if (largeStrings) goto STUB;                  // separate stub implementation for large strings
5059 //    cnt2 = cnt2 - 4;                              // update counter by the number of loaded characters
5060 //    str1 = str1 + cnt2 << str1_chr_shift;         // address of str1 last load
5061 //    vtmpz = 0;                                    // implemented as eor
5062 //    str2 = str2 + cnt2 << str2_chr_shift;         // address of str2 last load
5063 //    cnt1 = -(cnt2 << str1_chr_shift);             // byte offset to 1st character in 1st string
5064 //    vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz);  // convert Latin1 to UTF16 because it'll be compared with UTF16. implemented as zip instruction
5065 //    cnt2 = -(cnt2 << str2_chr_shift);             // byte offset to 1st character in 2nd string
5066 //    cnt1 = cnt1 + 8;                              // advance 1st string offset by the number of loaded bytes
5067 //    tmp2 = vtmp;                                  // move converted characters from FPU register to GPR
5068 //  }
5069 //  cnt2 = cnt2 + (isUL ? 4 : 8);                   // update offset by the number of loaded bytes
5070 //  bool onlyLastLoadRemains = cnt2 >= 0;           // kept in flags
5071 //  if (onlyLastLoadRemains) goto TAIL;
5072 //  rscratch2 = BIT_XOR(tmp1, tmp2);                // current block comparison result
5073 //  if (rscratch2 != 0) goto DIFFERENCE;            // found different characters in current block
5074 // NEXT_WORD:                                       // main loop
5075 //  // implementation for each encoding loads 4 or 8 characters at calculated
5076 //  // offsets from each string and convert encodings if necessary. Then offsets
5077 //  // are updated.
5078 //  if (str1_isL == str2_isL) {
5079 //    tmp1 = LOAD8BYTES(str1, cnt2);
5080 //    tmp2 = LOAD8BYTES(str2, cnt2);
5081 //    cnt2 = cnt2 + 8;                              // update counter by the number of loaded bytes
5082 //    onlyLastLoadRemains = cnt2 >= 0;              // kept in flags
5083 //  } else if (isLU) {
5084 //    vtmp = LOAD4BYTES(str1, cnt1);
5085 //    tmp2 = LOAD8BYTES(str2, cnt2);
5086 //    cnt1 = cnt1 + 4;
5087 //    vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz);
5088 //    tmp1 = vtmp;
5089 //    cnt2 = cnt2 + 8;
5090 //    onlyLastLoadRemains = cnt2 >= 0;              // kept in flags
5091 //  } else { // UL
5092 //    vtmp = LOAD4BYTES(str2, cnt2);
5093 //    tmp1 = LOAD8BYTES(str1, cnt1);
5094 //    vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz);
5095 //    cnt1 = cnt1 + 8;
5096 //    tmp2 = vtmp;
5097 //    cnt2 = cnt2 + 4;
5098 //    onlyLastLoadRemains = cnt2 >= 0;              // kept in flags
5099 //  }
5100 //  if (onlyLastLoadRemains) goto TAIL;
5101 //  rscratch2 = BIT_XOR(tmp1, tmp2);                // current block comparison result
5102 //  if (rscratch2 == 0) goto NEXT_WORD;
5103 //  goto DIFFERENCE;
5104 // TAIL: // check already loaded data and last load
5105 //  rscratch2 = BIT_XOR(tmp1, tmp2);                // current block comparison result
5106 //  if (rscratch2 != 0) goto DIFFERENCE;
5107 //
5108 //  // last load (and convert if needed) from each string
5109 //  if (str1_isL == str2_isL) {
5110 //    tmp1 = LOAD8BYTES(str1);
5111 //    tmp2 = LOAD8BYTES(str2);
5112 //  } else if (isLU) {
5113 //    vtmp = LOAD4BYTES(str1);
5114 //    tmp2 = LOAD8BYTES(str2);
5115 //    vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz);
5116 //    tmp1 = vtmp;
5117 //  } else { // UL
5118 //    vtmp = LOAD4BYTES(str2);
5119 //    tmp1 = LOAD8BYTES(str1);
5120 //    vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz);
5121 //    tmp2 = vtmp;
5122 //  }
5123 // TAIL_CHECK:                                      // last check
5124 //  rscratch2 = BIT_XOR(tmp1, tmp2);                // current block comparison result
5125 //  if (rscratch2 == 0) goto DONE;                  // return
5126 // DIFFERENCE:
5127 //  rscratch2 = REVERSE_BITS(rscratch2);            // It's not possible to count trailing zeroes. Reverse bits and then count leading zeroes instead.
5128 //  rscratch2 = COUNT_LEADING_ZEROES(rscratch2);    // position of different bit in current 8 bytes
5129 //  rscratch2 = rscratch2 & (isLL ? -8 : -16);      // number of bits until (possibly converted) different characters in tmp1 and tmp2
5130 //  tmp1 = tmp1 >> rscratch2;                       // first character in tmp1 is the one sought for
5131 //  tmp1 = isLL ? UNSIGNED_EXTEND_BYTE2INT(tmp1) : UNSIGNED_EXTEND_SHORT2INT(tmp1); // only first different character left
5132 //  tmp2 = tmp2 >> rscratch2;                       // first character in tmp2 is the one sought for
5133 //  tmp2 = isLL ? UNSIGNED_EXTEND_BYTE2INT(tmp2) : UNSIGNED_EXTEND_SHORT2INT(tmp1); // only first different character left
5134 //  result = tmp1 - tmp2;
5135 //  goto DONE;
5136 // }
5137 //
5138 // STUB:
5139 //  <get address of compare_long_string_[LL|UU|LU|UL] stub routine and call it>
5140 //  goto DONE;
5141 //
5142 // // Short strings comparison code. Instead of simple per-character loop with
5143 // // load-and-compare code it uses loop than issues 2 per-character loads from
5144 // // each string per iteration. Different registers are used for that to
5145 // // remove dependencies: (tmp1, cnt1) and (tmp2, rscratch1) pairs.
5146 // // First characters loads are issued in pre-loop.
5147 // SHORT_STRING:
5148 //  if (cnt2 == 0) goto DONE;                       // no characters to compare. Length difference (already calculated) should be used as result
5149 //  tmp1 = LOAD_STR1_CHAR(str1);
5150 //  str1 = str1 + str1_chr_size);                   // merged with load above as post-increment
5151 //  cnt2 = cnt2 - 1;                                // calculate remaining length after first character is loaded
5152 //  bool endReached = cnt2 == 0;                    // kept in flags
5153 //  if (endReached) goto SHORT_LAST_INIT;           // load 1 character to complete from 2nd string to complete init and compare it with 1st string character
5154 //  cnt1 = LOAD_STR2_CHAR(str2);
5155 //  str2 = str2 + str2_chr_size;                    // merged with load above as post-increment
5156 //  goto SHORT_LOOP_START;                          // per-character loop entry point
5157 // SHORT_LOOP:                                      // per-character loop
5158 //  cnt2 = cnt2 - 1;                                // calculate remaining length
5159 //  endReached = cnt2 == 0;
5160 //  if (endReached) goto SHORT_LAST_INIT;
5161 // SHORT_LOOP_START:                                // per-character loop entry point
5162 //  tmp2 = LOAD_STR1_CHAR(str1);
5163 //  rscratch1 = LOAD_STR2_CHAR(str2);
5164 //  bool differentResult = tmp1 != cnt1;            // check difference of previously loaded pair of registers while last pair is still loading. Kept in flags
5165 //  if (differentResult) goto SHORT_LOOP_TAIL;      // calculate character difference and return
5166 //  cnt2 = cnt2 - 1;                                // calculate remaining length
5167 //  endReached = cnt2 == 0;
5168 //  if (endReached) goto SHORT_LAST2;               // last comparison of second pair of registers (tmp2, rscratch1) is left
5169 //  tmp1 = LOAD_STR1_CHAR(str1);
5170 //  cnt1 = LOAD_STR2_CHAR(str2);
5171 //  bool sameResult = tmp2 == rscratch1;            // check difference of previously loaded pair of registers while last pair is still loading. Kept in flags
5172 //  if (sameResult) goto SHORT_LOOP;
5173 //  result = tmp2 - rscratch1;
5174 //  goto DONE;
5175 // SHORT_LAST2:                                     // last comparison is left: (tmp2, rscratch1)
5176 //  sameResult = tmp2 == rscratch1;
5177 //  if (sameResult) goto DONE;
5178 //  result = tmp2 - rscratch1;
5179 //  goto DONE;
5180 // SHORT_LAST_INIT:
5181 //  cnt1 = LOAD_STR2_CHAR(str2);
5182 // SHORT_LAST:                                      // last comparison of second pair of registers (tmp1, cnt1) is left
5183 //  sameResult = tmp1 == cnt1;
5184 //  if (sameResult) goto DONE;
5185 //  result = tmp1 - cnt1;
5186 // DONE:
5187 //  return;                                         // result
5188 
5189 void MacroAssembler::string_compare(Register str1, Register str2,
5190     Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2,
5191     FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, int ae) {
5192   Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB,
5193       DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT,
5194       SHORT_LOOP_START, TAIL_CHECK;
5195 
5196   const u1 STUB_THRESHOLD = 64 + 8;
5197   bool isLL = ae == StrIntrinsicNode::LL;
5198   bool isLU = ae == StrIntrinsicNode::LU;
5199   bool isUL = ae == StrIntrinsicNode::UL;
5200 
5201   bool str1_isL = isLL || isLU;
5202   bool str2_isL = isLL || isUL;
5203 
5204   int str1_chr_shift = str1_isL ? 0 : 1;
5205   int str2_chr_shift = str2_isL ? 0 : 1;
5206   int str1_chr_size = str1_isL ? 1 : 2;
5207   int str2_chr_size = str2_isL ? 1 : 2;
5208   int minCharsInWord = isLL ? wordSize : wordSize/2;


< prev index next >