8565 movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); |
8591 movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); |
8566 } |
8592 } |
8567 } |
8593 } |
8568 #endif // _LP64 |
8594 #endif // _LP64 |
8569 |
8595 |
8570 // IndexOf substring. |
8596 // IndexOf for constant substrings with size >= 8 chars |
8571 void MacroAssembler::string_indexof(Register str1, Register str2, |
8597 // which don't need to be loaded through stack. |
8572 Register cnt1, Register cnt2, Register result, |
8598 void MacroAssembler::string_indexofC8(Register str1, Register str2, |
8573 XMMRegister vec, Register tmp) { |
8599 Register cnt1, Register cnt2, |
|
8600 int int_cnt2, Register result, |
|
8601 XMMRegister vec, Register tmp) { |
8574 assert(UseSSE42Intrinsics, "SSE4.2 is required"); |
8602 assert(UseSSE42Intrinsics, "SSE4.2 is required"); |
8575 |
8603 |
8576 Label RELOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, |
8604 // This method uses pcmpestri inxtruction with bound registers |
8577 SCAN_SUBSTR, RET_NOT_FOUND, CLEANUP; |
|
8578 |
|
8579 push(str1); // string addr |
|
8580 push(str2); // substr addr |
|
8581 push(cnt2); // substr count |
|
8582 jmpb(PREP_FOR_SCAN); |
|
8583 |
|
8584 // Substr count saved at sp |
|
8585 // Substr saved at sp+1*wordSize |
|
8586 // String saved at sp+2*wordSize |
|
8587 |
|
8588 // Reload substr for rescan |
|
8589 bind(RELOAD_SUBSTR); |
|
8590 movl(cnt2, Address(rsp, 0)); |
|
8591 movptr(str2, Address(rsp, wordSize)); |
|
8592 // We came here after the beginninig of the substring was |
|
8593 // matched but the rest of it was not so we need to search |
|
8594 // again. Start from the next element after the previous match. |
|
8595 subptr(str1, result); // Restore counter |
|
8596 shrl(str1, 1); |
|
8597 addl(cnt1, str1); |
|
8598 decrementl(cnt1); |
|
8599 lea(str1, Address(result, 2)); // Reload string |
|
8600 |
|
8601 // Load substr |
|
8602 bind(PREP_FOR_SCAN); |
|
8603 movdqu(vec, Address(str2, 0)); |
|
8604 addl(cnt1, 8); // prime the loop |
|
8605 subptr(str1, 16); |
|
8606 |
|
8607 // Scan string for substr in 16-byte vectors |
|
8608 bind(SCAN_TO_SUBSTR); |
|
8609 subl(cnt1, 8); |
|
8610 addptr(str1, 16); |
|
8611 |
|
8612 // pcmpestri |
|
8613 // inputs: |
8605 // inputs: |
8614 // xmm - substring |
8606 // xmm - substring |
8615 // rax - substring length (elements count) |
8607 // rax - substring length (elements count) |
8616 // mem - scaned string |
8608 // mem - scanned string |
8617 // rdx - string length (elements count) |
8609 // rdx - string length (elements count) |
8618 // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) |
8610 // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) |
8619 // outputs: |
8611 // outputs: |
8620 // rcx - matched index in string |
8612 // rcx - matched index in string |
8621 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); |
8613 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); |
8622 |
8614 |
8623 pcmpestri(vec, Address(str1, 0), 0x0d); |
8615 Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, |
8624 jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0 |
8616 RET_FOUND, RET_NOT_FOUND, EXIT, FOUND_SUBSTR, |
8625 jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0 |
8617 MATCH_SUBSTR_HEAD, RELOAD_STR, FOUND_CANDIDATE; |
8626 |
8618 |
8627 // Fallthrough: found a potential substr |
8619 // Note, inline_string_indexOf() generates checks: |
|
8620 // if (substr.count > string.count) return -1; |
|
8621 // if (substr.count == 0) return 0; |
|
8622 assert(int_cnt2 >= 8, "this code isused only for cnt2 >= 8 chars"); |
|
8623 |
|
8624 // Load substring. |
|
8625 movdqu(vec, Address(str2, 0)); |
|
8626 movl(cnt2, int_cnt2); |
|
8627 movptr(result, str1); // string addr |
|
8628 |
|
8629 if (int_cnt2 > 8) { |
|
8630 jmpb(SCAN_TO_SUBSTR); |
|
8631 |
|
8632 // Reload substr for rescan, this code |
|
8633 // is executed only for large substrings (> 8 chars) |
|
8634 bind(RELOAD_SUBSTR); |
|
8635 movdqu(vec, Address(str2, 0)); |
|
8636 negptr(cnt2); // Jumped here with negative cnt2, convert to positive |
|
8637 |
|
8638 bind(RELOAD_STR); |
|
8639 // We came here after the beginning of the substring was |
|
8640 // matched but the rest of it was not so we need to search |
|
8641 // again. Start from the next element after the previous match. |
|
8642 |
|
8643 // cnt2 is number of substring reminding elements and |
|
8644 // cnt1 is number of string reminding elements when cmp failed. |
|
8645 // Restored cnt1 = cnt1 - cnt2 + int_cnt2 |
|
8646 subl(cnt1, cnt2); |
|
8647 addl(cnt1, int_cnt2); |
|
8648 movl(cnt2, int_cnt2); // Now restore cnt2 |
|
8649 |
|
8650 decrementl(cnt1); // Shift to next element |
|
8651 cmpl(cnt1, cnt2); |
|
8652 jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring |
|
8653 |
|
8654 addptr(result, 2); |
|
8655 |
|
8656 } // (int_cnt2 > 8) |
|
8657 |
|
8658 // Scan string for start of substr in 16-byte vectors |
|
8659 bind(SCAN_TO_SUBSTR); |
|
8660 pcmpestri(vec, Address(result, 0), 0x0d); |
|
8661 jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1 |
|
8662 subl(cnt1, 8); |
|
8663 jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string |
|
8664 cmpl(cnt1, cnt2); |
|
8665 jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring |
|
8666 addptr(result, 16); |
|
8667 jmpb(SCAN_TO_SUBSTR); |
|
8668 |
|
8669 // Found a potential substr |
|
8670 bind(FOUND_CANDIDATE); |
|
8671 // Matched whole vector if first element matched (tmp(rcx) == 0). |
|
8672 if (int_cnt2 == 8) { |
|
8673 jccb(Assembler::overflow, RET_FOUND); // OF == 1 |
|
8674 } else { // int_cnt2 > 8 |
|
8675 jccb(Assembler::overflow, FOUND_SUBSTR); |
|
8676 } |
|
8677 // After pcmpestri tmp(rcx) contains matched element index |
|
8678 // Compute start addr of substr |
|
8679 lea(result, Address(result, tmp, Address::times_2)); |
8628 |
8680 |
8629 // Make sure string is still long enough |
8681 // Make sure string is still long enough |
8630 subl(cnt1, tmp); |
8682 subl(cnt1, tmp); |
8631 cmpl(cnt1, cnt2); |
8683 cmpl(cnt1, cnt2); |
8632 jccb(Assembler::negative, RET_NOT_FOUND); |
8684 if (int_cnt2 == 8) { |
8633 // Compute start addr of substr |
8685 jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR); |
8634 lea(str1, Address(str1, tmp, Address::times_2)); |
8686 } else { // int_cnt2 > 8 |
8635 movptr(result, str1); // save |
8687 jccb(Assembler::greaterEqual, MATCH_SUBSTR_HEAD); |
8636 |
8688 } |
8637 // Compare potential substr |
8689 // Left less then substring. |
8638 addl(cnt1, 8); // prime the loop |
|
8639 addl(cnt2, 8); |
|
8640 subptr(str1, 16); |
|
8641 subptr(str2, 16); |
|
8642 |
|
8643 // Scan 16-byte vectors of string and substr |
|
8644 bind(SCAN_SUBSTR); |
|
8645 subl(cnt1, 8); |
|
8646 subl(cnt2, 8); |
|
8647 addptr(str1, 16); |
|
8648 addptr(str2, 16); |
|
8649 movdqu(vec, Address(str2, 0)); |
|
8650 pcmpestri(vec, Address(str1, 0), 0x0d); |
|
8651 jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 |
|
8652 jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0 |
|
8653 |
|
8654 // Compute substr offset |
|
8655 subptr(result, Address(rsp, 2*wordSize)); |
|
8656 shrl(result, 1); // index |
|
8657 jmpb(CLEANUP); |
|
8658 |
8690 |
8659 bind(RET_NOT_FOUND); |
8691 bind(RET_NOT_FOUND); |
8660 movl(result, -1); |
8692 movl(result, -1); |
|
8693 jmpb(EXIT); |
|
8694 |
|
8695 if (int_cnt2 > 8) { |
|
8696 // This code is optimized for the case when whole substring |
|
8697 // is matched if its head is matched. |
|
8698 bind(MATCH_SUBSTR_HEAD); |
|
8699 pcmpestri(vec, Address(result, 0), 0x0d); |
|
8700 // Reload only string if does not match |
|
8701 jccb(Assembler::noOverflow, RELOAD_STR); // OF == 0 |
|
8702 |
|
8703 Label CONT_SCAN_SUBSTR; |
|
8704 // Compare the rest of substring (> 8 chars). |
|
8705 bind(FOUND_SUBSTR); |
|
8706 // First 8 chars are already matched. |
|
8707 negptr(cnt2); |
|
8708 addptr(cnt2, 8); |
|
8709 |
|
8710 bind(SCAN_SUBSTR); |
|
8711 subl(cnt1, 8); |
|
8712 cmpl(cnt2, -8); // Do not read beyond substring |
|
8713 jccb(Assembler::lessEqual, CONT_SCAN_SUBSTR); |
|
8714 // Back-up strings to avoid reading beyond substring: |
|
8715 // cnt1 = cnt1 - cnt2 + 8 |
|
8716 addl(cnt1, cnt2); // cnt2 is negative |
|
8717 addl(cnt1, 8); |
|
8718 movl(cnt2, 8); negptr(cnt2); |
|
8719 bind(CONT_SCAN_SUBSTR); |
|
8720 if (int_cnt2 < (int)G) { |
|
8721 movdqu(vec, Address(str2, cnt2, Address::times_2, int_cnt2*2)); |
|
8722 pcmpestri(vec, Address(result, cnt2, Address::times_2, int_cnt2*2), 0x0d); |
|
8723 } else { |
|
8724 // calculate index in register to avoid integer overflow (int_cnt2*2) |
|
8725 movl(tmp, int_cnt2); |
|
8726 addptr(tmp, cnt2); |
|
8727 movdqu(vec, Address(str2, tmp, Address::times_2, 0)); |
|
8728 pcmpestri(vec, Address(result, tmp, Address::times_2, 0), 0x0d); |
|
8729 } |
|
8730 // Need to reload strings pointers if not matched whole vector |
|
8731 jccb(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 |
|
8732 addptr(cnt2, 8); |
|
8733 jccb(Assembler::negative, SCAN_SUBSTR); |
|
8734 // Fall through if found full substring |
|
8735 |
|
8736 } // (int_cnt2 > 8) |
|
8737 |
|
8738 bind(RET_FOUND); |
|
8739 // Found result if we matched full small substring. |
|
8740 // Compute substr offset |
|
8741 subptr(result, str1); |
|
8742 shrl(result, 1); // index |
|
8743 bind(EXIT); |
|
8744 |
|
8745 } // string_indexofC8 |
|
8746 |
|
8747 // Small strings are loaded through stack if they cross page boundary. |
|
8748 void MacroAssembler::string_indexof(Register str1, Register str2, |
|
8749 Register cnt1, Register cnt2, |
|
8750 int int_cnt2, Register result, |
|
8751 XMMRegister vec, Register tmp) { |
|
8752 assert(UseSSE42Intrinsics, "SSE4.2 is required"); |
|
8753 // |
|
8754 // int_cnt2 is length of small (< 8 chars) constant substring |
|
8755 // or (-1) for non constant substring in which case its length |
|
8756 // is in cnt2 register. |
|
8757 // |
|
8758 // Note, inline_string_indexOf() generates checks: |
|
8759 // if (substr.count > string.count) return -1; |
|
8760 // if (substr.count == 0) return 0; |
|
8761 // |
|
8762 assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0"); |
|
8763 |
|
8764 // This method uses pcmpestri inxtruction with bound registers |
|
8765 // inputs: |
|
8766 // xmm - substring |
|
8767 // rax - substring length (elements count) |
|
8768 // mem - scanned string |
|
8769 // rdx - string length (elements count) |
|
8770 // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) |
|
8771 // outputs: |
|
8772 // rcx - matched index in string |
|
8773 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); |
|
8774 |
|
8775 Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, ADJUST_STR, |
|
8776 RET_FOUND, RET_NOT_FOUND, CLEANUP, FOUND_SUBSTR, |
|
8777 FOUND_CANDIDATE; |
|
8778 |
|
8779 { //======================================================== |
|
8780 // We don't know where these strings are located |
|
8781 // and we can't read beyond them. Load them through stack. |
|
8782 Label BIG_STRINGS, CHECK_STR, COPY_SUBSTR, COPY_STR; |
|
8783 |
|
8784 movptr(tmp, rsp); // save old SP |
|
8785 |
|
8786 if (int_cnt2 > 0) { // small (< 8 chars) constant substring |
|
8787 if (int_cnt2 == 1) { // One char |
|
8788 load_unsigned_short(result, Address(str2, 0)); |
|
8789 movdl(vec, result); // move 32 bits |
|
8790 } else if (int_cnt2 == 2) { // Two chars |
|
8791 movdl(vec, Address(str2, 0)); // move 32 bits |
|
8792 } else if (int_cnt2 == 4) { // Four chars |
|
8793 movq(vec, Address(str2, 0)); // move 64 bits |
|
8794 } else { // cnt2 = { 3, 5, 6, 7 } |
|
8795 // Array header size is 12 bytes in 32-bit VM |
|
8796 // + 6 bytes for 3 chars == 18 bytes, |
|
8797 // enough space to load vec and shift. |
|
8798 assert(HeapWordSize*typeArrayKlass::header_size() >= 12,"sanity"); |
|
8799 movdqu(vec, Address(str2, (int_cnt2*2)-16)); |
|
8800 psrldq(vec, 16-(int_cnt2*2)); |
|
8801 } |
|
8802 } else { // not constant substring |
|
8803 cmpl(cnt2, 8); |
|
8804 jccb(Assembler::aboveEqual, BIG_STRINGS); // Both strings are big enough |
|
8805 |
|
8806 // We can read beyond string if srt+16 does not cross page boundary |
|
8807 // since heaps are aligned and mapped by pages. |
|
8808 assert(os::vm_page_size() < (int)G, "default page should be small"); |
|
8809 movl(result, str2); // We need only low 32 bits |
|
8810 andl(result, (os::vm_page_size()-1)); |
|
8811 cmpl(result, (os::vm_page_size()-16)); |
|
8812 jccb(Assembler::belowEqual, CHECK_STR); |
|
8813 |
|
8814 // Move small strings to stack to allow load 16 bytes into vec. |
|
8815 subptr(rsp, 16); |
|
8816 int stk_offset = wordSize-2; |
|
8817 push(cnt2); |
|
8818 |
|
8819 bind(COPY_SUBSTR); |
|
8820 load_unsigned_short(result, Address(str2, cnt2, Address::times_2, -2)); |
|
8821 movw(Address(rsp, cnt2, Address::times_2, stk_offset), result); |
|
8822 decrement(cnt2); |
|
8823 jccb(Assembler::notZero, COPY_SUBSTR); |
|
8824 |
|
8825 pop(cnt2); |
|
8826 movptr(str2, rsp); // New substring address |
|
8827 } // non constant |
|
8828 |
|
8829 bind(CHECK_STR); |
|
8830 cmpl(cnt1, 8); |
|
8831 jccb(Assembler::aboveEqual, BIG_STRINGS); |
|
8832 |
|
8833 // Check cross page boundary. |
|
8834 movl(result, str1); // We need only low 32 bits |
|
8835 andl(result, (os::vm_page_size()-1)); |
|
8836 cmpl(result, (os::vm_page_size()-16)); |
|
8837 jccb(Assembler::belowEqual, BIG_STRINGS); |
|
8838 |
|
8839 subptr(rsp, 16); |
|
8840 int stk_offset = -2; |
|
8841 if (int_cnt2 < 0) { // not constant |
|
8842 push(cnt2); |
|
8843 stk_offset += wordSize; |
|
8844 } |
|
8845 movl(cnt2, cnt1); |
|
8846 |
|
8847 bind(COPY_STR); |
|
8848 load_unsigned_short(result, Address(str1, cnt2, Address::times_2, -2)); |
|
8849 movw(Address(rsp, cnt2, Address::times_2, stk_offset), result); |
|
8850 decrement(cnt2); |
|
8851 jccb(Assembler::notZero, COPY_STR); |
|
8852 |
|
8853 if (int_cnt2 < 0) { // not constant |
|
8854 pop(cnt2); |
|
8855 } |
|
8856 movptr(str1, rsp); // New string address |
|
8857 |
|
8858 bind(BIG_STRINGS); |
|
8859 // Load substring. |
|
8860 if (int_cnt2 < 0) { // -1 |
|
8861 movdqu(vec, Address(str2, 0)); |
|
8862 push(cnt2); // substr count |
|
8863 push(str2); // substr addr |
|
8864 push(str1); // string addr |
|
8865 } else { |
|
8866 // Small (< 8 chars) constant substrings are loaded already. |
|
8867 movl(cnt2, int_cnt2); |
|
8868 } |
|
8869 push(tmp); // original SP |
|
8870 |
|
8871 } // Finished loading |
|
8872 |
|
8873 //======================================================== |
|
8874 // Start search |
|
8875 // |
|
8876 |
|
8877 movptr(result, str1); // string addr |
|
8878 |
|
8879 if (int_cnt2 < 0) { // Only for non constant substring |
|
8880 jmpb(SCAN_TO_SUBSTR); |
|
8881 |
|
8882 // SP saved at sp+0 |
|
8883 // String saved at sp+1*wordSize |
|
8884 // Substr saved at sp+2*wordSize |
|
8885 // Substr count saved at sp+3*wordSize |
|
8886 |
|
8887 // Reload substr for rescan, this code |
|
8888 // is executed only for large substrings (> 8 chars) |
|
8889 bind(RELOAD_SUBSTR); |
|
8890 movptr(str2, Address(rsp, 2*wordSize)); |
|
8891 movl(cnt2, Address(rsp, 3*wordSize)); |
|
8892 movdqu(vec, Address(str2, 0)); |
|
8893 // We came here after the beginning of the substring was |
|
8894 // matched but the rest of it was not so we need to search |
|
8895 // again. Start from the next element after the previous match. |
|
8896 subptr(str1, result); // Restore counter |
|
8897 shrl(str1, 1); |
|
8898 addl(cnt1, str1); |
|
8899 decrementl(cnt1); // Shift to next element |
|
8900 cmpl(cnt1, cnt2); |
|
8901 jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring |
|
8902 |
|
8903 addptr(result, 2); |
|
8904 } // non constant |
|
8905 |
|
8906 // Scan string for start of substr in 16-byte vectors |
|
8907 bind(SCAN_TO_SUBSTR); |
|
8908 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); |
|
8909 pcmpestri(vec, Address(result, 0), 0x0d); |
|
8910 jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1 |
|
8911 subl(cnt1, 8); |
|
8912 jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string |
|
8913 cmpl(cnt1, cnt2); |
|
8914 jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring |
|
8915 addptr(result, 16); |
|
8916 |
|
8917 bind(ADJUST_STR); |
|
8918 cmpl(cnt1, 8); // Do not read beyond string |
|
8919 jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR); |
|
8920 // Back-up string to avoid reading beyond string. |
|
8921 lea(result, Address(result, cnt1, Address::times_2, -16)); |
|
8922 movl(cnt1, 8); |
|
8923 jmpb(SCAN_TO_SUBSTR); |
|
8924 |
|
8925 // Found a potential substr |
|
8926 bind(FOUND_CANDIDATE); |
|
8927 // After pcmpestri tmp(rcx) contains matched element index |
|
8928 |
|
8929 // Make sure string is still long enough |
|
8930 subl(cnt1, tmp); |
|
8931 cmpl(cnt1, cnt2); |
|
8932 jccb(Assembler::greaterEqual, FOUND_SUBSTR); |
|
8933 // Left less then substring. |
|
8934 |
|
8935 bind(RET_NOT_FOUND); |
|
8936 movl(result, -1); |
|
8937 jmpb(CLEANUP); |
|
8938 |
|
8939 bind(FOUND_SUBSTR); |
|
8940 // Compute start addr of substr |
|
8941 lea(result, Address(result, tmp, Address::times_2)); |
|
8942 |
|
8943 if (int_cnt2 > 0) { // Constant substring |
|
8944 // Repeat search for small substring (< 8 chars) |
|
8945 // from new point without reloading substring. |
|
8946 // Have to check that we don't read beyond string. |
|
8947 cmpl(tmp, 8-int_cnt2); |
|
8948 jccb(Assembler::greater, ADJUST_STR); |
|
8949 // Fall through if matched whole substring. |
|
8950 } else { // non constant |
|
8951 assert(int_cnt2 == -1, "should be != 0"); |
|
8952 |
|
8953 addl(tmp, cnt2); |
|
8954 // Found result if we matched whole substring. |
|
8955 cmpl(tmp, 8); |
|
8956 jccb(Assembler::lessEqual, RET_FOUND); |
|
8957 |
|
8958 // Repeat search for small substring (<= 8 chars) |
|
8959 // from new point 'str1' without reloading substring. |
|
8960 cmpl(cnt2, 8); |
|
8961 // Have to check that we don't read beyond string. |
|
8962 jccb(Assembler::lessEqual, ADJUST_STR); |
|
8963 |
|
8964 Label CHECK_NEXT, CONT_SCAN_SUBSTR, RET_FOUND_LONG; |
|
8965 // Compare the rest of substring (> 8 chars). |
|
8966 movptr(str1, result); |
|
8967 |
|
8968 cmpl(tmp, cnt2); |
|
8969 // First 8 chars are already matched. |
|
8970 jccb(Assembler::equal, CHECK_NEXT); |
|
8971 |
|
8972 bind(SCAN_SUBSTR); |
|
8973 pcmpestri(vec, Address(str1, 0), 0x0d); |
|
8974 // Need to reload strings pointers if not matched whole vector |
|
8975 jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 |
|
8976 |
|
8977 bind(CHECK_NEXT); |
|
8978 subl(cnt2, 8); |
|
8979 jccb(Assembler::lessEqual, RET_FOUND_LONG); // Found full substring |
|
8980 addptr(str1, 16); |
|
8981 addptr(str2, 16); |
|
8982 subl(cnt1, 8); |
|
8983 cmpl(cnt2, 8); // Do not read beyond substring |
|
8984 jccb(Assembler::greaterEqual, CONT_SCAN_SUBSTR); |
|
8985 // Back-up strings to avoid reading beyond substring. |
|
8986 lea(str2, Address(str2, cnt2, Address::times_2, -16)); |
|
8987 lea(str1, Address(str1, cnt2, Address::times_2, -16)); |
|
8988 subl(cnt1, cnt2); |
|
8989 movl(cnt2, 8); |
|
8990 addl(cnt1, 8); |
|
8991 bind(CONT_SCAN_SUBSTR); |
|
8992 movdqu(vec, Address(str2, 0)); |
|
8993 jmpb(SCAN_SUBSTR); |
|
8994 |
|
8995 bind(RET_FOUND_LONG); |
|
8996 movptr(str1, Address(rsp, wordSize)); |
|
8997 } // non constant |
|
8998 |
|
8999 bind(RET_FOUND); |
|
9000 // Compute substr offset |
|
9001 subptr(result, str1); |
|
9002 shrl(result, 1); // index |
8661 |
9003 |
8662 bind(CLEANUP); |
9004 bind(CLEANUP); |
8663 addptr(rsp, 3*wordSize); |
9005 pop(rsp); // restore SP |
8664 } |
9006 |
|
9007 } // string_indexof |
8665 |
9008 |
8666 // Compare strings. |
9009 // Compare strings. |
8667 void MacroAssembler::string_compare(Register str1, Register str2, |
9010 void MacroAssembler::string_compare(Register str1, Register str2, |
8668 Register cnt1, Register cnt2, Register result, |
9011 Register cnt1, Register cnt2, Register result, |
8669 XMMRegister vec1) { |
9012 XMMRegister vec1) { |