8157834: aarch64: Hello World crashes with fastdebug build

Support LL, UL and LU encodings of StrIndexOf

Reviewed-by: aph
This commit is contained in:
Ed Nevill 2016-05-25 15:05:26 +00:00
parent ac5718b306
commit 7694596568
3 changed files with 212 additions and 76 deletions

View File

@ -3331,7 +3331,6 @@ const bool Matcher::match_rule_supported(int opcode) {
switch (opcode) { switch (opcode) {
case Op_StrComp: case Op_StrComp:
case Op_StrIndexOf:
if (CompactStrings) return false; if (CompactStrings) return false;
break; break;
default: default:
@ -14953,26 +14952,83 @@ instruct string_compareU(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 c
ins_pipe(pipe_class_memory); ins_pipe(pipe_class_memory);
%} %}
instruct string_indexof(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2, instruct string_indexofUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr) iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
%{ %{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU); predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result" %} format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UU)" %}
ins_encode %{ ins_encode %{
__ string_indexof($str1$$Register, $str2$$Register, __ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register, $cnt1$$Register, $cnt2$$Register,
$tmp1$$Register, $tmp2$$Register, $tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register, $tmp3$$Register, $tmp4$$Register,
-1, $result$$Register); -1, $result$$Register, StrIntrinsicNode::UU);
%} %}
ins_pipe(pipe_class_memory); ins_pipe(pipe_class_memory);
%} %}
instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, instruct string_indexofLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (LL)" %}
ins_encode %{
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register,
$tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register,
-1, $result$$Register, StrIntrinsicNode::LL);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_indexofUL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UL)" %}
ins_encode %{
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register,
$tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register,
-1, $result$$Register, StrIntrinsicNode::UL);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_indexofLU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (LU)" %}
ins_encode %{
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register,
$tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register,
-1, $result$$Register, StrIntrinsicNode::LU);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_indexof_conUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2, immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
iRegI tmp3, iRegI tmp4, rFlagsReg cr) iRegI tmp3, iRegI tmp4, rFlagsReg cr)
%{ %{
@ -14980,7 +15036,7 @@ instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result" %} format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UU)" %}
ins_encode %{ ins_encode %{
int icnt2 = (int)$int_cnt2$$constant; int icnt2 = (int)$int_cnt2$$constant;
@ -14988,7 +15044,70 @@ instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
$cnt1$$Register, zr, $cnt1$$Register, zr,
$tmp1$$Register, $tmp2$$Register, $tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register, $tmp3$$Register, $tmp4$$Register,
icnt2, $result$$Register); icnt2, $result$$Register, StrIntrinsicNode::UU);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_indexof_conLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
iRegI tmp3, iRegI tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (LL)" %}
ins_encode %{
int icnt2 = (int)$int_cnt2$$constant;
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, zr,
$tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register,
icnt2, $result$$Register, StrIntrinsicNode::LL);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_indexof_conUL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
immI_1 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
iRegI tmp3, iRegI tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UL)" %}
ins_encode %{
int icnt2 = (int)$int_cnt2$$constant;
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, zr,
$tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register,
icnt2, $result$$Register, StrIntrinsicNode::UL);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_indexof_conLU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
immI_1 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
iRegI tmp3, iRegI tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (LU)" %}
ins_encode %{
int icnt2 = (int)$int_cnt2$$constant;
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, zr,
$tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register,
icnt2, $result$$Register, StrIntrinsicNode::LU);
%} %}
ins_pipe(pipe_class_memory); ins_pipe(pipe_class_memory);
%} %}

View File

@ -4136,13 +4136,14 @@ void MacroAssembler::remove_frame(int framesize) {
} }
} }
typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr);
// Search for str1 in str2 and return index or -1 // Search for str1 in str2 and return index or -1
void MacroAssembler::string_indexof(Register str2, Register str1, void MacroAssembler::string_indexof(Register str2, Register str1,
Register cnt2, Register cnt1, Register cnt2, Register cnt1,
Register tmp1, Register tmp2, Register tmp1, Register tmp2,
Register tmp3, Register tmp4, Register tmp3, Register tmp4,
int icnt1, Register result) { int icnt1, Register result, int ae) {
Label BM, LINEARSEARCH, DONE, NOMATCH, MATCH; Label BM, LINEARSEARCH, DONE, NOMATCH, MATCH;
Register ch1 = rscratch1; Register ch1 = rscratch1;
@ -4153,6 +4154,21 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
Register cnt2_neg = cnt2; Register cnt2_neg = cnt2;
Register result_tmp = tmp4; Register result_tmp = tmp4;
bool isL = ae == StrIntrinsicNode::LL;
bool str1_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL;
bool str2_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU;
int str1_chr_shift = str1_isL ? 0:1;
int str2_chr_shift = str2_isL ? 0:1;
int str1_chr_size = str1_isL ? 1:2;
int str2_chr_size = str2_isL ? 1:2;
chr_insn str1_load_1chr = str1_isL ? (chr_insn)&MacroAssembler::ldrb :
(chr_insn)&MacroAssembler::ldrh;
chr_insn str2_load_1chr = str2_isL ? (chr_insn)&MacroAssembler::ldrb :
(chr_insn)&MacroAssembler::ldrh;
chr_insn load_2chr = isL ? (chr_insn)&MacroAssembler::ldrh : (chr_insn)&MacroAssembler::ldrw;
chr_insn load_4chr = isL ? (chr_insn)&MacroAssembler::ldrw : (chr_insn)&MacroAssembler::ldr;
// Note, inline_string_indexOf() generates checks: // Note, inline_string_indexOf() generates checks:
// if (substr.count > string.count) return -1; // if (substr.count > string.count) return -1;
// if (substr.count == 0) return 0; // if (substr.count == 0) return 0;
@ -4242,7 +4258,7 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
mov(cnt1tmp, 0); mov(cnt1tmp, 0);
sub(cnt1end, cnt1, 1); sub(cnt1end, cnt1, 1);
BIND(BCLOOP); BIND(BCLOOP);
ldrh(ch1, Address(str1, cnt1tmp, Address::lsl(1))); (this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp, Address::lsl(str1_chr_shift)));
cmp(ch1, 128); cmp(ch1, 128);
add(cnt1tmp, cnt1tmp, 1); add(cnt1tmp, cnt1tmp, 1);
br(HS, BCSKIP); br(HS, BCSKIP);
@ -4254,36 +4270,36 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
mov(result_tmp, str2); mov(result_tmp, str2);
sub(cnt2, cnt2, cnt1); sub(cnt2, cnt2, cnt1);
add(str2end, str2, cnt2, LSL, 1); add(str2end, str2, cnt2, LSL, str2_chr_shift);
BIND(BMLOOPSTR2); BIND(BMLOOPSTR2);
sub(cnt1tmp, cnt1, 1); sub(cnt1tmp, cnt1, 1);
ldrh(ch1, Address(str1, cnt1tmp, Address::lsl(1))); (this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp, Address::lsl(str1_chr_shift)));
ldrh(skipch, Address(str2, cnt1tmp, Address::lsl(1))); (this->*str2_load_1chr)(skipch, Address(str2, cnt1tmp, Address::lsl(str2_chr_shift)));
cmp(ch1, skipch); cmp(ch1, skipch);
br(NE, BMSKIP); br(NE, BMSKIP);
subs(cnt1tmp, cnt1tmp, 1); subs(cnt1tmp, cnt1tmp, 1);
br(LT, BMMATCH); br(LT, BMMATCH);
BIND(BMLOOPSTR1); BIND(BMLOOPSTR1);
ldrh(ch1, Address(str1, cnt1tmp, Address::lsl(1))); (this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp, Address::lsl(str1_chr_shift)));
ldrh(ch2, Address(str2, cnt1tmp, Address::lsl(1))); (this->*str2_load_1chr)(ch2, Address(str2, cnt1tmp, Address::lsl(str2_chr_shift)));
cmp(ch1, ch2); cmp(ch1, ch2);
br(NE, BMSKIP); br(NE, BMSKIP);
subs(cnt1tmp, cnt1tmp, 1); subs(cnt1tmp, cnt1tmp, 1);
br(GE, BMLOOPSTR1); br(GE, BMLOOPSTR1);
BIND(BMMATCH); BIND(BMMATCH);
sub(result_tmp, str2, result_tmp); sub(result, str2, result_tmp);
lsr(result, result_tmp, 1); if (!str2_isL) lsr(result, result, 1);
add(sp, sp, 128); add(sp, sp, 128);
b(DONE); b(DONE);
BIND(BMADV); BIND(BMADV);
add(str2, str2, 2); add(str2, str2, str2_chr_size);
b(BMCHECKEND); b(BMCHECKEND);
BIND(BMSKIP); BIND(BMSKIP);
cmp(skipch, 128); cmp(skipch, 128);
br(HS, BMADV); br(HS, BMADV);
ldrb(ch2, Address(sp, skipch)); ldrb(ch2, Address(sp, skipch));
add(str2, str2, cnt1, LSL, 1); add(str2, str2, cnt1, LSL, str2_chr_shift);
sub(str2, str2, ch2, LSL, 1); sub(str2, str2, ch2, LSL, str2_chr_shift);
BIND(BMCHECKEND); BIND(BMCHECKEND);
cmp(str2, str2end); cmp(str2, str2end);
br(LE, BMLOOPSTR2); br(LE, BMLOOPSTR2);
@ -4300,119 +4316,113 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
if (icnt1 == -1) if (icnt1 == -1)
{ {
Label DOSHORT, FIRST_LOOP, STR2_NEXT, STR1_LOOP, STR1_NEXT, LAST_WORD; Label DOSHORT, FIRST_LOOP, STR2_NEXT, STR1_LOOP, STR1_NEXT;
cmp(cnt1, 4); cmp(cnt1, str1_isL == str2_isL ? 4 : 2);
br(LT, DOSHORT); br(LT, DOSHORT);
sub(cnt2, cnt2, cnt1); sub(cnt2, cnt2, cnt1);
sub(cnt1, cnt1, 4);
mov(result_tmp, cnt2); mov(result_tmp, cnt2);
lea(str1, Address(str1, cnt1, Address::uxtw(1))); lea(str1, Address(str1, cnt1, Address::lsl(str1_chr_shift)));
lea(str2, Address(str2, cnt2, Address::uxtw(1))); lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt1_neg, zr, cnt1, LSL, 1); sub(cnt1_neg, zr, cnt1, LSL, str1_chr_shift);
sub(cnt2_neg, zr, cnt2, LSL, 1); sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
ldr(first, Address(str1, cnt1_neg)); (this->*str1_load_1chr)(first, Address(str1, cnt1_neg));
BIND(FIRST_LOOP); BIND(FIRST_LOOP);
ldr(ch2, Address(str2, cnt2_neg)); (this->*str2_load_1chr)(ch2, Address(str2, cnt2_neg));
cmp(first, ch2); cmp(first, ch2);
br(EQ, STR1_LOOP); br(EQ, STR1_LOOP);
BIND(STR2_NEXT); BIND(STR2_NEXT);
adds(cnt2_neg, cnt2_neg, 2); adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LE, FIRST_LOOP); br(LE, FIRST_LOOP);
b(NOMATCH); b(NOMATCH);
BIND(STR1_LOOP); BIND(STR1_LOOP);
adds(cnt1tmp, cnt1_neg, 8); adds(cnt1tmp, cnt1_neg, str1_chr_size);
add(cnt2tmp, cnt2_neg, 8); add(cnt2tmp, cnt2_neg, str2_chr_size);
br(GE, LAST_WORD); br(GE, MATCH);
BIND(STR1_NEXT); BIND(STR1_NEXT);
ldr(ch1, Address(str1, cnt1tmp)); (this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp));
ldr(ch2, Address(str2, cnt2tmp)); (this->*str2_load_1chr)(ch2, Address(str2, cnt2tmp));
cmp(ch1, ch2); cmp(ch1, ch2);
br(NE, STR2_NEXT); br(NE, STR2_NEXT);
adds(cnt1tmp, cnt1tmp, 8); adds(cnt1tmp, cnt1tmp, str1_chr_size);
add(cnt2tmp, cnt2tmp, 8); add(cnt2tmp, cnt2tmp, str2_chr_size);
br(LT, STR1_NEXT); br(LT, STR1_NEXT);
BIND(LAST_WORD);
ldr(ch1, Address(str1));
sub(str2tmp, str2, cnt1_neg); // adjust to corresponding
ldr(ch2, Address(str2tmp, cnt2_neg)); // word in str2
cmp(ch1, ch2);
br(NE, STR2_NEXT);
b(MATCH); b(MATCH);
BIND(DOSHORT); BIND(DOSHORT);
if (str1_isL == str2_isL) {
cmp(cnt1, 2); cmp(cnt1, 2);
br(LT, DO1); br(LT, DO1);
br(GT, DO3); br(GT, DO3);
}
} }
if (icnt1 == 4) { if (icnt1 == 4) {
Label CH1_LOOP; Label CH1_LOOP;
ldr(ch1, str1); (this->*load_4chr)(ch1, str1);
sub(cnt2, cnt2, 4); sub(cnt2, cnt2, 4);
mov(result_tmp, cnt2); mov(result_tmp, cnt2);
lea(str2, Address(str2, cnt2, Address::uxtw(1))); lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt2_neg, zr, cnt2, LSL, 1); sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
BIND(CH1_LOOP); BIND(CH1_LOOP);
ldr(ch2, Address(str2, cnt2_neg)); (this->*load_4chr)(ch2, Address(str2, cnt2_neg));
cmp(ch1, ch2); cmp(ch1, ch2);
br(EQ, MATCH); br(EQ, MATCH);
adds(cnt2_neg, cnt2_neg, 2); adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LE, CH1_LOOP); br(LE, CH1_LOOP);
b(NOMATCH); b(NOMATCH);
} }
if (icnt1 == -1 || icnt1 == 2) { if ((icnt1 == -1 && str1_isL == str2_isL) || icnt1 == 2) {
Label CH1_LOOP; Label CH1_LOOP;
BIND(DO2); BIND(DO2);
ldrw(ch1, str1); (this->*load_2chr)(ch1, str1);
sub(cnt2, cnt2, 2); sub(cnt2, cnt2, 2);
mov(result_tmp, cnt2); mov(result_tmp, cnt2);
lea(str2, Address(str2, cnt2, Address::uxtw(1))); lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt2_neg, zr, cnt2, LSL, 1); sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
BIND(CH1_LOOP); BIND(CH1_LOOP);
ldrw(ch2, Address(str2, cnt2_neg)); (this->*load_2chr)(ch2, Address(str2, cnt2_neg));
cmp(ch1, ch2); cmp(ch1, ch2);
br(EQ, MATCH); br(EQ, MATCH);
adds(cnt2_neg, cnt2_neg, 2); adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LE, CH1_LOOP); br(LE, CH1_LOOP);
b(NOMATCH); b(NOMATCH);
} }
if (icnt1 == -1 || icnt1 == 3) { if ((icnt1 == -1 && str1_isL == str2_isL) || icnt1 == 3) {
Label FIRST_LOOP, STR2_NEXT, STR1_LOOP; Label FIRST_LOOP, STR2_NEXT, STR1_LOOP;
BIND(DO3); BIND(DO3);
ldrw(first, str1); (this->*load_2chr)(first, str1);
ldrh(ch1, Address(str1, 4)); (this->*str1_load_1chr)(ch1, Address(str1, 2*str1_chr_size));
sub(cnt2, cnt2, 3); sub(cnt2, cnt2, 3);
mov(result_tmp, cnt2); mov(result_tmp, cnt2);
lea(str2, Address(str2, cnt2, Address::uxtw(1))); lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt2_neg, zr, cnt2, LSL, 1); sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
BIND(FIRST_LOOP); BIND(FIRST_LOOP);
ldrw(ch2, Address(str2, cnt2_neg)); (this->*load_2chr)(ch2, Address(str2, cnt2_neg));
cmpw(first, ch2); cmpw(first, ch2);
br(EQ, STR1_LOOP); br(EQ, STR1_LOOP);
BIND(STR2_NEXT); BIND(STR2_NEXT);
adds(cnt2_neg, cnt2_neg, 2); adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LE, FIRST_LOOP); br(LE, FIRST_LOOP);
b(NOMATCH); b(NOMATCH);
BIND(STR1_LOOP); BIND(STR1_LOOP);
add(cnt2tmp, cnt2_neg, 4); add(cnt2tmp, cnt2_neg, 2*str2_chr_size);
ldrh(ch2, Address(str2, cnt2tmp)); (this->*str2_load_1chr)(ch2, Address(str2, cnt2tmp));
cmp(ch1, ch2); cmp(ch1, ch2);
br(NE, STR2_NEXT); br(NE, STR2_NEXT);
b(MATCH); b(MATCH);
@ -4423,24 +4433,31 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
Label DO1_SHORT, DO1_LOOP; Label DO1_SHORT, DO1_LOOP;
BIND(DO1); BIND(DO1);
ldrh(ch1, str1); (this->*str1_load_1chr)(ch1, str1);
cmp(cnt2, 4); cmp(cnt2, 8);
br(LT, DO1_SHORT); br(LT, DO1_SHORT);
if (str2_isL) {
if (!str1_isL) {
tst(ch1, 0xff00);
br(NE, NOMATCH);
}
orr(ch1, ch1, ch1, LSL, 8);
}
orr(ch1, ch1, ch1, LSL, 16); orr(ch1, ch1, ch1, LSL, 16);
orr(ch1, ch1, ch1, LSL, 32); orr(ch1, ch1, ch1, LSL, 32);
sub(cnt2, cnt2, 4); sub(cnt2, cnt2, 8/str2_chr_size);
mov(result_tmp, cnt2); mov(result_tmp, cnt2);
lea(str2, Address(str2, cnt2, Address::uxtw(1))); lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt2_neg, zr, cnt2, LSL, 1); sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
mov(tmp3, 0x0001000100010001); mov(tmp3, str2_isL ? 0x0101010101010101 : 0x0001000100010001);
BIND(CH1_LOOP); BIND(CH1_LOOP);
ldr(ch2, Address(str2, cnt2_neg)); ldr(ch2, Address(str2, cnt2_neg));
eor(ch2, ch1, ch2); eor(ch2, ch1, ch2);
sub(tmp1, ch2, tmp3); sub(tmp1, ch2, tmp3);
orr(tmp2, ch2, 0x7fff7fff7fff7fff); orr(tmp2, ch2, str2_isL ? 0x7f7f7f7f7f7f7f7f : 0x7fff7fff7fff7fff);
bics(tmp1, tmp1, tmp2); bics(tmp1, tmp1, tmp2);
br(NE, HAS_ZERO); br(NE, HAS_ZERO);
adds(cnt2_neg, cnt2_neg, 8); adds(cnt2_neg, cnt2_neg, 8);
@ -4459,13 +4476,13 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
BIND(DO1_SHORT); BIND(DO1_SHORT);
mov(result_tmp, cnt2); mov(result_tmp, cnt2);
lea(str2, Address(str2, cnt2, Address::uxtw(1))); lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt2_neg, zr, cnt2, LSL, 1); sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
BIND(DO1_LOOP); BIND(DO1_LOOP);
ldrh(ch2, Address(str2, cnt2_neg)); (this->*str2_load_1chr)(ch2, Address(str2, cnt2_neg));
cmpw(ch1, ch2); cmpw(ch1, ch2);
br(EQ, MATCH); br(EQ, MATCH);
adds(cnt2_neg, cnt2_neg, 2); adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LT, DO1_LOOP); br(LT, DO1_LOOP);
} }
} }
@ -4473,7 +4490,7 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
mov(result, -1); mov(result, -1);
b(DONE); b(DONE);
BIND(MATCH); BIND(MATCH);
add(result, result_tmp, cnt2_neg, ASR, 1); add(result, result_tmp, cnt2_neg, ASR, str2_chr_shift);
BIND(DONE); BIND(DONE);
} }

View File

@ -1217,7 +1217,7 @@ public:
Register cnt1, Register cnt2, Register cnt1, Register cnt2,
Register tmp1, Register tmp2, Register tmp1, Register tmp2,
Register tmp3, Register tmp4, Register tmp3, Register tmp4,
int int_cnt1, Register result); int int_cnt1, Register result, int ae);
private: private:
void add2_with_carry(Register final_dest_hi, Register dest_hi, Register dest_lo, void add2_with_carry(Register final_dest_hi, Register dest_hi, Register dest_lo,
Register src1, Register src2); Register src1, Register src2);