This commit is contained in:
Vladimir Ivanov 2016-05-27 14:49:05 +00:00
commit 3cda431b12
11 changed files with 336 additions and 142 deletions

View File

@ -3331,7 +3331,6 @@ const bool Matcher::match_rule_supported(int opcode) {
switch (opcode) {
case Op_StrComp:
case Op_StrIndexOf:
if (CompactStrings) return false;
break;
default:
@ -4744,7 +4743,8 @@ encode %{
__ br(Assembler::EQ, cont);
} else {
Label retry_load;
__ prfm(Address(oop), PSTL1STRM);
if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH))
__ prfm(Address(oop), PSTL1STRM);
__ bind(retry_load);
__ ldaxr(tmp, oop);
__ cmp(tmp, disp_hdr);
@ -4799,7 +4799,8 @@ encode %{
__ cmp(rscratch1, disp_hdr);
} else {
Label retry_load, fail;
__ prfm(Address(tmp), PSTL1STRM);
if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH))
__ prfm(Address(tmp), PSTL1STRM);
__ bind(retry_load);
__ ldaxr(rscratch1, tmp);
__ cmp(disp_hdr, rscratch1);
@ -4893,7 +4894,8 @@ encode %{
__ cmp(tmp, box);
} else {
Label retry_load;
__ prfm(Address(oop), PSTL1STRM);
if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH))
__ prfm(Address(oop), PSTL1STRM);
__ bind(retry_load);
__ ldxr(tmp, oop);
__ cmp(box, tmp);
@ -14953,26 +14955,83 @@ instruct string_compareU(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 c
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)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
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" %}
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UU)" %}
ins_encode %{
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register,
$tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register,
-1, $result$$Register);
-1, $result$$Register, StrIntrinsicNode::UU);
%}
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,
iRegI tmp3, iRegI tmp4, rFlagsReg cr)
%{
@ -14980,7 +15039,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)));
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" %}
format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UU)" %}
ins_encode %{
int icnt2 = (int)$int_cnt2$$constant;
@ -14988,7 +15047,70 @@ instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
$cnt1$$Register, zr,
$tmp1$$Register, $tmp2$$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);
%}

View File

@ -23,8 +23,8 @@
*
*/
#ifndef CPU_X86_VM_C1_LIRASSEMBLER_X86_HPP
#define CPU_X86_VM_C1_LIRASSEMBLER_X86_HPP
#ifndef CPU_AARCH64_VM_C1_LIRASSEMBLER_AARCH64_HPP
#define CPU_AARCH64_VM_C1_LIRASSEMBLER_AARCH64_HPP
// ArrayCopyStub needs access to bailout
friend class ArrayCopyStub;
@ -78,4 +78,4 @@ enum { call_stub_size = 12 * NativeInstruction::instruction_size,
exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
deopt_handler_size = 7 * NativeInstruction::instruction_size };
#endif // CPU_X86_VM_C1_LIRASSEMBLER_X86_HPP
#endif // CPU_AARCH64_VM_C1_LIRASSEMBLER_AARCH64_HPP

View File

@ -1643,7 +1643,8 @@ void MacroAssembler::atomic_incw(Register counter_addr, Register tmp, Register t
return;
}
Label retry_load;
prfm(Address(counter_addr), PSTL1STRM);
if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH))
prfm(Address(counter_addr), PSTL1STRM);
bind(retry_load);
// flush and load exclusive from the memory location
ldxrw(tmp, counter_addr);
@ -2084,7 +2085,8 @@ void MacroAssembler::cmpxchgptr(Register oldv, Register newv, Register addr, Reg
membar(AnyAny);
} else {
Label retry_load, nope;
prfm(Address(addr), PSTL1STRM);
if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH))
prfm(Address(addr), PSTL1STRM);
bind(retry_load);
// flush and load exclusive from the memory location
// and fail if it is not what we expect
@ -2120,7 +2122,8 @@ void MacroAssembler::cmpxchgw(Register oldv, Register newv, Register addr, Regis
membar(AnyAny);
} else {
Label retry_load, nope;
prfm(Address(addr), PSTL1STRM);
if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH))
prfm(Address(addr), PSTL1STRM);
bind(retry_load);
// flush and load exclusive from the memory location
// and fail if it is not what we expect
@ -2155,7 +2158,8 @@ void MacroAssembler::cmpxchg(Register addr, Register expected,
} else {
BLOCK_COMMENT("cmpxchg {");
Label retry_load, done;
prfm(Address(addr), PSTL1STRM);
if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH))
prfm(Address(addr), PSTL1STRM);
bind(retry_load);
load_exclusive(tmp, addr, size, acquire);
if (size == xword)
@ -2194,7 +2198,8 @@ void MacroAssembler::atomic_##NAME(Register prev, RegisterOrConstant incr, Regis
result = different(prev, incr, addr) ? prev : rscratch2; \
\
Label retry_load; \
prfm(Address(addr), PSTL1STRM); \
if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH)) \
prfm(Address(addr), PSTL1STRM); \
bind(retry_load); \
LDXR(result, addr); \
OP(rscratch1, result, incr); \
@ -2224,7 +2229,8 @@ void MacroAssembler::atomic_##OP(Register prev, Register newv, Register addr) {
result = different(prev, newv, addr) ? prev : rscratch2; \
\
Label retry_load; \
prfm(Address(addr), PSTL1STRM); \
if ((VM_Version::features() & VM_Version::CPU_STXR_PREFETCH)) \
prfm(Address(addr), PSTL1STRM); \
bind(retry_load); \
LDXR(result, addr); \
STXR(rscratch1, newv, addr); \
@ -4136,13 +4142,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
void MacroAssembler::string_indexof(Register str2, Register str1,
Register cnt2, Register cnt1,
Register tmp1, Register tmp2,
Register tmp3, Register tmp4,
int icnt1, Register result) {
int icnt1, Register result, int ae) {
Label BM, LINEARSEARCH, DONE, NOMATCH, MATCH;
Register ch1 = rscratch1;
@ -4153,6 +4160,21 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
Register cnt2_neg = cnt2;
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:
// if (substr.count > string.count) return -1;
// if (substr.count == 0) return 0;
@ -4242,7 +4264,7 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
mov(cnt1tmp, 0);
sub(cnt1end, cnt1, 1);
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);
add(cnt1tmp, cnt1tmp, 1);
br(HS, BCSKIP);
@ -4254,36 +4276,36 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
mov(result_tmp, str2);
sub(cnt2, cnt2, cnt1);
add(str2end, str2, cnt2, LSL, 1);
add(str2end, str2, cnt2, LSL, str2_chr_shift);
BIND(BMLOOPSTR2);
sub(cnt1tmp, cnt1, 1);
ldrh(ch1, Address(str1, cnt1tmp, Address::lsl(1)));
ldrh(skipch, Address(str2, cnt1tmp, Address::lsl(1)));
(this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp, Address::lsl(str1_chr_shift)));
(this->*str2_load_1chr)(skipch, Address(str2, cnt1tmp, Address::lsl(str2_chr_shift)));
cmp(ch1, skipch);
br(NE, BMSKIP);
subs(cnt1tmp, cnt1tmp, 1);
br(LT, BMMATCH);
BIND(BMLOOPSTR1);
ldrh(ch1, Address(str1, cnt1tmp, Address::lsl(1)));
ldrh(ch2, Address(str2, cnt1tmp, Address::lsl(1)));
(this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp, Address::lsl(str1_chr_shift)));
(this->*str2_load_1chr)(ch2, Address(str2, cnt1tmp, Address::lsl(str2_chr_shift)));
cmp(ch1, ch2);
br(NE, BMSKIP);
subs(cnt1tmp, cnt1tmp, 1);
br(GE, BMLOOPSTR1);
BIND(BMMATCH);
sub(result_tmp, str2, result_tmp);
lsr(result, result_tmp, 1);
sub(result, str2, result_tmp);
if (!str2_isL) lsr(result, result, 1);
add(sp, sp, 128);
b(DONE);
BIND(BMADV);
add(str2, str2, 2);
add(str2, str2, str2_chr_size);
b(BMCHECKEND);
BIND(BMSKIP);
cmp(skipch, 128);
br(HS, BMADV);
ldrb(ch2, Address(sp, skipch));
add(str2, str2, cnt1, LSL, 1);
sub(str2, str2, ch2, LSL, 1);
add(str2, str2, cnt1, LSL, str2_chr_shift);
sub(str2, str2, ch2, LSL, str2_chr_shift);
BIND(BMCHECKEND);
cmp(str2, str2end);
br(LE, BMLOOPSTR2);
@ -4300,119 +4322,113 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
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);
sub(cnt2, cnt2, cnt1);
sub(cnt1, cnt1, 4);
mov(result_tmp, cnt2);
lea(str1, Address(str1, cnt1, Address::uxtw(1)));
lea(str2, Address(str2, cnt2, Address::uxtw(1)));
sub(cnt1_neg, zr, cnt1, LSL, 1);
sub(cnt2_neg, zr, cnt2, LSL, 1);
ldr(first, Address(str1, cnt1_neg));
lea(str1, Address(str1, cnt1, Address::lsl(str1_chr_shift)));
lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt1_neg, zr, cnt1, LSL, str1_chr_shift);
sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
(this->*str1_load_1chr)(first, Address(str1, cnt1_neg));
BIND(FIRST_LOOP);
ldr(ch2, Address(str2, cnt2_neg));
(this->*str2_load_1chr)(ch2, Address(str2, cnt2_neg));
cmp(first, ch2);
br(EQ, STR1_LOOP);
BIND(STR2_NEXT);
adds(cnt2_neg, cnt2_neg, 2);
adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LE, FIRST_LOOP);
b(NOMATCH);
BIND(STR1_LOOP);
adds(cnt1tmp, cnt1_neg, 8);
add(cnt2tmp, cnt2_neg, 8);
br(GE, LAST_WORD);
adds(cnt1tmp, cnt1_neg, str1_chr_size);
add(cnt2tmp, cnt2_neg, str2_chr_size);
br(GE, MATCH);
BIND(STR1_NEXT);
ldr(ch1, Address(str1, cnt1tmp));
ldr(ch2, Address(str2, cnt2tmp));
(this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp));
(this->*str2_load_1chr)(ch2, Address(str2, cnt2tmp));
cmp(ch1, ch2);
br(NE, STR2_NEXT);
adds(cnt1tmp, cnt1tmp, 8);
add(cnt2tmp, cnt2tmp, 8);
adds(cnt1tmp, cnt1tmp, str1_chr_size);
add(cnt2tmp, cnt2tmp, str2_chr_size);
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);
BIND(DOSHORT);
if (str1_isL == str2_isL) {
cmp(cnt1, 2);
br(LT, DO1);
br(GT, DO3);
}
}
if (icnt1 == 4) {
Label CH1_LOOP;
ldr(ch1, str1);
(this->*load_4chr)(ch1, str1);
sub(cnt2, cnt2, 4);
mov(result_tmp, cnt2);
lea(str2, Address(str2, cnt2, Address::uxtw(1)));
sub(cnt2_neg, zr, cnt2, LSL, 1);
lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
BIND(CH1_LOOP);
ldr(ch2, Address(str2, cnt2_neg));
(this->*load_4chr)(ch2, Address(str2, cnt2_neg));
cmp(ch1, ch2);
br(EQ, MATCH);
adds(cnt2_neg, cnt2_neg, 2);
adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LE, CH1_LOOP);
b(NOMATCH);
}
if (icnt1 == -1 || icnt1 == 2) {
if ((icnt1 == -1 && str1_isL == str2_isL) || icnt1 == 2) {
Label CH1_LOOP;
BIND(DO2);
ldrw(ch1, str1);
(this->*load_2chr)(ch1, str1);
sub(cnt2, cnt2, 2);
mov(result_tmp, cnt2);
lea(str2, Address(str2, cnt2, Address::uxtw(1)));
sub(cnt2_neg, zr, cnt2, LSL, 1);
lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
BIND(CH1_LOOP);
ldrw(ch2, Address(str2, cnt2_neg));
(this->*load_2chr)(ch2, Address(str2, cnt2_neg));
cmp(ch1, ch2);
br(EQ, MATCH);
adds(cnt2_neg, cnt2_neg, 2);
adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LE, CH1_LOOP);
b(NOMATCH);
}
if (icnt1 == -1 || icnt1 == 3) {
if ((icnt1 == -1 && str1_isL == str2_isL) || icnt1 == 3) {
Label FIRST_LOOP, STR2_NEXT, STR1_LOOP;
BIND(DO3);
ldrw(first, str1);
ldrh(ch1, Address(str1, 4));
(this->*load_2chr)(first, str1);
(this->*str1_load_1chr)(ch1, Address(str1, 2*str1_chr_size));
sub(cnt2, cnt2, 3);
mov(result_tmp, cnt2);
lea(str2, Address(str2, cnt2, Address::uxtw(1)));
sub(cnt2_neg, zr, cnt2, LSL, 1);
lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
BIND(FIRST_LOOP);
ldrw(ch2, Address(str2, cnt2_neg));
(this->*load_2chr)(ch2, Address(str2, cnt2_neg));
cmpw(first, ch2);
br(EQ, STR1_LOOP);
BIND(STR2_NEXT);
adds(cnt2_neg, cnt2_neg, 2);
adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LE, FIRST_LOOP);
b(NOMATCH);
BIND(STR1_LOOP);
add(cnt2tmp, cnt2_neg, 4);
ldrh(ch2, Address(str2, cnt2tmp));
add(cnt2tmp, cnt2_neg, 2*str2_chr_size);
(this->*str2_load_1chr)(ch2, Address(str2, cnt2tmp));
cmp(ch1, ch2);
br(NE, STR2_NEXT);
b(MATCH);
@ -4423,24 +4439,31 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
Label DO1_SHORT, DO1_LOOP;
BIND(DO1);
ldrh(ch1, str1);
cmp(cnt2, 4);
(this->*str1_load_1chr)(ch1, str1);
cmp(cnt2, 8);
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, 32);
sub(cnt2, cnt2, 4);
sub(cnt2, cnt2, 8/str2_chr_size);
mov(result_tmp, cnt2);
lea(str2, Address(str2, cnt2, Address::uxtw(1)));
sub(cnt2_neg, zr, cnt2, LSL, 1);
lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
mov(tmp3, 0x0001000100010001);
mov(tmp3, str2_isL ? 0x0101010101010101 : 0x0001000100010001);
BIND(CH1_LOOP);
ldr(ch2, Address(str2, cnt2_neg));
eor(ch2, ch1, ch2);
sub(tmp1, ch2, tmp3);
orr(tmp2, ch2, 0x7fff7fff7fff7fff);
orr(tmp2, ch2, str2_isL ? 0x7f7f7f7f7f7f7f7f : 0x7fff7fff7fff7fff);
bics(tmp1, tmp1, tmp2);
br(NE, HAS_ZERO);
adds(cnt2_neg, cnt2_neg, 8);
@ -4459,13 +4482,13 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
BIND(DO1_SHORT);
mov(result_tmp, cnt2);
lea(str2, Address(str2, cnt2, Address::uxtw(1)));
sub(cnt2_neg, zr, cnt2, LSL, 1);
lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
BIND(DO1_LOOP);
ldrh(ch2, Address(str2, cnt2_neg));
(this->*str2_load_1chr)(ch2, Address(str2, cnt2_neg));
cmpw(ch1, ch2);
br(EQ, MATCH);
adds(cnt2_neg, cnt2_neg, 2);
adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LT, DO1_LOOP);
}
}
@ -4473,7 +4496,7 @@ void MacroAssembler::string_indexof(Register str2, Register str1,
mov(result, -1);
b(DONE);
BIND(MATCH);
add(result, result_tmp, cnt2_neg, ASR, 1);
add(result, result_tmp, cnt2_neg, ASR, str2_chr_shift);
BIND(DONE);
}

View File

@ -545,6 +545,15 @@ public:
mrs(0b011, 0b0000, 0b0000, 0b111, reg);
}
// CTR_EL0: op1 == 011
// CRn == 0000
// CRm == 0000
// op2 == 001
inline void get_ctr_el0(Register reg)
{
mrs(0b011, 0b0000, 0b0000, 0b001, reg);
}
// idiv variant which deals with MINLONG as dividend and -1 as divisor
int corrected_idivl(Register result, Register ra, Register rb,
bool want_remainder, Register tmp = rscratch1);
@ -1217,7 +1226,7 @@ public:
Register cnt1, Register cnt2,
Register tmp1, Register tmp2,
Register tmp3, Register tmp4,
int int_cnt1, Register result);
int int_cnt1, Register result, int ae);
private:
void add2_with_carry(Register final_dest_hi, Register dest_hi, Register dest_lo,
Register src1, Register src2);

View File

@ -105,6 +105,9 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ get_dczid_el0(rscratch1);
__ strw(rscratch1, Address(c_rarg0, in_bytes(VM_Version::dczid_el0_offset())));
__ get_ctr_el0(rscratch1);
__ strw(rscratch1, Address(c_rarg0, in_bytes(VM_Version::ctr_el0_offset())));
__ leave();
__ ret(lr);
@ -124,16 +127,20 @@ void VM_Version::get_processor_features() {
getPsrInfo_stub(&_psr_info);
int dcache_line = VM_Version::dcache_line_size();
if (FLAG_IS_DEFAULT(AllocatePrefetchDistance))
FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256);
FLAG_SET_DEFAULT(AllocatePrefetchDistance, 3*dcache_line);
if (FLAG_IS_DEFAULT(AllocatePrefetchStepSize))
FLAG_SET_DEFAULT(AllocatePrefetchStepSize, 64);
FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 256);
FLAG_SET_DEFAULT(PrefetchFieldsAhead, 256);
FLAG_SET_DEFAULT(AllocatePrefetchStepSize, dcache_line);
if (FLAG_IS_DEFAULT(PrefetchScanIntervalInBytes))
FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 3*dcache_line);
if (FLAG_IS_DEFAULT(PrefetchCopyIntervalInBytes))
FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, 256);
if ((PrefetchCopyIntervalInBytes & 7) || (PrefetchCopyIntervalInBytes >= 32768)) {
warning("PrefetchCopyIntervalInBytes must be a multiple of 8 and < 32768");
FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, 3*dcache_line);
if (PrefetchCopyIntervalInBytes != -1 &&
((PrefetchCopyIntervalInBytes & 7) || (PrefetchCopyIntervalInBytes >= 32768))) {
warning("PrefetchCopyIntervalInBytes must be -1, or a multiple of 8 and < 32768");
PrefetchCopyIntervalInBytes &= ~7;
if (PrefetchCopyIntervalInBytes >= 32768)
PrefetchCopyIntervalInBytes = 32760;
@ -170,6 +177,7 @@ void VM_Version::get_processor_features() {
// Enable vendor specific features
if (_cpu == CPU_CAVIUM && _variant == 0) _features |= CPU_DMB_ATOMICS;
if (_cpu == CPU_ARM && (_model == 0xd03 || _model2 == 0xd03)) _features |= CPU_A53MAC;
if (_cpu == CPU_ARM && (_model == 0xd07 || _model2 == 0xd07)) _features |= CPU_STXR_PREFETCH;
// If an olde style /proc/cpuinfo (cpu_lines == 1) then if _model is an A57 (0xd07)
// we assume the worst and assume we could be on a big little system and have
// undisclosed A53 cores which we could be swapped to at any stage

View File

@ -42,6 +42,7 @@ protected:
struct PsrInfo {
uint32_t dczid_el0;
uint32_t ctr_el0;
};
static PsrInfo _psr_info;
static void get_processor_features();
@ -78,6 +79,7 @@ public:
CPU_SHA2 = (1<<6),
CPU_CRC32 = (1<<7),
CPU_LSE = (1<<8),
CPU_STXR_PREFETCH= (1 << 29),
CPU_A53MAC = (1 << 30),
CPU_DMB_ATOMICS = (1 << 31),
};
@ -88,6 +90,7 @@ public:
static int cpu_variant() { return _variant; }
static int cpu_revision() { return _revision; }
static ByteSize dczid_el0_offset() { return byte_offset_of(PsrInfo, dczid_el0); }
static ByteSize ctr_el0_offset() { return byte_offset_of(PsrInfo, ctr_el0); }
static bool is_zva_enabled() {
// Check the DZP bit (bit 4) of dczid_el0 is zero
// and block size (bit 0~3) is not zero.
@ -98,6 +101,12 @@ public:
assert(is_zva_enabled(), "ZVA not available");
return 4 << (_psr_info.dczid_el0 & 0xf);
}
static int icache_line_size() {
return (1 << (_psr_info.ctr_el0 & 0x0f)) * 4;
}
static int dcache_line_size() {
return (1 << ((_psr_info.ctr_el0 >> 16) & 0x0f)) * 4;
}
};
#endif // CPU_AARCH64_VM_VM_VERSION_AARCH64_HPP

View File

@ -3084,49 +3084,25 @@ JRT_END
frame SharedRuntime::look_for_reserved_stack_annotated_method(JavaThread* thread, frame fr) {
frame activation;
int decode_offset = 0;
nmethod* nm = NULL;
frame prv_fr = fr;
CompiledMethod* nm = NULL;
int count = 1;
assert(fr.is_java_frame(), "Must start on Java frame");
while (!fr.is_first_frame()) {
while (true) {
Method* method = NULL;
// Compiled java method case.
if (decode_offset != 0) {
DebugInfoReadStream stream(nm, decode_offset);
decode_offset = stream.read_int();
method = (Method*)nm->metadata_at(stream.read_int());
if (fr.is_interpreted_frame()) {
method = fr.interpreter_frame_method();
} else {
if (fr.is_first_java_frame()) break;
address pc = fr.pc();
prv_fr = fr;
if (fr.is_interpreted_frame()) {
method = fr.interpreter_frame_method();
fr = fr.java_sender();
} else {
CodeBlob* cb = fr.cb();
fr = fr.java_sender();
if (cb == NULL || !cb->is_nmethod()) {
continue;
}
nm = (nmethod*)cb;
if (nm->method()->is_native()) {
method = nm->method();
} else {
PcDesc* pd = nm->pc_desc_at(pc);
assert(pd != NULL, "PcDesc must not be NULL");
decode_offset = pd->scope_decode_offset();
// if decode_offset is not equal to 0, it will execute the
// "compiled java method case" at the beginning of the loop.
continue;
}
CodeBlob* cb = fr.cb();
if (cb != NULL && cb->is_compiled()) {
nm = cb->as_compiled_method();
method = nm->method();
}
}
if (method->has_reserved_stack_access()) {
if ((method != NULL) && method->has_reserved_stack_access()) {
ResourceMark rm(thread);
activation = prv_fr;
activation = fr;
warning("Potentially dangerous stack overflow in "
"ReservedStackAccess annotated method %s [%d]",
method->name_and_sig_as_C_string(), count++);
@ -3136,6 +3112,11 @@ frame SharedRuntime::look_for_reserved_stack_annotated_method(JavaThread* thread
event.commit();
}
}
if (fr.is_first_java_frame()) {
break;
} else {
fr = fr.java_sender();
}
}
return activation;
}

View File

@ -73,6 +73,7 @@ public class MultiCommand extends AbstractTestBase {
public void test() {
Scenario.Builder builder = Scenario.getBuilder();
builder.addFlag("-Xmixed");
builder.addFlag("-XX:CompilerDirectivesLimit=101");
for (CompileCommand cc : testCases) {
cc.print();
builder.add(cc);

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright 2016 Azul Systems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test TestOnSpinWaitEnableDisable
* @summary Test to ensure basic functioning of java.lang.Thread.onSpinWait
* @bug 8157683
* @run main TestOnSpinWaitEnableDisable
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_onSpinWait TestOnSpinWaitEnableDisable
*/
public class TestOnSpinWaitEnableDisable {
public static void main(String[] args) {
for (int i = 0; i < 50_000; i++) {
java.lang.Thread.onSpinWait();
}
}
}

View File

@ -33,6 +33,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -52,14 +53,16 @@ public class JitTesterDriver {
throw new Error("Unexpected exception on test jvm start :" + e, e);
}
Pattern splitOut = Pattern.compile("\\n"); // tests use \n only in stdout
Pattern splitErr = Pattern.compile("\\r?\\n"); // can handle both \r\n and \n
Path testDir = Paths.get(Utils.TEST_SRC);
String goldOut = formatOutput(streamGoldFile(testDir, args[0], "out"), s -> true);
Asserts.assertEQ(oa.getStdout(), goldOut, "Actual stdout isn't equal to golden one");
String anlzOut = formatOutput(Arrays.stream(splitOut.split(oa.getStdout())), s -> true);
Asserts.assertEQ(anlzOut, goldOut, "Actual stdout isn't equal to golden one");
// TODO: add a comment why we skip such lines
Predicate<String> notStartWhitespaces = s -> !(s.startsWith("\t") || s.startsWith(" "));
String goldErr = formatOutput(streamGoldFile(testDir, args[0], "err"), notStartWhitespaces);
String anlzErr = formatOutput(Arrays.stream(oa.getStderr().split(Utils.NEW_LINE)),
String anlzErr = formatOutput(Arrays.stream(splitErr.split(oa.getStderr())),
notStartWhitespaces);
Asserts.assertEQ(anlzErr, goldErr, "Actual stderr isn't equal to golden one");

View File

@ -37,7 +37,6 @@ import jdk.test.lib.jittester.Nothing;
import jdk.test.lib.jittester.Operator;
import jdk.test.lib.jittester.OperatorKind;
import jdk.test.lib.jittester.PrintVariables;
import jdk.test.lib.jittester.ProductionFailedException;
import jdk.test.lib.jittester.Statement;
import jdk.test.lib.jittester.StaticMemberVariable;
import jdk.test.lib.jittester.Symbol;
@ -171,22 +170,22 @@ public class FixedTrees {
TryCatchBlock tryCatch1 = new TryCatchBlock(tryNode, nothing, catchBlocks1, 3);
TypeKlass printStreamKlass = new TypeKlass("java.io.PrintStream");
TypeKlass systemKlass = new TypeKlass("java.lang.System");
FunctionInfo systemOutPrintlnInfo = new FunctionInfo("println", printStreamKlass,
FunctionInfo systemOutPrintInfo = new FunctionInfo("print", printStreamKlass,
TypeList.VOID, 0, FunctionInfo.PUBLIC,
new VariableInfo("this", owner, printStreamKlass, VariableInfo.LOCAL | VariableInfo.INITIALIZED),
new VariableInfo("t", owner, TypeList.OBJECT,
VariableInfo.LOCAL | VariableInfo.INITIALIZED));
List<IRNode> printlnArgs = new ArrayList<>();
List<IRNode> printArgs = new ArrayList<>();
VariableInfo systemOutInfo = new VariableInfo("out", systemKlass, printStreamKlass,
VariableInfo.STATIC | VariableInfo.PUBLIC);
StaticMemberVariable systemOutVar = new StaticMemberVariable(owner, systemOutInfo);
printlnArgs.add(systemOutVar);
printlnArgs.add(tVar);
Function println = new Function(printStreamKlass, systemOutPrintlnInfo, printlnArgs);
ArrayList<IRNode> printlnBlockContent = new ArrayList<>();
printlnBlockContent.add(new Statement(println, true));
Block printlnBlock = new Block(owner, TypeList.VOID, printlnBlockContent, 3);
TryCatchBlock tryCatch2 = new TryCatchBlock(printlnBlock, nothing, catchBlocks2, 3);
printArgs.add(systemOutVar);
printArgs.add(tVar);
Function print = new Function(printStreamKlass, systemOutPrintInfo, printArgs);
ArrayList<IRNode> printBlockContent = new ArrayList<>();
printBlockContent.add(new Statement(print, true));
Block printBlock = new Block(owner, TypeList.VOID, printBlockContent, 3);
TryCatchBlock tryCatch2 = new TryCatchBlock(printBlock, nothing, catchBlocks2, 3);
List<IRNode> mainTryCatchBlockContent = new ArrayList<>();
mainTryCatchBlockContent.add(new Statement(testInit, true));