src/cpu/x86/vm/macroAssembler_x86.cpp

Print this page


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


6177 
6178   xorptr(tmp, tmp);
6179   if (UseFastStosb) {
6180     shlptr(cnt,3); // convert to number of bytes
6181     rep_stosb();
6182   } else {
6183     NOT_LP64(shlptr(cnt,1);) // convert to number of dwords for 32-bit VM
6184     rep_stos();
6185   }
6186 }
6187 
6188 // IndexOf for constant substrings with size >= 8 chars
6189 // which don't need to be loaded through stack.
6190 void MacroAssembler::string_indexofC8(Register str1, Register str2,
6191                                       Register cnt1, Register cnt2,
6192                                       int int_cnt2,  Register result,
6193                                       XMMRegister vec, Register tmp) {
6194   ShortBranchVerifier sbv(this);
6195   assert(UseSSE42Intrinsics, "SSE4.2 is required");
6196 
6197   // This method uses pcmpestri inxtruction with bound registers
6198   //   inputs:
6199   //     xmm - substring
6200   //     rax - substring length (elements count)
6201   //     mem - scanned string
6202   //     rdx - string length (elements count)
6203   //     0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
6204   //   outputs:
6205   //     rcx - matched index in string
6206   assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
6207 
6208   Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR,
6209         RET_FOUND, RET_NOT_FOUND, EXIT, FOUND_SUBSTR,
6210         MATCH_SUBSTR_HEAD, RELOAD_STR, FOUND_CANDIDATE;
6211 
6212   // Note, inline_string_indexOf() generates checks:
6213   // if (substr.count > string.count) return -1;
6214   // if (substr.count == 0) return 0;
6215   assert(int_cnt2 >= 8, "this code isused only for cnt2 >= 8 chars");
6216 
6217   // Load substring.


6338 } // string_indexofC8
6339 
6340 // Small strings are loaded through stack if they cross page boundary.
6341 void MacroAssembler::string_indexof(Register str1, Register str2,
6342                                     Register cnt1, Register cnt2,
6343                                     int int_cnt2,  Register result,
6344                                     XMMRegister vec, Register tmp) {
6345   ShortBranchVerifier sbv(this);
6346   assert(UseSSE42Intrinsics, "SSE4.2 is required");
6347   //
6348   // int_cnt2 is length of small (< 8 chars) constant substring
6349   // or (-1) for non constant substring in which case its length
6350   // is in cnt2 register.
6351   //
6352   // Note, inline_string_indexOf() generates checks:
6353   // if (substr.count > string.count) return -1;
6354   // if (substr.count == 0) return 0;
6355   //
6356   assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0");
6357 
6358   // This method uses pcmpestri inxtruction with bound registers
6359   //   inputs:
6360   //     xmm - substring
6361   //     rax - substring length (elements count)
6362   //     mem - scanned string
6363   //     rdx - string length (elements count)
6364   //     0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
6365   //   outputs:
6366   //     rcx - matched index in string
6367   assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
6368 
6369   Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, ADJUST_STR,
6370         RET_FOUND, RET_NOT_FOUND, CLEANUP, FOUND_SUBSTR,
6371         FOUND_CANDIDATE;
6372 
6373   { //========================================================
6374     // We don't know where these strings are located
6375     // and we can't read beyond them. Load them through stack.
6376     Label BIG_STRINGS, CHECK_STR, COPY_SUBSTR, COPY_STR;
6377 
6378     movptr(tmp, rsp); // save old SP


6627   cmpl(cnt2, 1);
6628   jcc(Assembler::equal, LENGTH_DIFF_LABEL);
6629 
6630   // Check if the strings start at the same location.
6631   cmpptr(str1, str2);
6632   jcc(Assembler::equal, LENGTH_DIFF_LABEL);
6633 
6634   Address::ScaleFactor scale = Address::times_2;
6635   int stride = 8;
6636 
6637   if (UseAVX >= 2 && UseSSE42Intrinsics) {
6638     Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR;
6639     Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR;
6640     Label COMPARE_TAIL_LONG;
6641     int pcmpmask = 0x19;
6642 
6643     // Setup to compare 16-chars (32-bytes) vectors,
6644     // start from first character again because it has aligned address.
6645     int stride2 = 16;
6646     int adr_stride  = stride  << scale;
6647     int adr_stride2 = stride2 << scale;
6648 
6649     assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
6650     // rax and rdx are used by pcmpestri as elements counters
6651     movl(result, cnt2);
6652     andl(cnt2, ~(stride2-1));   // cnt2 holds the vector count
6653     jcc(Assembler::zero, COMPARE_TAIL_LONG);
6654 
6655     // fast path : compare first 2 8-char vectors.
6656     bind(COMPARE_16_CHARS);
6657     movdqu(vec1, Address(str1, 0));
6658     pcmpestri(vec1, Address(str2, 0), pcmpmask);
6659     jccb(Assembler::below, COMPARE_INDEX_CHAR);
6660 
6661     movdqu(vec1, Address(str1, adr_stride));
6662     pcmpestri(vec1, Address(str2, adr_stride), pcmpmask);
6663     jccb(Assembler::aboveEqual, COMPARE_WIDE_VECTORS);
6664     addl(cnt1, stride);
6665 
6666     // Compare the characters at index in cnt1
6667     bind(COMPARE_INDEX_CHAR); //cnt1 has the offset of the mismatching character


6726     jmpb(WHILE_HEAD_LABEL);
6727 
6728     bind(COMPARE_SMALL_STR);
6729   } else if (UseSSE42Intrinsics) {
6730     Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
6731     int pcmpmask = 0x19;
6732     // Setup to compare 8-char (16-byte) vectors,
6733     // start from first character again because it has aligned address.
6734     movl(result, cnt2);
6735     andl(cnt2, ~(stride - 1));   // cnt2 holds the vector count
6736     jccb(Assembler::zero, COMPARE_TAIL);
6737 
6738     lea(str1, Address(str1, result, scale));
6739     lea(str2, Address(str2, result, scale));
6740     negptr(result);
6741 
6742     // pcmpestri
6743     //   inputs:
6744     //     vec1- substring
6745     //     rax - negative string length (elements count)
6746     //     mem - scaned string
6747     //     rdx - string length (elements count)
6748     //     pcmpmask - cmp mode: 11000 (string compare with negated result)
6749     //               + 00 (unsigned bytes) or  + 01 (unsigned shorts)
6750     //   outputs:
6751     //     rcx - first mismatched element index
6752     assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
6753 
6754     bind(COMPARE_WIDE_VECTORS);
6755     movdqu(vec1, Address(str1, result, scale));
6756     pcmpestri(vec1, Address(str2, result, scale), pcmpmask);
6757     // After pcmpestri cnt1(rcx) contains mismatched element index
6758 
6759     jccb(Assembler::below, VECTOR_NOT_EQUAL);  // CF==1
6760     addptr(result, stride);
6761     subptr(cnt2, stride);
6762     jccb(Assembler::notZero, COMPARE_WIDE_VECTORS);
6763 
6764     // compare wide vectors tail
6765     testptr(result, result);
6766     jccb(Assembler::zero, LENGTH_DIFF_LABEL);


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


6177 
6178   xorptr(tmp, tmp);
6179   if (UseFastStosb) {
6180     shlptr(cnt,3); // convert to number of bytes
6181     rep_stosb();
6182   } else {
6183     NOT_LP64(shlptr(cnt,1);) // convert to number of dwords for 32-bit VM
6184     rep_stos();
6185   }
6186 }
6187 
6188 // IndexOf for constant substrings with size >= 8 chars
6189 // which don't need to be loaded through stack.
6190 void MacroAssembler::string_indexofC8(Register str1, Register str2,
6191                                       Register cnt1, Register cnt2,
6192                                       int int_cnt2,  Register result,
6193                                       XMMRegister vec, Register tmp) {
6194   ShortBranchVerifier sbv(this);
6195   assert(UseSSE42Intrinsics, "SSE4.2 is required");
6196 
6197   // This method uses pcmpestri instruction with bound registers
6198   //   inputs:
6199   //     xmm - substring
6200   //     rax - substring length (elements count)
6201   //     mem - scanned string
6202   //     rdx - string length (elements count)
6203   //     0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
6204   //   outputs:
6205   //     rcx - matched index in string
6206   assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
6207 
6208   Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR,
6209         RET_FOUND, RET_NOT_FOUND, EXIT, FOUND_SUBSTR,
6210         MATCH_SUBSTR_HEAD, RELOAD_STR, FOUND_CANDIDATE;
6211 
6212   // Note, inline_string_indexOf() generates checks:
6213   // if (substr.count > string.count) return -1;
6214   // if (substr.count == 0) return 0;
6215   assert(int_cnt2 >= 8, "this code isused only for cnt2 >= 8 chars");
6216 
6217   // Load substring.


6338 } // string_indexofC8
6339 
6340 // Small strings are loaded through stack if they cross page boundary.
6341 void MacroAssembler::string_indexof(Register str1, Register str2,
6342                                     Register cnt1, Register cnt2,
6343                                     int int_cnt2,  Register result,
6344                                     XMMRegister vec, Register tmp) {
6345   ShortBranchVerifier sbv(this);
6346   assert(UseSSE42Intrinsics, "SSE4.2 is required");
6347   //
6348   // int_cnt2 is length of small (< 8 chars) constant substring
6349   // or (-1) for non constant substring in which case its length
6350   // is in cnt2 register.
6351   //
6352   // Note, inline_string_indexOf() generates checks:
6353   // if (substr.count > string.count) return -1;
6354   // if (substr.count == 0) return 0;
6355   //
6356   assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0");
6357 
6358   // This method uses pcmpestri instruction with bound registers
6359   //   inputs:
6360   //     xmm - substring
6361   //     rax - substring length (elements count)
6362   //     mem - scanned string
6363   //     rdx - string length (elements count)
6364   //     0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
6365   //   outputs:
6366   //     rcx - matched index in string
6367   assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
6368 
6369   Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, ADJUST_STR,
6370         RET_FOUND, RET_NOT_FOUND, CLEANUP, FOUND_SUBSTR,
6371         FOUND_CANDIDATE;
6372 
6373   { //========================================================
6374     // We don't know where these strings are located
6375     // and we can't read beyond them. Load them through stack.
6376     Label BIG_STRINGS, CHECK_STR, COPY_SUBSTR, COPY_STR;
6377 
6378     movptr(tmp, rsp); // save old SP


6627   cmpl(cnt2, 1);
6628   jcc(Assembler::equal, LENGTH_DIFF_LABEL);
6629 
6630   // Check if the strings start at the same location.
6631   cmpptr(str1, str2);
6632   jcc(Assembler::equal, LENGTH_DIFF_LABEL);
6633 
6634   Address::ScaleFactor scale = Address::times_2;
6635   int stride = 8;
6636 
6637   if (UseAVX >= 2 && UseSSE42Intrinsics) {
6638     Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR;
6639     Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR;
6640     Label COMPARE_TAIL_LONG;
6641     int pcmpmask = 0x19;
6642 
6643     // Setup to compare 16-chars (32-bytes) vectors,
6644     // start from first character again because it has aligned address.
6645     int stride2 = 16;
6646     int adr_stride  = stride  << scale;

6647 
6648     assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
6649     // rax and rdx are used by pcmpestri as elements counters
6650     movl(result, cnt2);
6651     andl(cnt2, ~(stride2-1));   // cnt2 holds the vector count
6652     jcc(Assembler::zero, COMPARE_TAIL_LONG);
6653 
6654     // fast path : compare first 2 8-char vectors.
6655     bind(COMPARE_16_CHARS);
6656     movdqu(vec1, Address(str1, 0));
6657     pcmpestri(vec1, Address(str2, 0), pcmpmask);
6658     jccb(Assembler::below, COMPARE_INDEX_CHAR);
6659 
6660     movdqu(vec1, Address(str1, adr_stride));
6661     pcmpestri(vec1, Address(str2, adr_stride), pcmpmask);
6662     jccb(Assembler::aboveEqual, COMPARE_WIDE_VECTORS);
6663     addl(cnt1, stride);
6664 
6665     // Compare the characters at index in cnt1
6666     bind(COMPARE_INDEX_CHAR); //cnt1 has the offset of the mismatching character


6725     jmpb(WHILE_HEAD_LABEL);
6726 
6727     bind(COMPARE_SMALL_STR);
6728   } else if (UseSSE42Intrinsics) {
6729     Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
6730     int pcmpmask = 0x19;
6731     // Setup to compare 8-char (16-byte) vectors,
6732     // start from first character again because it has aligned address.
6733     movl(result, cnt2);
6734     andl(cnt2, ~(stride - 1));   // cnt2 holds the vector count
6735     jccb(Assembler::zero, COMPARE_TAIL);
6736 
6737     lea(str1, Address(str1, result, scale));
6738     lea(str2, Address(str2, result, scale));
6739     negptr(result);
6740 
6741     // pcmpestri
6742     //   inputs:
6743     //     vec1- substring
6744     //     rax - negative string length (elements count)
6745     //     mem - scanned string
6746     //     rdx - string length (elements count)
6747     //     pcmpmask - cmp mode: 11000 (string compare with negated result)
6748     //               + 00 (unsigned bytes) or  + 01 (unsigned shorts)
6749     //   outputs:
6750     //     rcx - first mismatched element index
6751     assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
6752 
6753     bind(COMPARE_WIDE_VECTORS);
6754     movdqu(vec1, Address(str1, result, scale));
6755     pcmpestri(vec1, Address(str2, result, scale), pcmpmask);
6756     // After pcmpestri cnt1(rcx) contains mismatched element index
6757 
6758     jccb(Assembler::below, VECTOR_NOT_EQUAL);  // CF==1
6759     addptr(result, stride);
6760     subptr(cnt2, stride);
6761     jccb(Assembler::notZero, COMPARE_WIDE_VECTORS);
6762 
6763     // compare wide vectors tail
6764     testptr(result, result);
6765     jccb(Assembler::zero, LENGTH_DIFF_LABEL);