mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-15 01:18:40 +00:00
Merge branch 'master' of https://github.com/openjdk/jdk into fix/vh-adapt-cache
This commit is contained in:
commit
59aca0dfb5
@ -5379,7 +5379,6 @@ void MacroAssembler::set_narrow_klass(Register dst, Klass* k) {
|
||||
assert (UseCompressedClassPointers, "should only be used for compressed headers");
|
||||
assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder");
|
||||
int index = oop_recorder()->find_index(k);
|
||||
assert(! Universe::heap()->is_in(k), "should not be an oop");
|
||||
|
||||
InstructionMark im(this);
|
||||
RelocationHolder rspec = metadata_Relocation::spec(index);
|
||||
|
||||
@ -2067,6 +2067,83 @@ void C2_MacroAssembler::enc_cmove_cmp_fp(int cmpFlag, FloatRegister op1, FloatRe
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::enc_cmove_fp_cmp(int cmpFlag, Register op1, Register op2,
|
||||
FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
bool is_unsigned = (cmpFlag & unsigned_branch_mask) == unsigned_branch_mask;
|
||||
int op_select = cmpFlag & (~unsigned_branch_mask);
|
||||
|
||||
switch (op_select) {
|
||||
case BoolTest::eq:
|
||||
cmov_fp_eq(op1, op2, dst, src, is_single);
|
||||
break;
|
||||
case BoolTest::ne:
|
||||
cmov_fp_ne(op1, op2, dst, src, is_single);
|
||||
break;
|
||||
case BoolTest::le:
|
||||
if (is_unsigned) {
|
||||
cmov_fp_leu(op1, op2, dst, src, is_single);
|
||||
} else {
|
||||
cmov_fp_le(op1, op2, dst, src, is_single);
|
||||
}
|
||||
break;
|
||||
case BoolTest::ge:
|
||||
if (is_unsigned) {
|
||||
cmov_fp_geu(op1, op2, dst, src, is_single);
|
||||
} else {
|
||||
cmov_fp_ge(op1, op2, dst, src, is_single);
|
||||
}
|
||||
break;
|
||||
case BoolTest::lt:
|
||||
if (is_unsigned) {
|
||||
cmov_fp_ltu(op1, op2, dst, src, is_single);
|
||||
} else {
|
||||
cmov_fp_lt(op1, op2, dst, src, is_single);
|
||||
}
|
||||
break;
|
||||
case BoolTest::gt:
|
||||
if (is_unsigned) {
|
||||
cmov_fp_gtu(op1, op2, dst, src, is_single);
|
||||
} else {
|
||||
cmov_fp_gt(op1, op2, dst, src, is_single);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false, "unsupported compare condition");
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::enc_cmove_fp_cmp_fp(int cmpFlag,
|
||||
FloatRegister op1, FloatRegister op2,
|
||||
FloatRegister dst, FloatRegister src,
|
||||
bool cmp_single, bool cmov_single) {
|
||||
int op_select = cmpFlag & (~unsigned_branch_mask);
|
||||
|
||||
switch (op_select) {
|
||||
case BoolTest::eq:
|
||||
cmov_fp_cmp_fp_eq(op1, op2, dst, src, cmp_single, cmov_single);
|
||||
break;
|
||||
case BoolTest::ne:
|
||||
cmov_fp_cmp_fp_ne(op1, op2, dst, src, cmp_single, cmov_single);
|
||||
break;
|
||||
case BoolTest::le:
|
||||
cmov_fp_cmp_fp_le(op1, op2, dst, src, cmp_single, cmov_single);
|
||||
break;
|
||||
case BoolTest::ge:
|
||||
cmov_fp_cmp_fp_ge(op1, op2, dst, src, cmp_single, cmov_single);
|
||||
break;
|
||||
case BoolTest::lt:
|
||||
cmov_fp_cmp_fp_lt(op1, op2, dst, src, cmp_single, cmov_single);
|
||||
break;
|
||||
case BoolTest::gt:
|
||||
cmov_fp_cmp_fp_gt(op1, op2, dst, src, cmp_single, cmov_single);
|
||||
break;
|
||||
default:
|
||||
assert(false, "unsupported compare condition");
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
// Set dst to NaN if any NaN input.
|
||||
void C2_MacroAssembler::minmax_fp(FloatRegister dst, FloatRegister src1, FloatRegister src2,
|
||||
FLOAT_TYPE ft, bool is_min) {
|
||||
|
||||
@ -132,6 +132,13 @@
|
||||
FloatRegister op1, FloatRegister op2,
|
||||
Register dst, Register src, bool is_single);
|
||||
|
||||
void enc_cmove_fp_cmp(int cmpFlag, Register op1, Register op2,
|
||||
FloatRegister dst, FloatRegister src, bool is_single);
|
||||
|
||||
void enc_cmove_fp_cmp_fp(int cmpFlag, FloatRegister op1, FloatRegister op2,
|
||||
FloatRegister dst, FloatRegister src,
|
||||
bool cmp_single, bool cmov_single);
|
||||
|
||||
void spill(Register r, bool is64, int offset) {
|
||||
is64 ? sd(r, Address(sp, offset))
|
||||
: sw(r, Address(sp, offset));
|
||||
|
||||
@ -1233,7 +1233,119 @@ void MacroAssembler::cmov_gtu(Register cmp1, Register cmp2, Register dst, Regist
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// ----------- cmove, compare float -----------
|
||||
// ----------- cmove float/double -----------
|
||||
|
||||
void MacroAssembler::cmov_fp_eq(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
Label no_set;
|
||||
bne(cmp1, cmp2, no_set);
|
||||
if (is_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_ne(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
Label no_set;
|
||||
beq(cmp1, cmp2, no_set);
|
||||
if (is_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_le(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
Label no_set;
|
||||
bgt(cmp1, cmp2, no_set);
|
||||
if (is_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_leu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
Label no_set;
|
||||
bgtu(cmp1, cmp2, no_set);
|
||||
if (is_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_ge(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
Label no_set;
|
||||
blt(cmp1, cmp2, no_set);
|
||||
if (is_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_geu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
Label no_set;
|
||||
bltu(cmp1, cmp2, no_set);
|
||||
if (is_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_lt(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
Label no_set;
|
||||
bge(cmp1, cmp2, no_set);
|
||||
if (is_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_ltu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
Label no_set;
|
||||
bgeu(cmp1, cmp2, no_set);
|
||||
if (is_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_gt(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
Label no_set;
|
||||
ble(cmp1, cmp2, no_set);
|
||||
if (is_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_gtu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) {
|
||||
Label no_set;
|
||||
bleu(cmp1, cmp2, no_set);
|
||||
if (is_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// ----------- cmove, compare float/double -----------
|
||||
//
|
||||
// For CmpF/D + CMoveI/L, ordered ones are quite straight and simple,
|
||||
// so, just list behaviour of unordered ones as follow.
|
||||
@ -1391,6 +1503,148 @@ void MacroAssembler::cmov_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, Regi
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// ----------- cmove float/double, compare float/double -----------
|
||||
|
||||
// Move src to dst only if cmp1 == cmp2,
|
||||
// otherwise leave dst unchanged, including the case where one of them is NaN.
|
||||
// Clarification:
|
||||
// java code : cmp1 != cmp2 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 eq cmp2), dst, src
|
||||
void MacroAssembler::cmov_fp_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2,
|
||||
FloatRegister dst, FloatRegister src,
|
||||
bool cmp_single, bool cmov_single) {
|
||||
Label no_set;
|
||||
if (cmp_single) {
|
||||
// jump if cmp1 != cmp2, including the case of NaN
|
||||
// not jump (i.e. move src to dst) if cmp1 == cmp2
|
||||
float_bne(cmp1, cmp2, no_set);
|
||||
} else {
|
||||
double_bne(cmp1, cmp2, no_set);
|
||||
}
|
||||
if (cmov_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// Keep dst unchanged only if cmp1 == cmp2,
|
||||
// otherwise move src to dst, including the case where one of them is NaN.
|
||||
// Clarification:
|
||||
// java code : cmp1 == cmp2 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 ne cmp2), dst, src
|
||||
void MacroAssembler::cmov_fp_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2,
|
||||
FloatRegister dst, FloatRegister src,
|
||||
bool cmp_single, bool cmov_single) {
|
||||
Label no_set;
|
||||
if (cmp_single) {
|
||||
// jump if cmp1 == cmp2
|
||||
// not jump (i.e. move src to dst) if cmp1 != cmp2, including the case of NaN
|
||||
float_beq(cmp1, cmp2, no_set);
|
||||
} else {
|
||||
double_beq(cmp1, cmp2, no_set);
|
||||
}
|
||||
if (cmov_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// When cmp1 <= cmp2 or any of them is NaN then dst = src, otherwise, dst = dst
|
||||
// Clarification
|
||||
// scenario 1:
|
||||
// java code : cmp2 < cmp1 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 le cmp2), dst, src
|
||||
// scenario 2:
|
||||
// java code : cmp1 > cmp2 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 le cmp2), dst, src
|
||||
void MacroAssembler::cmov_fp_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2,
|
||||
FloatRegister dst, FloatRegister src,
|
||||
bool cmp_single, bool cmov_single) {
|
||||
Label no_set;
|
||||
if (cmp_single) {
|
||||
// jump if cmp1 > cmp2
|
||||
// not jump (i.e. move src to dst) if cmp1 <= cmp2 or either is NaN
|
||||
float_bgt(cmp1, cmp2, no_set);
|
||||
} else {
|
||||
double_bgt(cmp1, cmp2, no_set);
|
||||
}
|
||||
if (cmov_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2,
|
||||
FloatRegister dst, FloatRegister src,
|
||||
bool cmp_single, bool cmov_single) {
|
||||
Label no_set;
|
||||
if (cmp_single) {
|
||||
// jump if cmp1 < cmp2 or either is NaN
|
||||
// not jump (i.e. move src to dst) if cmp1 >= cmp2
|
||||
float_blt(cmp1, cmp2, no_set, false, true);
|
||||
} else {
|
||||
double_blt(cmp1, cmp2, no_set, false, true);
|
||||
}
|
||||
if (cmov_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// When cmp1 < cmp2 or any of them is NaN then dst = src, otherwise, dst = dst
|
||||
// Clarification
|
||||
// scenario 1:
|
||||
// java code : cmp2 <= cmp1 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 lt cmp2), dst, src
|
||||
// scenario 2:
|
||||
// java code : cmp1 >= cmp2 ? dst : src
|
||||
// transformed to : CMove dst, (cmp1 lt cmp2), dst, src
|
||||
void MacroAssembler::cmov_fp_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2,
|
||||
FloatRegister dst, FloatRegister src,
|
||||
bool cmp_single, bool cmov_single) {
|
||||
Label no_set;
|
||||
if (cmp_single) {
|
||||
// jump if cmp1 >= cmp2
|
||||
// not jump (i.e. move src to dst) if cmp1 < cmp2 or either is NaN
|
||||
float_bge(cmp1, cmp2, no_set);
|
||||
} else {
|
||||
double_bge(cmp1, cmp2, no_set);
|
||||
}
|
||||
if (cmov_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
void MacroAssembler::cmov_fp_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2,
|
||||
FloatRegister dst, FloatRegister src,
|
||||
bool cmp_single, bool cmov_single) {
|
||||
Label no_set;
|
||||
if (cmp_single) {
|
||||
// jump if cmp1 <= cmp2 or either is NaN
|
||||
// not jump (i.e. move src to dst) if cmp1 > cmp2
|
||||
float_ble(cmp1, cmp2, no_set, false, true);
|
||||
} else {
|
||||
double_ble(cmp1, cmp2, no_set, false, true);
|
||||
}
|
||||
if (cmov_single) {
|
||||
fmv_s(dst, src);
|
||||
} else {
|
||||
fmv_d(dst, src);
|
||||
}
|
||||
bind(no_set);
|
||||
}
|
||||
|
||||
// Float compare branch instructions
|
||||
|
||||
#define INSN(NAME, FLOATCMP, BRANCH) \
|
||||
@ -4933,7 +5187,6 @@ void MacroAssembler::set_narrow_klass(Register dst, Klass* k) {
|
||||
assert (UseCompressedClassPointers, "should only be used for compressed headers");
|
||||
assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder");
|
||||
int index = oop_recorder()->find_index(k);
|
||||
assert(!Universe::heap()->is_in(k), "should not be an oop");
|
||||
|
||||
narrowKlass nk = CompressedKlassPointers::encode(k);
|
||||
relocate(metadata_Relocation::spec(index), [&] {
|
||||
|
||||
@ -665,6 +665,24 @@ class MacroAssembler: public Assembler {
|
||||
void cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
|
||||
void cmov_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
|
||||
|
||||
void cmov_fp_eq(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single);
|
||||
void cmov_fp_ne(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single);
|
||||
void cmov_fp_le(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single);
|
||||
void cmov_fp_leu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single);
|
||||
void cmov_fp_ge(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single);
|
||||
void cmov_fp_geu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single);
|
||||
void cmov_fp_lt(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single);
|
||||
void cmov_fp_ltu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single);
|
||||
void cmov_fp_gt(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single);
|
||||
void cmov_fp_gtu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single);
|
||||
|
||||
void cmov_fp_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single);
|
||||
void cmov_fp_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single);
|
||||
void cmov_fp_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single);
|
||||
void cmov_fp_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single);
|
||||
void cmov_fp_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single);
|
||||
void cmov_fp_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single);
|
||||
|
||||
public:
|
||||
// We try to follow risc-v asm menomics.
|
||||
// But as we don't layout a reachable GOT,
|
||||
|
||||
@ -1924,8 +1924,6 @@ bool Matcher::match_rule_supported(int opcode) {
|
||||
case Op_SubHF:
|
||||
return UseZfh;
|
||||
|
||||
case Op_CMoveF:
|
||||
case Op_CMoveD:
|
||||
case Op_CMoveP:
|
||||
case Op_CMoveN:
|
||||
return false;
|
||||
@ -10466,6 +10464,286 @@ instruct cmovL_cmpP(iRegLNoSp dst, iRegL src, iRegP op1, iRegP op2, cmpOpU cop)
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
// --------- CMoveF ---------
|
||||
|
||||
instruct cmovF_cmpI(fRegF dst, fRegF src, iRegI op1, iRegI op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveF (Binary cop (CmpI op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpI\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovF_cmpU(fRegF dst, fRegF src, iRegI op1, iRegI op2, cmpOpU cop) %{
|
||||
match(Set dst (CMoveF (Binary cop (CmpU op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpU\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovF_cmpL(fRegF dst, fRegF src, iRegL op1, iRegL op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveF (Binary cop (CmpL op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpL\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovF_cmpUL(fRegF dst, fRegF src, iRegL op1, iRegL op2, cmpOpU cop) %{
|
||||
match(Set dst (CMoveF (Binary cop (CmpUL op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpUL\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovF_cmpF(fRegF dst, fRegF src, fRegF op1, fRegF op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveF (Binary cop (CmpF op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpF\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp_fp($cop$$cmpcode,
|
||||
as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
|
||||
true /* cmp_single */, true /* cmov_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovF_cmpD(fRegF dst, fRegF src, fRegD op1, fRegD op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveF (Binary cop (CmpD op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpD\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask,
|
||||
as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
|
||||
false /* cmp_single */, true /* cmov_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovF_cmpN(fRegF dst, fRegF src, iRegN op1, iRegN op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveF (Binary cop (CmpN op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpN\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovF_cmpP(fRegF dst, fRegF src, iRegP op1, iRegP op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveF (Binary cop (CmpP op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpP\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
// --------- CMoveD ---------
|
||||
|
||||
instruct cmovD_cmpI(fRegD dst, fRegD src, iRegI op1, iRegI op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveD (Binary cop (CmpI op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpI\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovD_cmpU(fRegD dst, fRegD src, iRegI op1, iRegI op2, cmpOpU cop) %{
|
||||
match(Set dst (CMoveD (Binary cop (CmpU op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpU\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovD_cmpL(fRegD dst, fRegD src, iRegL op1, iRegL op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveD (Binary cop (CmpL op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpL\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovD_cmpUL(fRegD dst, fRegD src, iRegL op1, iRegL op2, cmpOpU cop) %{
|
||||
match(Set dst (CMoveD (Binary cop (CmpUL op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpUL\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovD_cmpF(fRegD dst, fRegD src, fRegF op1, fRegF op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveD (Binary cop (CmpF op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpF\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp_fp($cop$$cmpcode,
|
||||
as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
|
||||
true /* cmp_single */, false /* cmov_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovD_cmpD(fRegD dst, fRegD src, fRegD op1, fRegD op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveD (Binary cop (CmpD op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpD\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask,
|
||||
as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
|
||||
false /* cmp_single */, false /* cmov_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovD_cmpN(fRegD dst, fRegD src, iRegN op1, iRegN op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveD (Binary cop (CmpN op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpN\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmovD_cmpP(fRegD dst, fRegD src, iRegP op1, iRegP op2, cmpOp cop) %{
|
||||
match(Set dst (CMoveD (Binary cop (CmpP op1 op2)) (Binary dst src)));
|
||||
ins_cost(ALU_COST + BRANCH_COST);
|
||||
|
||||
format %{
|
||||
"CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpP\n\t"
|
||||
%}
|
||||
|
||||
ins_encode %{
|
||||
__ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
|
||||
as_Register($op1$$reg), as_Register($op2$$reg),
|
||||
as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
|
||||
%}
|
||||
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
// ============================================================================
|
||||
// Procedure Call/Return Instructions
|
||||
|
||||
|
||||
@ -58,8 +58,6 @@
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/vmError.hpp"
|
||||
|
||||
PSYoungGen* ParallelScavengeHeap::_young_gen = nullptr;
|
||||
PSOldGen* ParallelScavengeHeap::_old_gen = nullptr;
|
||||
PSAdaptiveSizePolicy* ParallelScavengeHeap::_size_policy = nullptr;
|
||||
GCPolicyCounters* ParallelScavengeHeap::_gc_policy_counters = nullptr;
|
||||
size_t ParallelScavengeHeap::_desired_page_size = 0;
|
||||
@ -143,9 +141,9 @@ void ParallelScavengeHeap::initialize_serviceability() {
|
||||
"PS Survivor Space",
|
||||
false /* support_usage_threshold */);
|
||||
|
||||
_old_pool = new PSGenerationPool(_old_gen,
|
||||
"PS Old Gen",
|
||||
true /* support_usage_threshold */);
|
||||
_old_pool = new PSOldGenerationPool(_old_gen,
|
||||
"PS Old Gen",
|
||||
true /* support_usage_threshold */);
|
||||
|
||||
_young_manager = new GCMemoryManager("PS Scavenge");
|
||||
_old_manager = new GCMemoryManager("PS MarkSweep");
|
||||
|
||||
@ -69,8 +69,8 @@ class ReservedSpace;
|
||||
class ParallelScavengeHeap : public CollectedHeap {
|
||||
friend class VMStructs;
|
||||
private:
|
||||
static PSYoungGen* _young_gen;
|
||||
static PSOldGen* _old_gen;
|
||||
PSYoungGen* _young_gen;
|
||||
PSOldGen* _old_gen;
|
||||
|
||||
// Sizing policy for entire heap
|
||||
static PSAdaptiveSizePolicy* _size_policy;
|
||||
@ -160,8 +160,8 @@ public:
|
||||
GrowableArray<GCMemoryManager*> memory_managers() override;
|
||||
GrowableArray<MemoryPool*> memory_pools() override;
|
||||
|
||||
static PSYoungGen* young_gen() { return _young_gen; }
|
||||
static PSOldGen* old_gen() { return _old_gen; }
|
||||
PSYoungGen* young_gen() const { return _young_gen; }
|
||||
PSOldGen* old_gen() const { return _old_gen; }
|
||||
|
||||
PSAdaptiveSizePolicy* size_policy() { return _size_policy; }
|
||||
|
||||
|
||||
@ -24,14 +24,14 @@
|
||||
|
||||
#include "gc/parallel/psMemoryPool.hpp"
|
||||
|
||||
PSGenerationPool::PSGenerationPool(PSOldGen* old_gen,
|
||||
const char* name,
|
||||
bool support_usage_threshold) :
|
||||
PSOldGenerationPool::PSOldGenerationPool(PSOldGen* old_gen,
|
||||
const char* name,
|
||||
bool support_usage_threshold) :
|
||||
CollectedMemoryPool(name, old_gen->capacity_in_bytes(),
|
||||
old_gen->reserved().byte_size(), support_usage_threshold), _old_gen(old_gen) {
|
||||
}
|
||||
|
||||
MemoryUsage PSGenerationPool::get_memory_usage() {
|
||||
MemoryUsage PSOldGenerationPool::get_memory_usage() {
|
||||
size_t maxSize = (available_for_allocation() ? max_size() : 0);
|
||||
size_t used = used_in_bytes();
|
||||
size_t committed = _old_gen->capacity_in_bytes();
|
||||
|
||||
@ -31,12 +31,12 @@
|
||||
#include "services/memoryPool.hpp"
|
||||
#include "services/memoryUsage.hpp"
|
||||
|
||||
class PSGenerationPool : public CollectedMemoryPool {
|
||||
class PSOldGenerationPool : public CollectedMemoryPool {
|
||||
private:
|
||||
PSOldGen* _old_gen;
|
||||
|
||||
public:
|
||||
PSGenerationPool(PSOldGen* pool, const char* name, bool support_usage_threshold);
|
||||
PSOldGenerationPool(PSOldGen* pool, const char* name, bool support_usage_threshold);
|
||||
|
||||
MemoryUsage get_memory_usage();
|
||||
size_t used_in_bytes() { return _old_gen->used_in_bytes(); }
|
||||
|
||||
@ -115,7 +115,7 @@ class PSScavenge: AllStatic {
|
||||
}
|
||||
|
||||
static bool is_obj_in_to_space(oop o) {
|
||||
return ParallelScavengeHeap::young_gen()->to_space()->contains(o);
|
||||
return ParallelScavengeHeap::heap()->young_gen()->to_space()->contains(o);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -64,8 +64,8 @@
|
||||
nonstatic_field(PSOldGen, _max_gen_size, const size_t) \
|
||||
\
|
||||
\
|
||||
static_field(ParallelScavengeHeap, _young_gen, PSYoungGen*) \
|
||||
static_field(ParallelScavengeHeap, _old_gen, PSOldGen*) \
|
||||
nonstatic_field(ParallelScavengeHeap, _young_gen, PSYoungGen*) \
|
||||
nonstatic_field(ParallelScavengeHeap, _old_gen, PSOldGen*) \
|
||||
\
|
||||
|
||||
#define VM_TYPES_PARALLELGC(declare_type, \
|
||||
|
||||
@ -630,6 +630,14 @@ bool SerialHeap::requires_barriers(stackChunkOop obj) const {
|
||||
|
||||
// Returns "TRUE" iff "p" points into the committed areas of the heap.
|
||||
bool SerialHeap::is_in(const void* p) const {
|
||||
// precondition
|
||||
verify_not_in_native_if_java_thread();
|
||||
|
||||
if (!is_in_reserved(p)) {
|
||||
// If it's not even in reserved.
|
||||
return false;
|
||||
}
|
||||
|
||||
return _young_gen->is_in(p) || _old_gen->is_in(p);
|
||||
}
|
||||
|
||||
@ -797,3 +805,12 @@ void SerialHeap::gc_epilogue(bool full) {
|
||||
|
||||
MetaspaceCounters::update_performance_counters();
|
||||
};
|
||||
|
||||
#ifdef ASSERT
|
||||
void SerialHeap::verify_not_in_native_if_java_thread() {
|
||||
if (Thread::current()->is_Java_thread()) {
|
||||
JavaThread* thread = JavaThread::current();
|
||||
assert(thread->thread_state() != _thread_in_native, "precondition");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -111,6 +111,8 @@ private:
|
||||
void print_tracing_info() const override;
|
||||
void stop() override {};
|
||||
|
||||
static void verify_not_in_native_if_java_thread() NOT_DEBUG_RETURN;
|
||||
|
||||
public:
|
||||
// Returns JNI_OK on success
|
||||
jint initialize() override;
|
||||
|
||||
@ -24,11 +24,11 @@
|
||||
*/
|
||||
|
||||
#include "jfr/recorder/service/jfrEventThrottler.hpp"
|
||||
#include "jfr/utilities/jfrSpinlockHelper.hpp"
|
||||
#include "jfrfiles/jfrEventIds.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/spinCriticalSection.hpp"
|
||||
|
||||
constexpr static const JfrSamplerParams _disabled_params = {
|
||||
0, // sample points per window
|
||||
@ -128,7 +128,7 @@ JfrEventThrottler* JfrEventThrottler::create_throttler(JfrEventId id) {
|
||||
* - period_ms time period expressed in milliseconds
|
||||
*/
|
||||
void JfrEventThrottler::configure(int64_t sample_size, int64_t period_ms) {
|
||||
JfrSpinlockHelper mutex(&_lock);
|
||||
SpinCriticalSection scs(&_lock);
|
||||
_sample_size = sample_size;
|
||||
_period_ms = period_ms;
|
||||
_update = true;
|
||||
|
||||
@ -25,13 +25,13 @@
|
||||
|
||||
#include "jfr/support/jfrAdaptiveSampler.hpp"
|
||||
#include "jfr/utilities/jfrRandom.inline.hpp"
|
||||
#include "jfr/utilities/jfrSpinlockHelper.hpp"
|
||||
#include "jfr/utilities/jfrTime.hpp"
|
||||
#include "jfr/utilities/jfrTimeConverter.hpp"
|
||||
#include "jfr/utilities/jfrTryLock.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/atomicAccess.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/spinCriticalSection.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@ -342,7 +342,7 @@ JfrGTestFixedRateSampler::JfrGTestFixedRateSampler(size_t sample_points_per_wind
|
||||
|
||||
bool JfrGTestFixedRateSampler::initialize() {
|
||||
const bool result = JfrAdaptiveSampler::initialize();
|
||||
JfrSpinlockHelper mutex(&_lock);
|
||||
SpinCriticalSection scs(&_lock);
|
||||
reconfigure();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
#include "jfr/recorder/storage/jfrStorage.hpp"
|
||||
#include "jfr/support/jfrThreadId.inline.hpp"
|
||||
#include "jfr/support/jfrThreadLocal.hpp"
|
||||
#include "jfr/utilities/jfrSpinlockHelper.hpp"
|
||||
#include "jfr/writers/jfrJavaEventWriter.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_JFR_UTILITIES_JFRSPINLOCKHELPER_HPP
|
||||
#define SHARE_JFR_UTILITIES_JFRSPINLOCKHELPER_HPP
|
||||
|
||||
#include "runtime/javaThread.hpp"
|
||||
|
||||
class JfrSpinlockHelper {
|
||||
private:
|
||||
volatile int* const _lock;
|
||||
|
||||
public:
|
||||
JfrSpinlockHelper(volatile int* lock) : _lock(lock) {
|
||||
Thread::SpinAcquire(_lock);
|
||||
}
|
||||
|
||||
~JfrSpinlockHelper() {
|
||||
Thread::SpinRelease(_lock);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_JFR_UTILITIES_JFRSPINLOCKHELPER_HPP
|
||||
@ -26,97 +26,114 @@
|
||||
#include "opto/opcodes.hpp"
|
||||
#include "opto/phaseX.hpp"
|
||||
#include "opto/type.hpp"
|
||||
#include "utilities/count_leading_zeros.hpp"
|
||||
#include "utilities/count_trailing_zeros.hpp"
|
||||
#include "utilities/population_count.hpp"
|
||||
|
||||
static int count_leading_zeros_int(jint i) {
|
||||
return i == 0 ? BitsPerInt : count_leading_zeros(i);
|
||||
}
|
||||
|
||||
static int count_leading_zeros_long(jlong l) {
|
||||
return l == 0 ? BitsPerLong : count_leading_zeros(l);
|
||||
}
|
||||
|
||||
static int count_trailing_zeros_int(jint i) {
|
||||
return i == 0 ? BitsPerInt : count_trailing_zeros(i);
|
||||
}
|
||||
|
||||
static int count_trailing_zeros_long(jlong l) {
|
||||
return l == 0 ? BitsPerLong : count_trailing_zeros(l);
|
||||
}
|
||||
|
||||
//------------------------------Value------------------------------------------
|
||||
const Type* CountLeadingZerosINode::Value(PhaseGVN* phase) const {
|
||||
const Type* t = phase->type(in(1));
|
||||
if (t == Type::TOP) return Type::TOP;
|
||||
const TypeInt* ti = t->isa_int();
|
||||
if (ti && ti->is_con()) {
|
||||
jint i = ti->get_con();
|
||||
// HD, Figure 5-6
|
||||
if (i == 0)
|
||||
return TypeInt::make(BitsPerInt);
|
||||
int n = 1;
|
||||
unsigned int x = i;
|
||||
if (x >> 16 == 0) { n += 16; x <<= 16; }
|
||||
if (x >> 24 == 0) { n += 8; x <<= 8; }
|
||||
if (x >> 28 == 0) { n += 4; x <<= 4; }
|
||||
if (x >> 30 == 0) { n += 2; x <<= 2; }
|
||||
n -= x >> 31;
|
||||
return TypeInt::make(n);
|
||||
if (t == Type::TOP) {
|
||||
return Type::TOP;
|
||||
}
|
||||
return TypeInt::INT;
|
||||
|
||||
// To minimize `count_leading_zeros(x)`, we should make the highest 1 bit in x
|
||||
// as far to the left as possible. A bit in x can be 1 iff this bit is not
|
||||
// forced to be 0, i.e. the corresponding bit in `x._bits._zeros` is 0. Thus:
|
||||
// min(clz(x)) = number of bits to the left of the highest 0 bit in x._bits._zeros
|
||||
// = count_leading_ones(x._bits._zeros) = clz(~x._bits._zeros)
|
||||
//
|
||||
// To maximize `count_leading_zeros(x)`, we should make the leading zeros as
|
||||
// many as possible. A bit in x can be 0 iff this bit is not forced to be 1,
|
||||
// i.e. the corresponding bit in `x._bits._ones` is 0. Thus:
|
||||
// max(clz(x)) = clz(x._bits._ones)
|
||||
//
|
||||
// Therefore, the range of `count_leading_zeros(x)` is:
|
||||
// [clz(~x._bits._zeros), clz(x._bits._ones)]
|
||||
//
|
||||
// A more detailed proof using Z3 can be found at:
|
||||
// https://github.com/openjdk/jdk/pull/25928#discussion_r2256750507
|
||||
const TypeInt* ti = t->is_int();
|
||||
return TypeInt::make(count_leading_zeros_int(~ti->_bits._zeros),
|
||||
count_leading_zeros_int(ti->_bits._ones),
|
||||
ti->_widen);
|
||||
}
|
||||
|
||||
//------------------------------Value------------------------------------------
|
||||
const Type* CountLeadingZerosLNode::Value(PhaseGVN* phase) const {
|
||||
const Type* t = phase->type(in(1));
|
||||
if (t == Type::TOP) return Type::TOP;
|
||||
const TypeLong* tl = t->isa_long();
|
||||
if (tl && tl->is_con()) {
|
||||
jlong l = tl->get_con();
|
||||
// HD, Figure 5-6
|
||||
if (l == 0)
|
||||
return TypeInt::make(BitsPerLong);
|
||||
int n = 1;
|
||||
unsigned int x = (((julong) l) >> 32);
|
||||
if (x == 0) { n += 32; x = (int) l; }
|
||||
if (x >> 16 == 0) { n += 16; x <<= 16; }
|
||||
if (x >> 24 == 0) { n += 8; x <<= 8; }
|
||||
if (x >> 28 == 0) { n += 4; x <<= 4; }
|
||||
if (x >> 30 == 0) { n += 2; x <<= 2; }
|
||||
n -= x >> 31;
|
||||
return TypeInt::make(n);
|
||||
if (t == Type::TOP) {
|
||||
return Type::TOP;
|
||||
}
|
||||
return TypeInt::INT;
|
||||
|
||||
// The proof of correctness is same as the above comments
|
||||
// in `CountLeadingZerosINode::Value`.
|
||||
const TypeLong* tl = t->is_long();
|
||||
return TypeInt::make(count_leading_zeros_long(~tl->_bits._zeros),
|
||||
count_leading_zeros_long(tl->_bits._ones),
|
||||
tl->_widen);
|
||||
}
|
||||
|
||||
//------------------------------Value------------------------------------------
|
||||
const Type* CountTrailingZerosINode::Value(PhaseGVN* phase) const {
|
||||
const Type* t = phase->type(in(1));
|
||||
if (t == Type::TOP) return Type::TOP;
|
||||
const TypeInt* ti = t->isa_int();
|
||||
if (ti && ti->is_con()) {
|
||||
jint i = ti->get_con();
|
||||
// HD, Figure 5-14
|
||||
int y;
|
||||
if (i == 0)
|
||||
return TypeInt::make(BitsPerInt);
|
||||
int n = 31;
|
||||
y = i << 16; if (y != 0) { n = n - 16; i = y; }
|
||||
y = i << 8; if (y != 0) { n = n - 8; i = y; }
|
||||
y = i << 4; if (y != 0) { n = n - 4; i = y; }
|
||||
y = i << 2; if (y != 0) { n = n - 2; i = y; }
|
||||
y = i << 1; if (y != 0) { n = n - 1; }
|
||||
return TypeInt::make(n);
|
||||
if (t == Type::TOP) {
|
||||
return Type::TOP;
|
||||
}
|
||||
return TypeInt::INT;
|
||||
|
||||
// To minimize `count_trailing_zeros(x)`, we should make the lowest 1 bit in x
|
||||
// as far to the right as possible. A bit in x can be 1 iff this bit is not
|
||||
// forced to be 0, i.e. the corresponding bit in `x._bits._zeros` is 0. Thus:
|
||||
// min(ctz(x)) = number of bits to the right of the lowest 0 bit in x._bits._zeros
|
||||
// = count_trailing_ones(x._bits._zeros) = ctz(~x._bits._zeros)
|
||||
//
|
||||
// To maximize `count_trailing_zeros(x)`, we should make the trailing zeros as
|
||||
// many as possible. A bit in x can be 0 iff this bit is not forced to be 1,
|
||||
// i.e. the corresponding bit in `x._bits._ones` is 0. Thus:
|
||||
// max(ctz(x)) = ctz(x._bits._ones)
|
||||
//
|
||||
// Therefore, the range of `count_trailing_zeros(x)` is:
|
||||
// [ctz(~x._bits._zeros), ctz(x._bits._ones)]
|
||||
//
|
||||
// A more detailed proof using Z3 can be found at:
|
||||
// https://github.com/openjdk/jdk/pull/25928#discussion_r2256750507
|
||||
const TypeInt* ti = t->is_int();
|
||||
return TypeInt::make(count_trailing_zeros_int(~ti->_bits._zeros),
|
||||
count_trailing_zeros_int(ti->_bits._ones),
|
||||
ti->_widen);
|
||||
}
|
||||
|
||||
//------------------------------Value------------------------------------------
|
||||
const Type* CountTrailingZerosLNode::Value(PhaseGVN* phase) const {
|
||||
const Type* t = phase->type(in(1));
|
||||
if (t == Type::TOP) return Type::TOP;
|
||||
const TypeLong* tl = t->isa_long();
|
||||
if (tl && tl->is_con()) {
|
||||
jlong l = tl->get_con();
|
||||
// HD, Figure 5-14
|
||||
int x, y;
|
||||
if (l == 0)
|
||||
return TypeInt::make(BitsPerLong);
|
||||
int n = 63;
|
||||
y = (int) l; if (y != 0) { n = n - 32; x = y; } else x = (((julong) l) >> 32);
|
||||
y = x << 16; if (y != 0) { n = n - 16; x = y; }
|
||||
y = x << 8; if (y != 0) { n = n - 8; x = y; }
|
||||
y = x << 4; if (y != 0) { n = n - 4; x = y; }
|
||||
y = x << 2; if (y != 0) { n = n - 2; x = y; }
|
||||
y = x << 1; if (y != 0) { n = n - 1; }
|
||||
return TypeInt::make(n);
|
||||
if (t == Type::TOP) {
|
||||
return Type::TOP;
|
||||
}
|
||||
return TypeInt::INT;
|
||||
|
||||
// The proof of correctness is same as the above comments
|
||||
// in `CountTrailingZerosINode::Value`.
|
||||
const TypeLong* tl = t->is_long();
|
||||
return TypeInt::make(count_trailing_zeros_long(~tl->_bits._zeros),
|
||||
count_trailing_zeros_long(tl->_bits._ones),
|
||||
tl->_widen);
|
||||
}
|
||||
|
||||
// We use the KnownBits information from the integer types to derive how many one bits
|
||||
// we have at least and at most.
|
||||
// From the definition of KnownBits, we know:
|
||||
|
||||
@ -59,6 +59,7 @@
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/preserveException.hpp"
|
||||
#include "utilities/spinCriticalSection.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/support/jfrFlush.hpp"
|
||||
#endif
|
||||
@ -1863,9 +1864,10 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
|
||||
// returns because of a timeout of interrupt. Contention is exceptionally rare
|
||||
// so we use a simple spin-lock instead of a heavier-weight blocking lock.
|
||||
|
||||
Thread::SpinAcquire(&_wait_set_lock);
|
||||
add_waiter(&node);
|
||||
Thread::SpinRelease(&_wait_set_lock);
|
||||
{
|
||||
SpinCriticalSection scs(&_wait_set_lock);
|
||||
add_waiter(&node);
|
||||
}
|
||||
|
||||
intx save = _recursions; // record the old recursion count
|
||||
_waiters++; // increment the number of waiters
|
||||
@ -1922,12 +1924,11 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
|
||||
// That is, we fail toward safety.
|
||||
|
||||
if (node.TState == ObjectWaiter::TS_WAIT) {
|
||||
Thread::SpinAcquire(&_wait_set_lock);
|
||||
SpinCriticalSection scs(&_wait_set_lock);
|
||||
if (node.TState == ObjectWaiter::TS_WAIT) {
|
||||
dequeue_specific_waiter(&node); // unlink from wait_set
|
||||
node.TState = ObjectWaiter::TS_RUN;
|
||||
}
|
||||
Thread::SpinRelease(&_wait_set_lock);
|
||||
}
|
||||
|
||||
// The thread is now either on off-list (TS_RUN),
|
||||
@ -2036,7 +2037,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
|
||||
|
||||
bool ObjectMonitor::notify_internal(JavaThread* current) {
|
||||
bool did_notify = false;
|
||||
Thread::SpinAcquire(&_wait_set_lock);
|
||||
SpinCriticalSection scs(&_wait_set_lock);
|
||||
ObjectWaiter* iterator = dequeue_waiter();
|
||||
if (iterator != nullptr) {
|
||||
guarantee(iterator->TState == ObjectWaiter::TS_WAIT, "invariant");
|
||||
@ -2095,7 +2096,6 @@ bool ObjectMonitor::notify_internal(JavaThread* current) {
|
||||
}
|
||||
}
|
||||
}
|
||||
Thread::SpinRelease(&_wait_set_lock);
|
||||
return did_notify;
|
||||
}
|
||||
|
||||
@ -2198,9 +2198,10 @@ void ObjectMonitor::vthread_wait(JavaThread* current, jlong millis, bool interru
|
||||
// returns because of a timeout or interrupt. Contention is exceptionally rare
|
||||
// so we use a simple spin-lock instead of a heavier-weight blocking lock.
|
||||
|
||||
Thread::SpinAcquire(&_wait_set_lock);
|
||||
add_waiter(node);
|
||||
Thread::SpinRelease(&_wait_set_lock);
|
||||
{
|
||||
SpinCriticalSection scs(&_wait_set_lock);
|
||||
add_waiter(node);
|
||||
}
|
||||
|
||||
node->_recursions = _recursions; // record the old recursion count
|
||||
_recursions = 0; // set the recursion level to be 0
|
||||
@ -2221,12 +2222,11 @@ bool ObjectMonitor::vthread_wait_reenter(JavaThread* current, ObjectWaiter* node
|
||||
// need to check if we were interrupted or the wait timed-out, and
|
||||
// in that case remove ourselves from the _wait_set queue.
|
||||
if (node->TState == ObjectWaiter::TS_WAIT) {
|
||||
Thread::SpinAcquire(&_wait_set_lock);
|
||||
SpinCriticalSection scs(&_wait_set_lock);
|
||||
if (node->TState == ObjectWaiter::TS_WAIT) {
|
||||
dequeue_specific_waiter(node); // unlink from wait_set
|
||||
node->TState = ObjectWaiter::TS_RUN;
|
||||
}
|
||||
Thread::SpinRelease(&_wait_set_lock);
|
||||
}
|
||||
|
||||
// If this was an interrupted case, set the _interrupted boolean so that
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "nmt/memTracker.hpp"
|
||||
#include "runtime/javaThread.hpp"
|
||||
#include "utilities/spinCriticalSection.hpp"
|
||||
|
||||
// Lifecycle management for TSM ParkEvents.
|
||||
// ParkEvents are type-stable (TSM).
|
||||
@ -60,14 +61,13 @@ ParkEvent * ParkEvent::Allocate (Thread * t) {
|
||||
// Using a spin lock since we are part of the mutex impl.
|
||||
// 8028280: using concurrent free list without memory management can leak
|
||||
// pretty badly it turns out.
|
||||
Thread::SpinAcquire(&ListLock);
|
||||
{
|
||||
SpinCriticalSection scs(&ListLock);
|
||||
ev = FreeList;
|
||||
if (ev != nullptr) {
|
||||
FreeList = ev->FreeNext;
|
||||
}
|
||||
}
|
||||
Thread::SpinRelease(&ListLock);
|
||||
|
||||
if (ev != nullptr) {
|
||||
guarantee (ev->AssociatedWith == nullptr, "invariant") ;
|
||||
@ -88,12 +88,11 @@ void ParkEvent::Release (ParkEvent * ev) {
|
||||
ev->AssociatedWith = nullptr ;
|
||||
// Note that if we didn't have the TSM/immortal constraint, then
|
||||
// when reattaching we could trim the list.
|
||||
Thread::SpinAcquire(&ListLock);
|
||||
{
|
||||
SpinCriticalSection scs(&ListLock);
|
||||
ev->FreeNext = FreeList;
|
||||
FreeList = ev;
|
||||
}
|
||||
Thread::SpinRelease(&ListLock);
|
||||
}
|
||||
|
||||
// Override operator new and delete so we can ensure that the
|
||||
|
||||
@ -30,7 +30,9 @@
|
||||
|
||||
#ifdef ASSERT
|
||||
|
||||
NoSafepointVerifier::NoSafepointVerifier(bool active) : _thread(Thread::current()), _active(active) {
|
||||
NoSafepointVerifier::NoSafepointVerifier(bool active)
|
||||
: _thread(active ? Thread::current() : nullptr),
|
||||
_active(active) {
|
||||
if (!_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -566,49 +566,3 @@ bool Thread::set_as_starting_thread(JavaThread* jt) {
|
||||
DEBUG_ONLY(_starting_thread = jt;)
|
||||
return os::create_main_thread(jt);
|
||||
}
|
||||
|
||||
// Ad-hoc mutual exclusion primitive: spin lock
|
||||
//
|
||||
// We employ a spin lock _only for low-contention, fixed-length
|
||||
// short-duration critical sections where we're concerned
|
||||
// about native mutex_t or HotSpot Mutex:: latency.
|
||||
|
||||
void Thread::SpinAcquire(volatile int * adr) {
|
||||
if (AtomicAccess::cmpxchg(adr, 0, 1) == 0) {
|
||||
return; // normal fast-path return
|
||||
}
|
||||
|
||||
// Slow-path : We've encountered contention -- Spin/Yield/Block strategy.
|
||||
int ctr = 0;
|
||||
int Yields = 0;
|
||||
for (;;) {
|
||||
while (*adr != 0) {
|
||||
++ctr;
|
||||
if ((ctr & 0xFFF) == 0 || !os::is_MP()) {
|
||||
if (Yields > 5) {
|
||||
os::naked_short_sleep(1);
|
||||
} else {
|
||||
os::naked_yield();
|
||||
++Yields;
|
||||
}
|
||||
} else {
|
||||
SpinPause();
|
||||
}
|
||||
}
|
||||
if (AtomicAccess::cmpxchg(adr, 0, 1) == 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::SpinRelease(volatile int * adr) {
|
||||
assert(*adr != 0, "invariant");
|
||||
// Roach-motel semantics.
|
||||
// It's safe if subsequent LDs and STs float "up" into the critical section,
|
||||
// but prior LDs and STs within the critical section can't be allowed
|
||||
// to reorder or float past the ST that releases the lock.
|
||||
// Loads and stores in the critical section - which appear in program
|
||||
// order before the store that releases the lock - must also appear
|
||||
// before the store that releases the lock in memory visibility order.
|
||||
// So we need a #loadstore|#storestore "release" memory barrier before
|
||||
// the ST of 0 into the lock-word which releases the lock.
|
||||
AtomicAccess::release_store(adr, 0);
|
||||
}
|
||||
|
||||
@ -602,11 +602,6 @@ protected:
|
||||
jint _hashStateY;
|
||||
jint _hashStateZ;
|
||||
|
||||
// Low-level leaf-lock primitives used to implement synchronization.
|
||||
// Not for general synchronization use.
|
||||
static void SpinAcquire(volatile int * Lock);
|
||||
static void SpinRelease(volatile int * Lock);
|
||||
|
||||
#if defined(__APPLE__) && defined(AARCH64)
|
||||
private:
|
||||
DEBUG_ONLY(bool _wx_init);
|
||||
|
||||
69
src/hotspot/share/utilities/spinCriticalSection.cpp
Normal file
69
src/hotspot/share/utilities/spinCriticalSection.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "runtime/atomicAccess.hpp"
|
||||
#include "utilities/spinCriticalSection.hpp"
|
||||
|
||||
void SpinCriticalSection::spin_acquire(volatile int* adr) {
|
||||
if (AtomicAccess::cmpxchg(adr, 0, 1) == 0) {
|
||||
return; // normal fast-path return
|
||||
}
|
||||
|
||||
// Slow-path : We've encountered contention -- Spin/Yield/Block strategy.
|
||||
int ctr = 0;
|
||||
int Yields = 0;
|
||||
for (;;) {
|
||||
while (*adr != 0) {
|
||||
++ctr;
|
||||
if ((ctr & 0xFFF) == 0 || !os::is_MP()) {
|
||||
if (Yields > 5) {
|
||||
os::naked_short_sleep(1);
|
||||
}
|
||||
else {
|
||||
os::naked_yield();
|
||||
++Yields;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SpinPause();
|
||||
}
|
||||
}
|
||||
if (AtomicAccess::cmpxchg(adr, 0, 1) == 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
void SpinCriticalSection::spin_release(volatile int* adr) {
|
||||
assert(*adr != 0, "invariant");
|
||||
// Roach-motel semantics.
|
||||
// It's safe if subsequent LDs and STs float "up" into the critical section,
|
||||
// but prior LDs and STs within the critical section can't be allowed
|
||||
// to reorder or float past the ST that releases the lock.
|
||||
// Loads and stores in the critical section - which appear in program
|
||||
// order before the store that releases the lock - must also appear
|
||||
// before the store that releases the lock in memory visibility order.
|
||||
// So we need a #loadstore|#storestore "release" memory barrier before
|
||||
// the ST of 0 into the lock-word which releases the lock.
|
||||
AtomicAccess::release_store(adr, 0);
|
||||
}
|
||||
|
||||
63
src/hotspot/share/utilities/spinCriticalSection.hpp
Normal file
63
src/hotspot/share/utilities/spinCriticalSection.hpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_UTILITIES_SPINCRITICALSECTION_HPP
|
||||
#define SHARE_UTILITIES_SPINCRITICALSECTION_HPP
|
||||
|
||||
#include "runtime/javaThread.hpp"
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
// Ad-hoc mutual exclusion primitive: spin critical section,
|
||||
// which employs a spin lock.
|
||||
//
|
||||
// We use this critical section only for low-contention code, and
|
||||
// when it is know that the duration is short. To be used where
|
||||
// we're concerned about native mutex_t or HotSpot Mutex:: latency.
|
||||
// This class uses low-level leaf-lock primitives to implement
|
||||
// synchronization and is not for general synchronization use.
|
||||
// Should not be used in signal-handling contexts.
|
||||
class SpinCriticalSection {
|
||||
private:
|
||||
// We use int type as 32-bit atomic operation is the most performant
|
||||
// compared to smaller/larger types.
|
||||
volatile int* const _lock;
|
||||
DEBUG_ONLY(NoSafepointVerifier _nsv;)
|
||||
|
||||
static void spin_acquire(volatile int* Lock);
|
||||
static void spin_release(volatile int* Lock);
|
||||
public:
|
||||
NONCOPYABLE(SpinCriticalSection);
|
||||
SpinCriticalSection(volatile int* lock)
|
||||
: _lock(lock)
|
||||
DEBUG_ONLY(COMMA _nsv(Thread::current_or_null() != nullptr)) {
|
||||
spin_acquire(_lock);
|
||||
}
|
||||
~SpinCriticalSection() {
|
||||
spin_release(_lock);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_UTILITIES_SPINCRITICALSECTION_HPP
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. 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
|
||||
@ -44,6 +44,7 @@ import java.util.Objects;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import sun.net.util.IPAddressUtil;
|
||||
import sun.net.www.http.HttpClient;
|
||||
import sun.net.www.protocol.http.AuthCacheImpl;
|
||||
import sun.net.www.protocol.http.HttpURLConnection;
|
||||
@ -471,7 +472,13 @@ final class HttpsClient extends HttpClient
|
||||
SSLParameters parameters = s.getSSLParameters();
|
||||
parameters.setEndpointIdentificationAlgorithm("HTTPS");
|
||||
// host has been set previously for SSLSocketImpl
|
||||
if (!(s instanceof SSLSocketImpl)) {
|
||||
if (!(s instanceof SSLSocketImpl) &&
|
||||
!IPAddressUtil.isIPv4LiteralAddress(host) &&
|
||||
!(host.charAt(0) == '[' && host.charAt(host.length() - 1) == ']' &&
|
||||
IPAddressUtil.isIPv6LiteralAddress(host.substring(1, host.length() - 1))
|
||||
)) {
|
||||
// Fully qualified DNS hostname of the server, as per section 3, RFC 6066
|
||||
// Literal IPv4 and IPv6 addresses are not permitted in "HostName".
|
||||
parameters.setServerNames(List.of(new SNIHostName(host)));
|
||||
}
|
||||
s.setSSLParameters(parameters);
|
||||
|
||||
@ -5634,12 +5634,16 @@ public class Attr extends JCTree.Visitor {
|
||||
chk.validateRepeatable(c, repeatable, cbPos);
|
||||
}
|
||||
} else {
|
||||
// Check that all extended classes and interfaces
|
||||
// are compatible (i.e. no two define methods with same arguments
|
||||
// yet different return types). (JLS 8.4.8.3)
|
||||
chk.checkCompatibleSupertypes(tree.pos(), c.type);
|
||||
chk.checkDefaultMethodClashes(tree.pos(), c.type);
|
||||
chk.checkPotentiallyAmbiguousOverloads(tree, c.type);
|
||||
try {
|
||||
// Check that all extended classes and interfaces
|
||||
// are compatible (i.e. no two define methods with same arguments
|
||||
// yet different return types). (JLS 8.4.8.3)
|
||||
chk.checkCompatibleSupertypes(tree.pos(), c.type);
|
||||
chk.checkDefaultMethodClashes(tree.pos(), c.type);
|
||||
chk.checkPotentiallyAmbiguousOverloads(tree, c.type);
|
||||
} catch (CompletionFailure cf) {
|
||||
chk.completionError(tree.pos(), cf);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that class does not import the same parameterized interface
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. 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
|
||||
@ -60,11 +60,11 @@ public class ParallelScavengeHeap extends CollectedHeap {
|
||||
|
||||
// Accessors
|
||||
public PSYoungGen youngGen() {
|
||||
return VMObjectFactory.newObject(PSYoungGen.class, youngGenField.getValue());
|
||||
return VMObjectFactory.newObject(PSYoungGen.class, youngGenField.getValue(addr));
|
||||
}
|
||||
|
||||
public PSOldGen oldGen() {
|
||||
return VMObjectFactory.newObject(PSOldGen.class, oldGenField.getValue());
|
||||
return VMObjectFactory.newObject(PSOldGen.class, oldGenField.getValue(addr));
|
||||
}
|
||||
|
||||
public long capacity() {
|
||||
|
||||
@ -34,13 +34,12 @@
|
||||
|
||||
#include "jfr/utilities/jfrAllocation.hpp"
|
||||
#include "jfr/utilities/jfrRandom.inline.hpp"
|
||||
#include "jfr/utilities/jfrSpinlockHelper.hpp"
|
||||
#include "jfr/utilities/jfrTime.hpp"
|
||||
#include "jfr/utilities/jfrTimeConverter.hpp"
|
||||
#include "jfr/utilities/jfrTryLock.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/atomicAccess.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/spinCriticalSection.hpp"
|
||||
#include "unittest.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
570
test/hotspot/jtreg/compiler/c2/gvn/TestCountBitsRange.java
Normal file
570
test/hotspot/jtreg/compiler/c2/gvn/TestCountBitsRange.java
Normal file
@ -0,0 +1,570 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Alibaba Group Holding Limited. 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.
|
||||
*/
|
||||
|
||||
package compiler.c2.gvn;
|
||||
|
||||
import compiler.lib.generators.Generator;
|
||||
import compiler.lib.generators.Generators;
|
||||
import compiler.lib.generators.RestrictableGenerator;
|
||||
import compiler.lib.ir_framework.*;
|
||||
import java.util.function.Function;
|
||||
import jdk.test.lib.Asserts;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8360192
|
||||
* @summary Tests that count bits nodes are handled correctly.
|
||||
* @library /test/lib /
|
||||
* @run driver compiler.c2.gvn.TestCountBitsRange
|
||||
*/
|
||||
public class TestCountBitsRange {
|
||||
private static final Generator<Integer> INTS = Generators.G.ints();
|
||||
private static final Generator<Long> LONGS = Generators.G.longs();
|
||||
|
||||
private static final RestrictableGenerator<Integer> INTS_32 = Generators.G.ints().restricted(0, 32);
|
||||
private static final RestrictableGenerator<Integer> INTS_64 = Generators.G.ints().restricted(0, 64);
|
||||
|
||||
private static final int LIMITS_32_0 = INTS_32.next();
|
||||
private static final int LIMITS_32_1 = INTS_32.next();
|
||||
private static final int LIMITS_32_2 = INTS_32.next();
|
||||
private static final int LIMITS_32_3 = INTS_32.next();
|
||||
private static final int LIMITS_32_4 = INTS_32.next();
|
||||
private static final int LIMITS_32_5 = INTS_32.next();
|
||||
private static final int LIMITS_32_6 = INTS_32.next();
|
||||
private static final int LIMITS_32_7 = INTS_32.next();
|
||||
|
||||
private static final int LIMITS_64_0 = INTS_64.next();
|
||||
private static final int LIMITS_64_1 = INTS_64.next();
|
||||
private static final int LIMITS_64_2 = INTS_64.next();
|
||||
private static final int LIMITS_64_3 = INTS_64.next();
|
||||
private static final int LIMITS_64_4 = INTS_64.next();
|
||||
private static final int LIMITS_64_5 = INTS_64.next();
|
||||
private static final int LIMITS_64_6 = INTS_64.next();
|
||||
private static final int LIMITS_64_7 = INTS_64.next();
|
||||
|
||||
private static final IntRange RANGE_INT = IntRange.generate(INTS);
|
||||
private static final LongRange RANGE_LONG = LongRange.generate(LONGS);
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestFramework.run();
|
||||
}
|
||||
|
||||
@Run(test = {
|
||||
"clzConstInts", "clzCompareInt", "clzDiv8Int", "clzRandLimitInt",
|
||||
"clzConstLongs", "clzCompareLong", "clzDiv8Long", "clzRandLimitLong",
|
||||
"ctzConstInts", "ctzCompareInt", "ctzDiv8Int", "ctzRandLimitInt",
|
||||
"ctzConstLongs", "ctzCompareLong", "ctzDiv8Long", "ctzRandLimitLong",
|
||||
})
|
||||
public void runTest() {
|
||||
int randInt = INTS.next();
|
||||
long randLong = LONGS.next();
|
||||
assertResult(randInt, randLong);
|
||||
}
|
||||
|
||||
@DontCompile
|
||||
public void assertResult(int randInt, long randLong) {
|
||||
checkConstResults(clzConstInts(), x -> Integer.numberOfLeadingZeros(x.intValue()));
|
||||
Asserts.assertEQ(Integer.numberOfLeadingZeros(randInt) < 0
|
||||
|| Integer.numberOfLeadingZeros(randInt) > 32,
|
||||
clzCompareInt(randInt));
|
||||
Asserts.assertEQ(Integer.numberOfLeadingZeros(randInt) / 8,
|
||||
clzDiv8Int(randInt));
|
||||
Asserts.assertEQ(clzRandLimitInterpretedInt(randInt), clzRandLimitInt(randInt));
|
||||
|
||||
checkConstResults(clzConstLongs(), x -> Long.numberOfLeadingZeros(x.longValue()));
|
||||
Asserts.assertEQ(Long.numberOfLeadingZeros(randLong) < 0
|
||||
|| Long.numberOfLeadingZeros(randLong) > 64,
|
||||
clzCompareLong(randLong));
|
||||
Asserts.assertEQ(Long.numberOfLeadingZeros(randLong) / 8,
|
||||
clzDiv8Long(randLong));
|
||||
Asserts.assertEQ(clzRandLimitInterpretedLong(randLong), clzRandLimitLong(randLong));
|
||||
|
||||
checkConstResults(ctzConstInts(), x -> Integer.numberOfTrailingZeros(x.intValue()));
|
||||
Asserts.assertEQ(Integer.numberOfTrailingZeros(randInt) < 0
|
||||
|| Integer.numberOfTrailingZeros(randInt) > 32,
|
||||
ctzCompareInt(randInt));
|
||||
Asserts.assertEQ(Integer.numberOfTrailingZeros(randInt) / 8,
|
||||
ctzDiv8Int(randInt));
|
||||
Asserts.assertEQ(ctzRandLimitInterpretedInt(randInt), ctzRandLimitInt(randInt));
|
||||
|
||||
checkConstResults(ctzConstLongs(), x -> Long.numberOfTrailingZeros(x.longValue()));
|
||||
Asserts.assertEQ(Long.numberOfTrailingZeros(randLong) < 0
|
||||
|| Long.numberOfTrailingZeros(randLong) > 64,
|
||||
ctzCompareLong(randLong));
|
||||
Asserts.assertEQ(Long.numberOfTrailingZeros(randLong) / 8,
|
||||
ctzDiv8Long(randLong));
|
||||
Asserts.assertEQ(ctzRandLimitInterpretedLong(randLong), ctzRandLimitLong(randLong));
|
||||
}
|
||||
|
||||
@DontCompile
|
||||
public void checkConstResults(int[] results, Function<Long, Integer> op) {
|
||||
Asserts.assertEQ(op.apply(Long.valueOf(0)), results[0]);
|
||||
for (int i = 0; i < results.length - 1; ++i) {
|
||||
Asserts.assertEQ(op.apply(Long.valueOf(1l << i)), results[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Test CLZ with constant integer inputs.
|
||||
// All CLZs in this test are expected to be optimized away.
|
||||
@Test
|
||||
@IR(failOn = IRNode.COUNT_LEADING_ZEROS_I)
|
||||
public int[] clzConstInts() {
|
||||
return new int[] {
|
||||
Integer.numberOfLeadingZeros(0),
|
||||
Integer.numberOfLeadingZeros(1 << 0),
|
||||
Integer.numberOfLeadingZeros(1 << 1),
|
||||
Integer.numberOfLeadingZeros(1 << 2),
|
||||
Integer.numberOfLeadingZeros(1 << 3),
|
||||
Integer.numberOfLeadingZeros(1 << 4),
|
||||
Integer.numberOfLeadingZeros(1 << 5),
|
||||
Integer.numberOfLeadingZeros(1 << 6),
|
||||
Integer.numberOfLeadingZeros(1 << 7),
|
||||
Integer.numberOfLeadingZeros(1 << 8),
|
||||
Integer.numberOfLeadingZeros(1 << 9),
|
||||
Integer.numberOfLeadingZeros(1 << 10),
|
||||
Integer.numberOfLeadingZeros(1 << 11),
|
||||
Integer.numberOfLeadingZeros(1 << 12),
|
||||
Integer.numberOfLeadingZeros(1 << 13),
|
||||
Integer.numberOfLeadingZeros(1 << 14),
|
||||
Integer.numberOfLeadingZeros(1 << 15),
|
||||
Integer.numberOfLeadingZeros(1 << 16),
|
||||
Integer.numberOfLeadingZeros(1 << 17),
|
||||
Integer.numberOfLeadingZeros(1 << 18),
|
||||
Integer.numberOfLeadingZeros(1 << 19),
|
||||
Integer.numberOfLeadingZeros(1 << 20),
|
||||
Integer.numberOfLeadingZeros(1 << 21),
|
||||
Integer.numberOfLeadingZeros(1 << 22),
|
||||
Integer.numberOfLeadingZeros(1 << 23),
|
||||
Integer.numberOfLeadingZeros(1 << 24),
|
||||
Integer.numberOfLeadingZeros(1 << 25),
|
||||
Integer.numberOfLeadingZeros(1 << 26),
|
||||
Integer.numberOfLeadingZeros(1 << 27),
|
||||
Integer.numberOfLeadingZeros(1 << 28),
|
||||
Integer.numberOfLeadingZeros(1 << 29),
|
||||
Integer.numberOfLeadingZeros(1 << 30),
|
||||
Integer.numberOfLeadingZeros(1 << 31),
|
||||
};
|
||||
}
|
||||
|
||||
// Test the range of CLZ with random integer input.
|
||||
// The result of CLZ should be in range [0, 32], so CLZs in this test are
|
||||
// expected to be optimized away, and the test should always return false.
|
||||
@Test
|
||||
@IR(failOn = IRNode.COUNT_LEADING_ZEROS_I)
|
||||
public boolean clzCompareInt(int randInt) {
|
||||
return Integer.numberOfLeadingZeros(randInt) < 0
|
||||
|| Integer.numberOfLeadingZeros(randInt) > 32;
|
||||
}
|
||||
|
||||
// Test the combination of CLZ and division by 8.
|
||||
// The result of CLZ should be positive, so the division by 8 should be
|
||||
// optimized to a simple right shift without rounding.
|
||||
@Test
|
||||
@IR(counts = {IRNode.COUNT_LEADING_ZEROS_I, "1",
|
||||
IRNode.RSHIFT_I, "1",
|
||||
IRNode.URSHIFT_I, "0",
|
||||
IRNode.ADD_I, "0"})
|
||||
public int clzDiv8Int(int randInt) {
|
||||
return Integer.numberOfLeadingZeros(randInt) / 8;
|
||||
}
|
||||
|
||||
// Test the output range of CLZ with random input range.
|
||||
@Test
|
||||
public int clzRandLimitInt(int randInt) {
|
||||
randInt = RANGE_INT.clamp(randInt);
|
||||
int result = Integer.numberOfLeadingZeros(randInt);
|
||||
return getResultChecksum32(result);
|
||||
}
|
||||
|
||||
@DontCompile
|
||||
public int clzRandLimitInterpretedInt(int randInt) {
|
||||
randInt = RANGE_INT.clamp(randInt);
|
||||
int result = Integer.numberOfLeadingZeros(randInt);
|
||||
return getResultChecksum32(result);
|
||||
}
|
||||
|
||||
// Test CLZ with constant long inputs.
|
||||
// All CLZs in this test are expected to be optimized away.
|
||||
@Test
|
||||
@IR(failOn = IRNode.COUNT_LEADING_ZEROS_L)
|
||||
public int[] clzConstLongs() {
|
||||
return new int[] {
|
||||
Long.numberOfLeadingZeros(0),
|
||||
Long.numberOfLeadingZeros(1l << 0),
|
||||
Long.numberOfLeadingZeros(1l << 1),
|
||||
Long.numberOfLeadingZeros(1l << 2),
|
||||
Long.numberOfLeadingZeros(1l << 3),
|
||||
Long.numberOfLeadingZeros(1l << 4),
|
||||
Long.numberOfLeadingZeros(1l << 5),
|
||||
Long.numberOfLeadingZeros(1l << 6),
|
||||
Long.numberOfLeadingZeros(1l << 7),
|
||||
Long.numberOfLeadingZeros(1l << 8),
|
||||
Long.numberOfLeadingZeros(1l << 9),
|
||||
Long.numberOfLeadingZeros(1l << 10),
|
||||
Long.numberOfLeadingZeros(1l << 11),
|
||||
Long.numberOfLeadingZeros(1l << 12),
|
||||
Long.numberOfLeadingZeros(1l << 13),
|
||||
Long.numberOfLeadingZeros(1l << 14),
|
||||
Long.numberOfLeadingZeros(1l << 15),
|
||||
Long.numberOfLeadingZeros(1l << 16),
|
||||
Long.numberOfLeadingZeros(1l << 17),
|
||||
Long.numberOfLeadingZeros(1l << 18),
|
||||
Long.numberOfLeadingZeros(1l << 19),
|
||||
Long.numberOfLeadingZeros(1l << 20),
|
||||
Long.numberOfLeadingZeros(1l << 21),
|
||||
Long.numberOfLeadingZeros(1l << 22),
|
||||
Long.numberOfLeadingZeros(1l << 23),
|
||||
Long.numberOfLeadingZeros(1l << 24),
|
||||
Long.numberOfLeadingZeros(1l << 25),
|
||||
Long.numberOfLeadingZeros(1l << 26),
|
||||
Long.numberOfLeadingZeros(1l << 27),
|
||||
Long.numberOfLeadingZeros(1l << 28),
|
||||
Long.numberOfLeadingZeros(1l << 29),
|
||||
Long.numberOfLeadingZeros(1l << 30),
|
||||
Long.numberOfLeadingZeros(1l << 31),
|
||||
Long.numberOfLeadingZeros(1l << 32),
|
||||
Long.numberOfLeadingZeros(1l << 33),
|
||||
Long.numberOfLeadingZeros(1l << 34),
|
||||
Long.numberOfLeadingZeros(1l << 35),
|
||||
Long.numberOfLeadingZeros(1l << 36),
|
||||
Long.numberOfLeadingZeros(1l << 37),
|
||||
Long.numberOfLeadingZeros(1l << 38),
|
||||
Long.numberOfLeadingZeros(1l << 39),
|
||||
Long.numberOfLeadingZeros(1l << 40),
|
||||
Long.numberOfLeadingZeros(1l << 41),
|
||||
Long.numberOfLeadingZeros(1l << 42),
|
||||
Long.numberOfLeadingZeros(1l << 43),
|
||||
Long.numberOfLeadingZeros(1l << 44),
|
||||
Long.numberOfLeadingZeros(1l << 45),
|
||||
Long.numberOfLeadingZeros(1l << 46),
|
||||
Long.numberOfLeadingZeros(1l << 47),
|
||||
Long.numberOfLeadingZeros(1l << 48),
|
||||
Long.numberOfLeadingZeros(1l << 49),
|
||||
Long.numberOfLeadingZeros(1l << 50),
|
||||
Long.numberOfLeadingZeros(1l << 51),
|
||||
Long.numberOfLeadingZeros(1l << 52),
|
||||
Long.numberOfLeadingZeros(1l << 53),
|
||||
Long.numberOfLeadingZeros(1l << 54),
|
||||
Long.numberOfLeadingZeros(1l << 55),
|
||||
Long.numberOfLeadingZeros(1l << 56),
|
||||
Long.numberOfLeadingZeros(1l << 57),
|
||||
Long.numberOfLeadingZeros(1l << 58),
|
||||
Long.numberOfLeadingZeros(1l << 59),
|
||||
Long.numberOfLeadingZeros(1l << 60),
|
||||
Long.numberOfLeadingZeros(1l << 61),
|
||||
Long.numberOfLeadingZeros(1l << 62),
|
||||
Long.numberOfLeadingZeros(1l << 63),
|
||||
};
|
||||
}
|
||||
|
||||
// Test the range of CLZ with random long input.
|
||||
// The result of CLZ should be in range [0, 64], so CLZs in this test are
|
||||
// expected to be optimized away, and the test should always return false.
|
||||
@Test
|
||||
@IR(failOn = IRNode.COUNT_LEADING_ZEROS_L)
|
||||
public boolean clzCompareLong(long randLong) {
|
||||
return Long.numberOfLeadingZeros(randLong) < 0
|
||||
|| Long.numberOfLeadingZeros(randLong) > 64;
|
||||
}
|
||||
|
||||
// Test the combination of CLZ and division by 8.
|
||||
// The result of CLZ should be positive, so the division by 8 should be
|
||||
// optimized to a simple right shift without rounding.
|
||||
@Test
|
||||
@IR(counts = {IRNode.COUNT_LEADING_ZEROS_L, "1",
|
||||
IRNode.RSHIFT_I, "1",
|
||||
IRNode.URSHIFT_I, "0",
|
||||
IRNode.ADD_I, "0"})
|
||||
public int clzDiv8Long(long randLong) {
|
||||
return Long.numberOfLeadingZeros(randLong) / 8;
|
||||
}
|
||||
|
||||
// Test the output range of CLZ with random input range.
|
||||
@Test
|
||||
public int clzRandLimitLong(long randLong) {
|
||||
randLong = RANGE_LONG.clamp(randLong);
|
||||
int result = Long.numberOfLeadingZeros(randLong);
|
||||
return getResultChecksum64(result);
|
||||
}
|
||||
|
||||
@DontCompile
|
||||
public int clzRandLimitInterpretedLong(long randLong) {
|
||||
randLong = RANGE_LONG.clamp(randLong);
|
||||
int result = Long.numberOfLeadingZeros(randLong);
|
||||
return getResultChecksum64(result);
|
||||
}
|
||||
|
||||
// Test CTZ with constant integer inputs.
|
||||
// All CTZs in this test are expected to be optimized away.
|
||||
@Test
|
||||
@IR(failOn = IRNode.COUNT_TRAILING_ZEROS_I)
|
||||
public int[] ctzConstInts() {
|
||||
return new int[] {
|
||||
Integer.numberOfTrailingZeros(0),
|
||||
Integer.numberOfTrailingZeros(1 << 0),
|
||||
Integer.numberOfTrailingZeros(1 << 1),
|
||||
Integer.numberOfTrailingZeros(1 << 2),
|
||||
Integer.numberOfTrailingZeros(1 << 3),
|
||||
Integer.numberOfTrailingZeros(1 << 4),
|
||||
Integer.numberOfTrailingZeros(1 << 5),
|
||||
Integer.numberOfTrailingZeros(1 << 6),
|
||||
Integer.numberOfTrailingZeros(1 << 7),
|
||||
Integer.numberOfTrailingZeros(1 << 8),
|
||||
Integer.numberOfTrailingZeros(1 << 9),
|
||||
Integer.numberOfTrailingZeros(1 << 10),
|
||||
Integer.numberOfTrailingZeros(1 << 11),
|
||||
Integer.numberOfTrailingZeros(1 << 12),
|
||||
Integer.numberOfTrailingZeros(1 << 13),
|
||||
Integer.numberOfTrailingZeros(1 << 14),
|
||||
Integer.numberOfTrailingZeros(1 << 15),
|
||||
Integer.numberOfTrailingZeros(1 << 16),
|
||||
Integer.numberOfTrailingZeros(1 << 17),
|
||||
Integer.numberOfTrailingZeros(1 << 18),
|
||||
Integer.numberOfTrailingZeros(1 << 19),
|
||||
Integer.numberOfTrailingZeros(1 << 20),
|
||||
Integer.numberOfTrailingZeros(1 << 21),
|
||||
Integer.numberOfTrailingZeros(1 << 22),
|
||||
Integer.numberOfTrailingZeros(1 << 23),
|
||||
Integer.numberOfTrailingZeros(1 << 24),
|
||||
Integer.numberOfTrailingZeros(1 << 25),
|
||||
Integer.numberOfTrailingZeros(1 << 26),
|
||||
Integer.numberOfTrailingZeros(1 << 27),
|
||||
Integer.numberOfTrailingZeros(1 << 28),
|
||||
Integer.numberOfTrailingZeros(1 << 29),
|
||||
Integer.numberOfTrailingZeros(1 << 30),
|
||||
Integer.numberOfTrailingZeros(1 << 31),
|
||||
};
|
||||
}
|
||||
|
||||
// Test the range of CTZ with random integer input.
|
||||
// The result of CTZ should be in range [0, 32], so CTZs in this test are
|
||||
// expected to be optimized away, and the test should always return false.
|
||||
@Test
|
||||
@IR(failOn = IRNode.COUNT_TRAILING_ZEROS_I)
|
||||
public boolean ctzCompareInt(int randInt) {
|
||||
return Integer.numberOfTrailingZeros(randInt) < 0
|
||||
|| Integer.numberOfTrailingZeros(randInt) > 32;
|
||||
}
|
||||
|
||||
// Test the combination of CTZ and division by 8.
|
||||
// The result of CTZ should be positive, so the division by 8 should be
|
||||
// optimized to a simple right shift without rounding.
|
||||
@Test
|
||||
@IR(counts = {IRNode.COUNT_TRAILING_ZEROS_I, "1",
|
||||
IRNode.RSHIFT_I, "1",
|
||||
IRNode.URSHIFT_I, "0",
|
||||
IRNode.ADD_I, "0"})
|
||||
public int ctzDiv8Int(int randInt) {
|
||||
return Integer.numberOfTrailingZeros(randInt) / 8;
|
||||
}
|
||||
|
||||
// Test the output range of CTZ with random input range.
|
||||
@Test
|
||||
public int ctzRandLimitInt(int randInt) {
|
||||
randInt = RANGE_INT.clamp(randInt);
|
||||
int result = Integer.numberOfTrailingZeros(randInt);
|
||||
return getResultChecksum32(result);
|
||||
}
|
||||
|
||||
@DontCompile
|
||||
public int ctzRandLimitInterpretedInt(int randInt) {
|
||||
randInt = RANGE_INT.clamp(randInt);
|
||||
int result = Integer.numberOfTrailingZeros(randInt);
|
||||
return getResultChecksum32(result);
|
||||
}
|
||||
|
||||
// Test CTZ with constant long inputs.
|
||||
// All CTZs in this test are expected to be optimized away.
|
||||
@Test
|
||||
@IR(failOn = IRNode.COUNT_TRAILING_ZEROS_L)
|
||||
public int[] ctzConstLongs() {
|
||||
return new int[] {
|
||||
Long.numberOfTrailingZeros(0),
|
||||
Long.numberOfTrailingZeros(1l << 0),
|
||||
Long.numberOfTrailingZeros(1l << 1),
|
||||
Long.numberOfTrailingZeros(1l << 2),
|
||||
Long.numberOfTrailingZeros(1l << 3),
|
||||
Long.numberOfTrailingZeros(1l << 4),
|
||||
Long.numberOfTrailingZeros(1l << 5),
|
||||
Long.numberOfTrailingZeros(1l << 6),
|
||||
Long.numberOfTrailingZeros(1l << 7),
|
||||
Long.numberOfTrailingZeros(1l << 8),
|
||||
Long.numberOfTrailingZeros(1l << 9),
|
||||
Long.numberOfTrailingZeros(1l << 10),
|
||||
Long.numberOfTrailingZeros(1l << 11),
|
||||
Long.numberOfTrailingZeros(1l << 12),
|
||||
Long.numberOfTrailingZeros(1l << 13),
|
||||
Long.numberOfTrailingZeros(1l << 14),
|
||||
Long.numberOfTrailingZeros(1l << 15),
|
||||
Long.numberOfTrailingZeros(1l << 16),
|
||||
Long.numberOfTrailingZeros(1l << 17),
|
||||
Long.numberOfTrailingZeros(1l << 18),
|
||||
Long.numberOfTrailingZeros(1l << 19),
|
||||
Long.numberOfTrailingZeros(1l << 20),
|
||||
Long.numberOfTrailingZeros(1l << 21),
|
||||
Long.numberOfTrailingZeros(1l << 22),
|
||||
Long.numberOfTrailingZeros(1l << 23),
|
||||
Long.numberOfTrailingZeros(1l << 24),
|
||||
Long.numberOfTrailingZeros(1l << 25),
|
||||
Long.numberOfTrailingZeros(1l << 26),
|
||||
Long.numberOfTrailingZeros(1l << 27),
|
||||
Long.numberOfTrailingZeros(1l << 28),
|
||||
Long.numberOfTrailingZeros(1l << 29),
|
||||
Long.numberOfTrailingZeros(1l << 30),
|
||||
Long.numberOfTrailingZeros(1l << 31),
|
||||
Long.numberOfTrailingZeros(1l << 32),
|
||||
Long.numberOfTrailingZeros(1l << 33),
|
||||
Long.numberOfTrailingZeros(1l << 34),
|
||||
Long.numberOfTrailingZeros(1l << 35),
|
||||
Long.numberOfTrailingZeros(1l << 36),
|
||||
Long.numberOfTrailingZeros(1l << 37),
|
||||
Long.numberOfTrailingZeros(1l << 38),
|
||||
Long.numberOfTrailingZeros(1l << 39),
|
||||
Long.numberOfTrailingZeros(1l << 40),
|
||||
Long.numberOfTrailingZeros(1l << 41),
|
||||
Long.numberOfTrailingZeros(1l << 42),
|
||||
Long.numberOfTrailingZeros(1l << 43),
|
||||
Long.numberOfTrailingZeros(1l << 44),
|
||||
Long.numberOfTrailingZeros(1l << 45),
|
||||
Long.numberOfTrailingZeros(1l << 46),
|
||||
Long.numberOfTrailingZeros(1l << 47),
|
||||
Long.numberOfTrailingZeros(1l << 48),
|
||||
Long.numberOfTrailingZeros(1l << 49),
|
||||
Long.numberOfTrailingZeros(1l << 50),
|
||||
Long.numberOfTrailingZeros(1l << 51),
|
||||
Long.numberOfTrailingZeros(1l << 52),
|
||||
Long.numberOfTrailingZeros(1l << 53),
|
||||
Long.numberOfTrailingZeros(1l << 54),
|
||||
Long.numberOfTrailingZeros(1l << 55),
|
||||
Long.numberOfTrailingZeros(1l << 56),
|
||||
Long.numberOfTrailingZeros(1l << 57),
|
||||
Long.numberOfTrailingZeros(1l << 58),
|
||||
Long.numberOfTrailingZeros(1l << 59),
|
||||
Long.numberOfTrailingZeros(1l << 60),
|
||||
Long.numberOfTrailingZeros(1l << 61),
|
||||
Long.numberOfTrailingZeros(1l << 62),
|
||||
Long.numberOfTrailingZeros(1l << 63),
|
||||
};
|
||||
}
|
||||
|
||||
// Test the range of CTZ with random long input.
|
||||
// The result of CTZ should be in range [0, 64], so CTZs in this test are
|
||||
// expected to be optimized away, and the test should always return false.
|
||||
@Test
|
||||
@IR(failOn = IRNode.COUNT_TRAILING_ZEROS_L)
|
||||
public boolean ctzCompareLong(long randLong) {
|
||||
return Long.numberOfTrailingZeros(randLong) < 0
|
||||
|| Long.numberOfTrailingZeros(randLong) > 64;
|
||||
}
|
||||
|
||||
// Test the combination of CTZ and division by 8.
|
||||
// The result of CTZ should be positive, so the division by 8 should be
|
||||
// optimized to a simple right shift without rounding.
|
||||
@Test
|
||||
@IR(counts = {IRNode.COUNT_TRAILING_ZEROS_L, "1",
|
||||
IRNode.RSHIFT_I, "1",
|
||||
IRNode.URSHIFT_I, "0",
|
||||
IRNode.ADD_I, "0"})
|
||||
public int ctzDiv8Long(long randLong) {
|
||||
return Long.numberOfTrailingZeros(randLong) / 8;
|
||||
}
|
||||
|
||||
// Test the output range of CTZ with random input range.
|
||||
@Test
|
||||
public int ctzRandLimitLong(long randLong) {
|
||||
randLong = RANGE_LONG.clamp(randLong);
|
||||
int result = Long.numberOfLeadingZeros(randLong);
|
||||
return getResultChecksum64(result);
|
||||
}
|
||||
|
||||
@DontCompile
|
||||
public int ctzRandLimitInterpretedLong(long randLong) {
|
||||
randLong = RANGE_LONG.clamp(randLong);
|
||||
int result = Long.numberOfLeadingZeros(randLong);
|
||||
return getResultChecksum64(result);
|
||||
}
|
||||
|
||||
record IntRange(int lo, int hi) {
|
||||
IntRange {
|
||||
if (lo > hi) {
|
||||
throw new IllegalArgumentException("lo > hi");
|
||||
}
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
int clamp(int v) {
|
||||
return v < lo ? lo : v > hi ? hi : v;
|
||||
}
|
||||
|
||||
static IntRange generate(Generator<Integer> g) {
|
||||
int a = g.next(), b = g.next();
|
||||
return a < b ? new IntRange(a, b) : new IntRange(b, a);
|
||||
}
|
||||
}
|
||||
|
||||
record LongRange(long lo, long hi) {
|
||||
LongRange {
|
||||
if (lo > hi) {
|
||||
throw new IllegalArgumentException("lo > hi");
|
||||
}
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
long clamp(long v) {
|
||||
return v < lo ? lo : v > hi ? hi : v;
|
||||
}
|
||||
|
||||
static LongRange generate(Generator<Long> g) {
|
||||
long a = g.next(), b = g.next();
|
||||
return a < b ? new LongRange(a, b) : new LongRange(b, a);
|
||||
}
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
int getResultChecksum32(int result) {
|
||||
int sum = 0;
|
||||
if (result < LIMITS_32_0) sum += 1;
|
||||
if (result < LIMITS_32_1) sum += 2;
|
||||
if (result < LIMITS_32_2) sum += 4;
|
||||
if (result < LIMITS_32_3) sum += 8;
|
||||
if (result > LIMITS_32_4) sum += 16;
|
||||
if (result > LIMITS_32_5) sum += 32;
|
||||
if (result > LIMITS_32_6) sum += 64;
|
||||
if (result > LIMITS_32_7) sum += 128;
|
||||
return sum;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
int getResultChecksum64(int result) {
|
||||
int sum = 0;
|
||||
if (result < LIMITS_64_0) sum += 1;
|
||||
if (result < LIMITS_64_1) sum += 2;
|
||||
if (result < LIMITS_64_2) sum += 4;
|
||||
if (result < LIMITS_64_3) sum += 8;
|
||||
if (result > LIMITS_64_4) sum += 16;
|
||||
if (result > LIMITS_64_5) sum += 32;
|
||||
if (result > LIMITS_64_6) sum += 64;
|
||||
if (result > LIMITS_64_7) sum += 128;
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Rivos 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.
|
||||
*/
|
||||
|
||||
package compiler.c2.irTests;
|
||||
|
||||
import compiler.lib.ir_framework.*;
|
||||
import java.util.Random;
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.Utils;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test conditional move + compare object.
|
||||
* @requires vm.simpleArch == "riscv64"
|
||||
* @library /test/lib /
|
||||
* @run driver compiler.c2.irTests.TestScalarConditionalMoveCmpObj
|
||||
*/
|
||||
|
||||
public class TestScalarConditionalMoveCmpObj {
|
||||
final private static int SIZE = 1024;
|
||||
private static final Random RANDOM = Utils.getRandomInstance();
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:-UseVectorCmov",
|
||||
"-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders", "-XX:+UseCompressedOops");
|
||||
TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:-UseVectorCmov",
|
||||
"-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders", "-XX:-UseCompressedOops");
|
||||
TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:-UseVectorCmov",
|
||||
"-XX:+UnlockExperimentalVMOptions", "-XX:+UseCompactObjectHeaders", "-XX:+UseCompressedOops");
|
||||
TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:-UseVectorCmov",
|
||||
"-XX:+UnlockExperimentalVMOptions", "-XX:+UseCompactObjectHeaders", "-XX:-UseCompressedOops");
|
||||
}
|
||||
|
||||
// Object comparison
|
||||
// O for I
|
||||
private int cmoveOEQforI(Object a, Object b, int c, int d) {
|
||||
return (a == b) ? c : d;
|
||||
}
|
||||
|
||||
private int cmoveONEforI(Object a, Object b, int c, int d) {
|
||||
return (a != b) ? c : d;
|
||||
}
|
||||
|
||||
// O for L
|
||||
private long cmoveOEQforL(Object a, Object b, long c, long d) {
|
||||
return (a == b) ? c : d;
|
||||
}
|
||||
|
||||
private long cmoveONEforL(Object a, Object b, long c, long d) {
|
||||
return (a != b) ? c : d;
|
||||
}
|
||||
|
||||
// O for F
|
||||
private float cmoveOEQforF(Object a, Object b, float c, float d) {
|
||||
return (a == b) ? c : d;
|
||||
}
|
||||
|
||||
private float cmoveONEforF(Object a, Object b, float c, float d) {
|
||||
return (a != b) ? c : d;
|
||||
}
|
||||
|
||||
// O for D
|
||||
private double cmoveOEQforD(Object a, Object b, double c, double d) {
|
||||
return (a == b) ? c : d;
|
||||
}
|
||||
|
||||
private double cmoveONEforD(Object a, Object b, double c, double d) {
|
||||
return (a != b) ? c : d;
|
||||
}
|
||||
|
||||
// Tests shows CMoveI is generated, so let @IR verify CMOVE_I.
|
||||
//
|
||||
@Test
|
||||
@IR(failOn = {IRNode.STORE_VECTOR})
|
||||
@IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_P, ">0"},
|
||||
applyIf = {"UseCompressedOops", "false"})
|
||||
@IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_N, ">0"},
|
||||
applyIf = {"UseCompressedOops", "true"})
|
||||
private static void testCMoveOEQforI(Object[] a, Object[] b, int[] c, int[] d, int[] r, int[] r2) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
int cc = c[i];
|
||||
int dd = d[i];
|
||||
r2[i] = cc + dd;
|
||||
r[i] = (a[i] == b[i]) ? cc : dd;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = {IRNode.STORE_VECTOR})
|
||||
@IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_P, ">0"},
|
||||
applyIf = {"UseCompressedOops", "false"})
|
||||
@IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_N, ">0"},
|
||||
applyIf = {"UseCompressedOops", "true"})
|
||||
private static void testCMoveONEforI(Object[] a, Object[] b, int[] c, int[] d, int[] r, int[] r2) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
int cc = c[i];
|
||||
int dd = d[i];
|
||||
r2[i] = cc + dd;
|
||||
r[i] = (a[i] != b[i]) ? cc : dd;
|
||||
}
|
||||
}
|
||||
|
||||
// So far, CMoveL is not guaranteed to be generated, so @IR not verify CMOVE_L.
|
||||
// TODO: enable CMOVE_L verification when it's guaranteed to generate CMOVE_L.
|
||||
//
|
||||
@Test
|
||||
@IR(failOn = {IRNode.STORE_VECTOR})
|
||||
// @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_P, ">0"},
|
||||
// applyIf = {"UseCompressedOops", "false"})
|
||||
// @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_N, ">0"},
|
||||
// applyIf = {"UseCompressedOops", "true"})
|
||||
private static void testCMoveOEQforL(Object[] a, Object[] b, long[] c, long[] d, long[] r, long[] r2) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
long cc = c[i];
|
||||
long dd = d[i];
|
||||
r2[i] = cc + dd;
|
||||
r[i] = (a[i] == b[i]) ? cc : dd;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = {IRNode.STORE_VECTOR})
|
||||
// @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_P, ">0"},
|
||||
// applyIf = {"UseCompressedOops", "false"})
|
||||
// @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_N, ">0"},
|
||||
// applyIf = {"UseCompressedOops", "true"})
|
||||
private static void testCMoveONEforL(Object[] a, Object[] b, long[] c, long[] d, long[] r, long[] r2) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
long cc = c[i];
|
||||
long dd = d[i];
|
||||
r2[i] = cc + dd;
|
||||
r[i] = (a[i] != b[i]) ? cc : dd;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = {IRNode.STORE_VECTOR})
|
||||
@IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_P, ">0"},
|
||||
applyIf = {"UseCompressedOops", "false"})
|
||||
@IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_N, ">0"},
|
||||
applyIf = {"UseCompressedOops", "true"})
|
||||
private static void testCMoveOEQforF(Object[] a, Object[] b, float[] c, float[] d, float[] r, float[] r2) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
float cc = c[i];
|
||||
float dd = d[i];
|
||||
r2[i] = cc + dd;
|
||||
r[i] = (a[i] == b[i]) ? cc : dd;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = {IRNode.STORE_VECTOR})
|
||||
@IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_P, ">0"},
|
||||
applyIf = {"UseCompressedOops", "false"})
|
||||
@IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_N, ">0"},
|
||||
applyIf = {"UseCompressedOops", "true"})
|
||||
private static void testCMoveONEforF(Object[] a, Object[] b, float[] c, float[] d, float[] r, float[] r2) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
float cc = c[i];
|
||||
float dd = d[i];
|
||||
r2[i] = cc + dd;
|
||||
r[i] = (a[i] != b[i]) ? cc : dd;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = {IRNode.STORE_VECTOR})
|
||||
@IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_P, ">0"},
|
||||
applyIf = {"UseCompressedOops", "false"})
|
||||
@IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_N, ">0"},
|
||||
applyIf = {"UseCompressedOops", "true"})
|
||||
private static void testCMoveOEQforD(Object[] a, Object[] b, double[] c, double[] d, double[] r, double[] r2) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
double cc = c[i];
|
||||
double dd = d[i];
|
||||
r2[i] = cc + dd;
|
||||
r[i] = (a[i] == b[i]) ? cc : dd;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = {IRNode.STORE_VECTOR})
|
||||
@IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_P, ">0"},
|
||||
applyIf = {"UseCompressedOops", "false"})
|
||||
@IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_N, ">0"},
|
||||
applyIf = {"UseCompressedOops", "true"})
|
||||
private static void testCMoveONEforD(Object[] a, Object[] b, double[] c, double[] d, double[] r, double[] r2) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
double cc = c[i];
|
||||
double dd = d[i];
|
||||
r2[i] = cc + dd;
|
||||
r[i] = (a[i] != b[i]) ? cc : dd;
|
||||
}
|
||||
}
|
||||
|
||||
@Warmup(0)
|
||||
@Run(test = {// Object
|
||||
"testCMoveOEQforI",
|
||||
"testCMoveONEforI",
|
||||
"testCMoveOEQforL",
|
||||
"testCMoveONEforL",
|
||||
"testCMoveOEQforF",
|
||||
"testCMoveONEforF",
|
||||
"testCMoveOEQforD",
|
||||
"testCMoveONEforD",
|
||||
})
|
||||
private void testCMove_runner_two() {
|
||||
Object[] aO = new Object[SIZE];
|
||||
Object[] bO = new Object[SIZE];
|
||||
int[] cI = new int[SIZE];
|
||||
int[] dI = new int[SIZE];
|
||||
int[] rI = new int[SIZE];
|
||||
long[] cL = new long[SIZE];
|
||||
long[] dL = new long[SIZE];
|
||||
long[] rL = new long[SIZE];
|
||||
float[] cF = new float[SIZE];
|
||||
float[] dF = new float[SIZE];
|
||||
float[] rF = new float[SIZE];
|
||||
double[] cD = new double[SIZE];
|
||||
double[] dD = new double[SIZE];
|
||||
double[] rD = new double[SIZE];
|
||||
|
||||
init(aO);
|
||||
shuffle(aO, bO);
|
||||
init(cL);
|
||||
init(dL);
|
||||
init(cF);
|
||||
init(dF);
|
||||
init(cD);
|
||||
init(dD);
|
||||
|
||||
testCMoveOEQforI(aO, bO, cI, dI, rI, rI);
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
Asserts.assertEquals(rI[i], cmoveOEQforI(aO[i], bO[i], cI[i], dI[i]));
|
||||
}
|
||||
|
||||
testCMoveONEforI(aO, bO, cI, dI, rI, rI);
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
Asserts.assertEquals(rI[i], cmoveONEforI(aO[i], bO[i], cI[i], dI[i]));
|
||||
}
|
||||
|
||||
testCMoveOEQforL(aO, bO, cL, dL, rL, rL);
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
Asserts.assertEquals(rL[i], cmoveOEQforL(aO[i], bO[i], cL[i], dL[i]));
|
||||
}
|
||||
|
||||
testCMoveONEforL(aO, bO, cL, dL, rL, rL);
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
Asserts.assertEquals(rL[i], cmoveONEforL(aO[i], bO[i], cL[i], dL[i]));
|
||||
}
|
||||
|
||||
testCMoveOEQforF(aO, bO, cF, dF, rF, rF);
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
Asserts.assertEquals(rF[i], cmoveOEQforF(aO[i], bO[i], cF[i], dF[i]));
|
||||
}
|
||||
|
||||
testCMoveONEforF(aO, bO, cF, dF, rF, rF);
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
Asserts.assertEquals(rF[i], cmoveONEforF(aO[i], bO[i], cF[i], dF[i]));
|
||||
}
|
||||
|
||||
testCMoveOEQforD(aO, bO, cD, dD, rD, rD);
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
Asserts.assertEquals(rD[i], cmoveOEQforD(aO[i], bO[i], cD[i], dD[i]));
|
||||
}
|
||||
|
||||
testCMoveONEforD(aO, bO, cD, dD, rD, rD);
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
Asserts.assertEquals(rD[i], cmoveONEforD(aO[i], bO[i], cD[i], dD[i]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void init(Object[] a) {
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = new Object();
|
||||
}
|
||||
}
|
||||
|
||||
private static void shuffle(Object[] a, Object[] b) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
b[i] = a[i];
|
||||
}
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
if (rand.nextInt(5) == 0) {
|
||||
Object t = b[i];
|
||||
b[i] = b[SIZE-1-i];
|
||||
b[SIZE-1-i] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void init(int[] a) {
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = RANDOM.nextInt();
|
||||
}
|
||||
}
|
||||
|
||||
private static void init(long[] a) {
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = RANDOM.nextLong();
|
||||
}
|
||||
}
|
||||
|
||||
private static void init(float[] a) {
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = switch(RANDOM.nextInt() % 20) {
|
||||
case 0 -> Float.NaN;
|
||||
case 1 -> 0;
|
||||
case 2 -> 1;
|
||||
case 3 -> Float.POSITIVE_INFINITY;
|
||||
case 4 -> Float.NEGATIVE_INFINITY;
|
||||
case 5 -> Float.MAX_VALUE;
|
||||
case 6 -> Float.MIN_VALUE;
|
||||
case 7, 8, 9 -> RANDOM.nextFloat();
|
||||
default -> Float.intBitsToFloat(RANDOM.nextInt());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static void init(double[] a) {
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = switch(RANDOM.nextInt() % 20) {
|
||||
case 0 -> Double.NaN;
|
||||
case 1 -> 0;
|
||||
case 2 -> 1;
|
||||
case 3 -> Double.POSITIVE_INFINITY;
|
||||
case 4 -> Double.NEGATIVE_INFINITY;
|
||||
case 5 -> Double.MAX_VALUE;
|
||||
case 6 -> Double.MIN_VALUE;
|
||||
case 7, 8, 9 -> RANDOM.nextDouble();
|
||||
default -> Double.longBitsToDouble(RANDOM.nextLong());
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -545,11 +545,36 @@ public class IRNode {
|
||||
trapNodes(CLASS_CHECK_TRAP, "class_check");
|
||||
}
|
||||
|
||||
public static final String CMOVE_F = PREFIX + "CMOVE_F" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(CMOVE_F, "CMoveF");
|
||||
}
|
||||
|
||||
public static final String CMOVE_D = PREFIX + "CMOVE_D" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(CMOVE_D, "CMoveD");
|
||||
}
|
||||
|
||||
public static final String CMOVE_I = PREFIX + "CMOVE_I" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(CMOVE_I, "CMoveI");
|
||||
}
|
||||
|
||||
public static final String CMOVE_L = PREFIX + "CMOVE_L" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(CMOVE_L, "CMoveL");
|
||||
}
|
||||
|
||||
public static final String CMP_F = PREFIX + "CMP_F" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(CMP_F, "CmpF");
|
||||
}
|
||||
|
||||
public static final String CMP_D = PREFIX + "CMP_D" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(CMP_D, "CmpD");
|
||||
}
|
||||
|
||||
public static final String CMP_I = PREFIX + "CMP_I" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(CMP_I, "CmpI");
|
||||
@ -585,6 +610,11 @@ public class IRNode {
|
||||
beforeMatchingNameRegex(CMP_P, "CmpP");
|
||||
}
|
||||
|
||||
public static final String CMP_N = PREFIX + "CMP_N" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(CMP_N, "CmpN");
|
||||
}
|
||||
|
||||
public static final String CMP_LT_MASK = PREFIX + "CMP_LT_MASK" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(CMP_LT_MASK, "CmpLTMask");
|
||||
@ -1661,6 +1691,16 @@ public class IRNode {
|
||||
vectorNode(POPCOUNT_VL, "PopCountVL", TYPE_LONG);
|
||||
}
|
||||
|
||||
public static final String COUNT_TRAILING_ZEROS_I = PREFIX + "COUNT_TRAILING_ZEROS_I" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(COUNT_TRAILING_ZEROS_I, "CountTrailingZerosI");
|
||||
}
|
||||
|
||||
public static final String COUNT_TRAILING_ZEROS_L = PREFIX + "COUNT_TRAILING_ZEROS_L" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(COUNT_TRAILING_ZEROS_L, "CountTrailingZerosL");
|
||||
}
|
||||
|
||||
public static final String COUNT_TRAILING_ZEROS_VL = VECTOR_PREFIX + "COUNT_TRAILING_ZEROS_VL" + POSTFIX;
|
||||
static {
|
||||
vectorNode(COUNT_TRAILING_ZEROS_VL, "CountTrailingZerosV", TYPE_LONG);
|
||||
@ -1671,6 +1711,16 @@ public class IRNode {
|
||||
vectorNode(COUNT_TRAILING_ZEROS_VI, "CountTrailingZerosV", TYPE_INT);
|
||||
}
|
||||
|
||||
public static final String COUNT_LEADING_ZEROS_I = PREFIX + "COUNT_LEADING_ZEROS_I" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(COUNT_LEADING_ZEROS_I, "CountLeadingZerosI");
|
||||
}
|
||||
|
||||
public static final String COUNT_LEADING_ZEROS_L = PREFIX + "COUNT_LEADING_ZEROS_L" + POSTFIX;
|
||||
static {
|
||||
beforeMatchingNameRegex(COUNT_LEADING_ZEROS_L, "CountLeadingZerosL");
|
||||
}
|
||||
|
||||
public static final String COUNT_LEADING_ZEROS_VL = VECTOR_PREFIX + "COUNT_LEADING_ZEROS_VL" + POSTFIX;
|
||||
static {
|
||||
vectorNode(COUNT_LEADING_ZEROS_VL, "CountLeadingZerosV", TYPE_LONG);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. 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
|
||||
@ -355,7 +355,16 @@ public class ExceptionEvents extends TestScaffold {
|
||||
if (event.request() == request) {
|
||||
try {
|
||||
System.out.print("ExceptionEvent: ");
|
||||
System.out.print("" + event.exception().referenceType().name());
|
||||
try {
|
||||
System.out.print("" + event.exception().referenceType().name());
|
||||
} catch (ObjectCollectedException e) {
|
||||
if (event.request().suspendPolicy() == EventRequest.SUSPEND_NONE) {
|
||||
// Since the thread was not suspended, the exception object can be collected.
|
||||
System.out.print("<exception object collected>");
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
Location loc = event.location();
|
||||
System.out.print(" @ " + loc.method().name());
|
||||
System.out.print(":" + loc.lineNumber());
|
||||
|
||||
379
test/jdk/javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java
Normal file
379
test/jdk/javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java
Normal file
@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. 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
|
||||
* @bug 8369950
|
||||
* @summary Test that the HttpsURLConnection does not set IP address literals for
|
||||
* SNI hostname during TLS handshake
|
||||
* @library /test/lib
|
||||
* @modules java.base/sun.net.util
|
||||
* @comment Insert -Djavax.net.debug=all into the following lines to enable SSL debugging
|
||||
* @run main/othervm SubjectAltNameIP 127.0.0.1
|
||||
* @run main/othervm SubjectAltNameIP [::1]
|
||||
*/
|
||||
|
||||
import javax.net.ssl.HandshakeCompletedListener;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLServerSocket;
|
||||
import javax.net.ssl.SSLServerSocketFactory;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
import jdk.test.lib.net.SimpleSSLContext;
|
||||
import jtreg.SkippedException;
|
||||
import sun.net.util.IPAddressUtil;
|
||||
|
||||
public class SubjectAltNameIP {
|
||||
|
||||
// Is the server ready to serve?
|
||||
private final CountDownLatch serverReady = new CountDownLatch(1);
|
||||
|
||||
// Use any free port by default.
|
||||
volatile int serverPort = 0;
|
||||
|
||||
// Stores an exception thrown by server in a separate thread.
|
||||
volatile Exception serverException = null;
|
||||
|
||||
// SSLSocket object created by HttpsClient internally.
|
||||
SSLSocket clientSSLSocket = null;
|
||||
|
||||
// The hostname the server socket is bound to.
|
||||
String hostName;
|
||||
|
||||
static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n' };
|
||||
|
||||
// Read until the end of the request.
|
||||
void readOneRequest(InputStream is) throws IOException {
|
||||
int requestEndCount = 0, r;
|
||||
while ((r = is.read()) != -1) {
|
||||
if (r == requestEnd[requestEndCount]) {
|
||||
requestEndCount++;
|
||||
if (requestEndCount == 4) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
requestEndCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Define the server side of the test.
|
||||
*
|
||||
* If the server prematurely exits, serverReady will be set to true
|
||||
* to avoid infinite hangs.
|
||||
*/
|
||||
void doServerSide() throws Exception {
|
||||
SSLServerSocketFactory sslssf =
|
||||
new SimpleSSLContext().get().getServerSocketFactory();
|
||||
SSLServerSocket sslServerSocket =
|
||||
(SSLServerSocket) sslssf.createServerSocket(
|
||||
serverPort, 0,
|
||||
InetAddress.getByName(hostName));
|
||||
sslServerSocket.setEnabledProtocols(new String[]{"TLSv1.3"});
|
||||
serverPort = sslServerSocket.getLocalPort();
|
||||
|
||||
/*
|
||||
* Signal the client, the server is ready to accept connection.
|
||||
*/
|
||||
serverReady.countDown();
|
||||
|
||||
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
|
||||
OutputStream sslOS = sslSocket.getOutputStream();
|
||||
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sslOS));
|
||||
bw.write("HTTP/1.1 200 OK\r\n\r\n");
|
||||
bw.flush();
|
||||
readOneRequest(sslSocket.getInputStream());
|
||||
sslSocket.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Define the client side of the test.
|
||||
*
|
||||
* If the server prematurely exits, serverReady will be set to true
|
||||
* to avoid infinite hangs.
|
||||
*/
|
||||
void doClientSide() throws Exception {
|
||||
|
||||
/*
|
||||
* Wait for server to get started.
|
||||
*/
|
||||
serverReady.await();
|
||||
if (serverException != null) {
|
||||
throw new RuntimeException("Server failed to start.", serverException);
|
||||
}
|
||||
|
||||
SSLSocketFactory sf = new SimpleSSLContext().get().getSocketFactory();
|
||||
URI uri = new URI("https://" + hostName + ":" + serverPort + "/index.html");
|
||||
HttpsURLConnection conn = (HttpsURLConnection)uri.toURL().openConnection();
|
||||
|
||||
/*
|
||||
* Simulate an external JSSE implementation and store the client SSLSocket
|
||||
* used internally.
|
||||
*/
|
||||
conn.setSSLSocketFactory(wrapSocketFactory(sf,
|
||||
sslSocket -> {
|
||||
Asserts.assertEquals(null, clientSSLSocket, "clientSSLSocket is");
|
||||
clientSSLSocket = sslSocket;
|
||||
}));
|
||||
conn.getInputStream();
|
||||
|
||||
var sniSN = clientSSLSocket.getSSLParameters().getServerNames();
|
||||
if (sniSN != null && !sniSN.isEmpty()) {
|
||||
throw new RuntimeException("SNI server name '" +
|
||||
sniSN.getFirst() + "' must not be set.");
|
||||
}
|
||||
|
||||
if (conn.getResponseCode() == -1) {
|
||||
throw new RuntimeException("getResponseCode() returns -1");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
if (IPAddressUtil.isIPv6LiteralAddress(args[0]) && !IPSupport.hasIPv6()) {
|
||||
throw new SkippedException("Skipping test - IPv6 is not supported");
|
||||
}
|
||||
/*
|
||||
* Start the tests.
|
||||
*/
|
||||
new SubjectAltNameIP(args[0]);
|
||||
}
|
||||
|
||||
Thread serverThread = null;
|
||||
|
||||
/*
|
||||
* Primary constructor, used to drive remainder of the test.
|
||||
*
|
||||
* Fork off the other side, then do your work.
|
||||
*/
|
||||
SubjectAltNameIP(String host) throws Exception {
|
||||
hostName = host;
|
||||
startServer();
|
||||
doClientSide();
|
||||
|
||||
/*
|
||||
* Wait for other side to close down.
|
||||
*/
|
||||
serverThread.join();
|
||||
|
||||
if (serverException != null)
|
||||
throw serverException;
|
||||
}
|
||||
|
||||
void startServer() {
|
||||
serverThread = new Thread(() -> {
|
||||
try {
|
||||
doServerSide();
|
||||
} catch (Exception e) {
|
||||
/*
|
||||
* Our server thread just died.
|
||||
*
|
||||
* Store the exception and release the client.
|
||||
*/
|
||||
serverException = e;
|
||||
serverReady.countDown();
|
||||
}
|
||||
});
|
||||
serverThread.start();
|
||||
}
|
||||
|
||||
/*
|
||||
* Wraps SSLSocketImpl to simulate a different JSSE implementation
|
||||
*/
|
||||
private static SSLSocketFactory wrapSocketFactory(final SSLSocketFactory wrap, final Consumer<SSLSocket> store) {
|
||||
return new SSLSocketFactory() {
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return wrap.getDefaultCipherSuites();
|
||||
}
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return wrap.getSupportedCipherSuites();
|
||||
}
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose)
|
||||
throws IOException {
|
||||
final SSLSocket so =
|
||||
(SSLSocket) wrap.createSocket(s, host, port, autoClose);
|
||||
|
||||
// store the underlying SSLSocket for later use
|
||||
store.accept(so);
|
||||
|
||||
return new SSLSocket() {
|
||||
@Override
|
||||
public void connect(SocketAddress endpoint,
|
||||
int timeout) throws IOException {
|
||||
so.connect(endpoint, timeout);
|
||||
}
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return so.getSupportedCipherSuites();
|
||||
}
|
||||
@Override
|
||||
public String[] getEnabledCipherSuites() {
|
||||
return so.getEnabledCipherSuites();
|
||||
}
|
||||
@Override
|
||||
public void setEnabledCipherSuites(String[] suites) {
|
||||
so.setEnabledCipherSuites(suites);
|
||||
}
|
||||
@Override
|
||||
public String[] getSupportedProtocols() {
|
||||
return so.getSupportedProtocols();
|
||||
}
|
||||
@Override
|
||||
public String[] getEnabledProtocols() {
|
||||
return so.getEnabledProtocols();
|
||||
}
|
||||
@Override
|
||||
public void setEnabledProtocols(String[] protocols) {
|
||||
so.setEnabledProtocols(protocols);
|
||||
}
|
||||
@Override
|
||||
public SSLSession getSession() {
|
||||
return so.getSession();
|
||||
}
|
||||
@Override
|
||||
public SSLSession getHandshakeSession() {
|
||||
return so.getHandshakeSession();
|
||||
}
|
||||
@Override
|
||||
public void addHandshakeCompletedListener(HandshakeCompletedListener listener) {
|
||||
so.addHandshakeCompletedListener(listener);
|
||||
}
|
||||
@Override
|
||||
public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) {
|
||||
so.removeHandshakeCompletedListener(listener);
|
||||
}
|
||||
@Override
|
||||
public void startHandshake() throws IOException {
|
||||
so.startHandshake();
|
||||
}
|
||||
@Override
|
||||
public void setUseClientMode(boolean mode) {
|
||||
so.setUseClientMode(mode);
|
||||
}
|
||||
@Override
|
||||
public boolean getUseClientMode() {
|
||||
return so.getUseClientMode();
|
||||
}
|
||||
@Override
|
||||
public void setNeedClientAuth(boolean need) {
|
||||
}
|
||||
@Override
|
||||
public boolean getNeedClientAuth() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void setWantClientAuth(boolean want) {
|
||||
}
|
||||
@Override
|
||||
public boolean getWantClientAuth() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void setEnableSessionCreation(boolean flag) {
|
||||
so.setEnableSessionCreation(flag);
|
||||
}
|
||||
@Override
|
||||
public boolean getEnableSessionCreation() {
|
||||
return so.getEnableSessionCreation();
|
||||
}
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
so.close();
|
||||
}
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return so.isClosed();
|
||||
}
|
||||
@Override
|
||||
public void shutdownInput() throws IOException {
|
||||
so.shutdownInput();
|
||||
}
|
||||
@Override
|
||||
public boolean isInputShutdown() {
|
||||
return so.isInputShutdown();
|
||||
}
|
||||
@Override
|
||||
public void shutdownOutput() throws IOException {
|
||||
so.shutdownOutput();
|
||||
}
|
||||
@Override
|
||||
public boolean isOutputShutdown() {
|
||||
return so.isOutputShutdown();
|
||||
}
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return so.getInputStream();
|
||||
}
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
return so.getOutputStream();
|
||||
}
|
||||
@Override
|
||||
public SSLParameters getSSLParameters() {
|
||||
return so.getSSLParameters();
|
||||
}
|
||||
@Override
|
||||
public void setSSLParameters(SSLParameters params) {
|
||||
so.setSSLParameters(params);
|
||||
}
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public Socket createSocket(String h, int p) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public Socket createSocket(String h, int p, InetAddress ipa, int lp) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public Socket createSocket(InetAddress h, int p) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public Socket createSocket(InetAddress a, int p, InetAddress l, int lp) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8301580 8322159 8333107 8332230 8338678 8351260 8366196 8372336
|
||||
* @bug 8301580 8322159 8333107 8332230 8338678 8351260 8366196 8372336 8373094
|
||||
* @summary Verify error recovery w.r.t. Attr
|
||||
* @library /tools/lib
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
@ -32,8 +32,11 @@
|
||||
* @run main AttrRecovery
|
||||
*/
|
||||
|
||||
import com.sun.source.tree.IdentifierTree;
|
||||
import com.sun.source.tree.MemberReferenceTree;
|
||||
import com.sun.source.tree.MemberSelectTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import com.sun.source.util.TaskEvent;
|
||||
import com.sun.source.util.TaskListener;
|
||||
@ -41,11 +44,13 @@ import com.sun.source.util.TreePathScanner;
|
||||
import com.sun.source.util.Trees;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
@ -495,4 +500,155 @@ public class AttrRecovery extends TestRunner {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test //JDK-8373094
|
||||
public void testSensibleAttribution() throws Exception {
|
||||
Path curPath = Path.of(".");
|
||||
Path lib = curPath.resolve("lib");
|
||||
Path classes = lib.resolve("classes");
|
||||
Files.createDirectories(classes);
|
||||
new JavacTask(tb)
|
||||
.outdir(classes)
|
||||
.sources("""
|
||||
package test;
|
||||
public class Intermediate<T> extends Base<T> {}
|
||||
""",
|
||||
"""
|
||||
package test;
|
||||
public class Base<T> {
|
||||
public void t(Missing<T> m) {}
|
||||
}
|
||||
""",
|
||||
"""
|
||||
package test;
|
||||
public class Missing<T> {
|
||||
}
|
||||
""")
|
||||
.run()
|
||||
.writeAll();
|
||||
|
||||
Files.delete(classes.resolve("test").resolve("Missing.class"));
|
||||
|
||||
record TestCase(String code, List<String> options, String... expectedErrors) {}
|
||||
TestCase[] testCases = new TestCase[] {
|
||||
new TestCase("""
|
||||
package test;
|
||||
public class Test extends Intermediate<String> {
|
||||
private void test() {
|
||||
int i = 0;
|
||||
System.err.println(i);
|
||||
while (true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
""",
|
||||
List.of(),
|
||||
"Test.java:2:8: compiler.err.cant.access: test.Missing, (compiler.misc.class.file.not.found: test.Missing)",
|
||||
"1 error"),
|
||||
new TestCase("""
|
||||
package test;
|
||||
public class Test extends Intermediate<String> {
|
||||
private void test() {
|
||||
int i = 0;
|
||||
System.err.println(i);
|
||||
while (true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
""",
|
||||
List.of("-XDshould-stop.at=FLOW"),
|
||||
"Test.java:2:8: compiler.err.cant.access: test.Missing, (compiler.misc.class.file.not.found: test.Missing)",
|
||||
"1 error"),
|
||||
};
|
||||
|
||||
for (TestCase tc : testCases) {
|
||||
List<String> attributes = new ArrayList<>();
|
||||
List<String> actual = new JavacTask(tb)
|
||||
.options(Stream.concat(List.of("-XDrawDiagnostics", "-XDdev").stream(),
|
||||
tc.options.stream()).toList())
|
||||
.classpath(classes)
|
||||
.sources(tc.code())
|
||||
.outdir(curPath)
|
||||
.callback(task -> {
|
||||
task.addTaskListener(new TaskListener() {
|
||||
@Override
|
||||
public void finished(TaskEvent e) {
|
||||
if (e.getKind() != TaskEvent.Kind.ANALYZE) {
|
||||
return ;
|
||||
}
|
||||
Trees trees = Trees.instance(task);
|
||||
new TreePathScanner<Void, Void>() {
|
||||
boolean check;
|
||||
|
||||
@Override
|
||||
public Void visitMethod(MethodTree node, Void p) {
|
||||
if (node.getName().contentEquals("test")) {
|
||||
check = true;
|
||||
try {
|
||||
return super.visitMethod(node, p);
|
||||
} finally {
|
||||
check = false;
|
||||
}
|
||||
}
|
||||
|
||||
return super.visitMethod(node, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
|
||||
if (!node.toString().contains("super")) {
|
||||
verifyElement();
|
||||
}
|
||||
return super.visitMethodInvocation(node, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitIdentifier(IdentifierTree node, Void p) {
|
||||
verifyElement();
|
||||
return super.visitIdentifier(node, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitMemberSelect(MemberSelectTree node, Void p) {
|
||||
verifyElement();
|
||||
return super.visitMemberSelect(node, p);
|
||||
}
|
||||
|
||||
private void verifyElement() {
|
||||
if (!check) {
|
||||
return ;
|
||||
}
|
||||
|
||||
Element el = trees.getElement(getCurrentPath());
|
||||
if (el == null) {
|
||||
error("Unattributed tree: " + getCurrentPath().getLeaf());
|
||||
} else {
|
||||
attributes.add(el.toString());
|
||||
}
|
||||
}
|
||||
}.scan(e.getCompilationUnit(), null);
|
||||
}
|
||||
});
|
||||
})
|
||||
.run(Expect.FAIL)
|
||||
.writeAll()
|
||||
.getOutputLines(OutputKind.DIRECT);
|
||||
|
||||
List<String> expectedErrors = List.of(tc.expectedErrors);
|
||||
|
||||
if (!Objects.equals(actual, expectedErrors)) {
|
||||
error("Expected: " + expectedErrors + ", but got: " + actual);
|
||||
}
|
||||
|
||||
List<String> expectedAttributes =
|
||||
List.of("println(int)", "println(int)", "err", "java.lang.System", "i");
|
||||
|
||||
if (!Objects.equals(attributes, expectedAttributes)) {
|
||||
error("Expected: " + expectedAttributes + ", but got: " + attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -44,12 +44,8 @@ public class ClassComparison {
|
||||
Class[] c2;
|
||||
int[] res;
|
||||
long[] resLong;
|
||||
Object[] resObject;
|
||||
Object ro1;
|
||||
Object ro2;
|
||||
Object[] resClass;
|
||||
Class rc1;
|
||||
Class rc2;
|
||||
float[] resFloat;
|
||||
double[] resDouble;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
@ -58,12 +54,8 @@ public class ClassComparison {
|
||||
c2 = new Class[INVOCATIONS];
|
||||
res = new int[INVOCATIONS];
|
||||
resLong = new long[INVOCATIONS];
|
||||
resObject = new Object[INVOCATIONS];
|
||||
ro1 = new Object();
|
||||
ro2 = new Object();
|
||||
resClass = new Class[INVOCATIONS];
|
||||
rc1 = Float.class;
|
||||
rc2 = Double.class;
|
||||
resFloat = new float[INVOCATIONS];
|
||||
resDouble = new double[INVOCATIONS];
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
c1[i] = random.nextBoolean() ? Float.class : Double.class;
|
||||
}
|
||||
@ -86,6 +78,7 @@ public class ClassComparison {
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void equalClassResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = (c1[i] == c2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
@ -98,4 +91,32 @@ public class ClassComparison {
|
||||
resLong[i] = (c1[i] != c2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void equalClassResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (c1[i] == c2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualClassResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (c1[i] != c2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void equalClassResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (c1[i] == c2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualClassResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (c1[i] != c2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,34 +37,18 @@ import java.util.random.RandomGenerator;
|
||||
public class FPComparison {
|
||||
static final int INVOCATIONS = 1024;
|
||||
|
||||
float[] f1;
|
||||
double[] d1;
|
||||
float[] f2;
|
||||
double[] d2;
|
||||
int[] res;
|
||||
long[] resLong;
|
||||
Object[] resObject;
|
||||
Object ro1;
|
||||
Object ro2;
|
||||
Class[] resClass;
|
||||
Class rc1;
|
||||
Class rc2;
|
||||
static final float[] f1 = new float[INVOCATIONS];
|
||||
static final double[] d1 = new double[INVOCATIONS];
|
||||
static final float[] f2 = new float[INVOCATIONS];
|
||||
static final double[] d2 = new double[INVOCATIONS];
|
||||
static final int[] res = new int[INVOCATIONS];;
|
||||
static final long[] resLong = new long[INVOCATIONS];
|
||||
static final float[] resFloat = new float[INVOCATIONS];
|
||||
static final double[] resDouble = new double[INVOCATIONS];
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
var random = RandomGenerator.getDefault();
|
||||
f1 = new float[INVOCATIONS];
|
||||
d1 = new double[INVOCATIONS];
|
||||
f2 = new float[INVOCATIONS];
|
||||
d2 = new double[INVOCATIONS];
|
||||
res = new int[INVOCATIONS];
|
||||
resLong = new long[INVOCATIONS];
|
||||
resObject = new Object[INVOCATIONS];
|
||||
ro1 = new Object();
|
||||
ro2 = new Object();
|
||||
resClass = new Class[INVOCATIONS];
|
||||
rc1 = Float.class;
|
||||
rc2 = Double.class;
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
int type = random.nextInt(5);
|
||||
if (type == 1) {
|
||||
@ -274,4 +258,148 @@ public class FPComparison {
|
||||
resLong[i] = (d1[i] >= d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: float ---------
|
||||
|
||||
@Benchmark
|
||||
public void equalFloatResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (f1[i] == f2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void equalDoubleResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (d1[i] == d2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessFloatResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (f1[i] < f2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessDoubleResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (d1[i] < d2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualFloatResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (f1[i] <= f2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualDoubleResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (d1[i] <= d2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterFloatResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (f1[i] > f2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterDoubleResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (d1[i] > d2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualFloatResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (f1[i] >= f2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualDoubleResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (d1[i] >= d2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: double ---------
|
||||
|
||||
@Benchmark
|
||||
public void equalFloatResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (f1[i] == f2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void equalDoubleResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (d1[i] == d2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessFloatResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (f1[i] < f2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessDoubleResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (d1[i] < d2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualFloatResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (f1[i] <= f2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualDoubleResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (d1[i] <= d2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterFloatResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (f1[i] > f2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterDoubleResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (d1[i] > d2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualFloatResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (f1[i] >= f2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualDoubleResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (d1[i] >= d2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,12 +42,8 @@ public class IntegerComparison {
|
||||
int[] i2;
|
||||
int[] res;
|
||||
long[] resLong;
|
||||
Object[] resObject;
|
||||
Object ro1;
|
||||
Object ro2;
|
||||
Object[] resClass;
|
||||
Class rc1;
|
||||
Class rc2;
|
||||
float[] resFloat;
|
||||
double[] resDouble;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
@ -56,18 +52,17 @@ public class IntegerComparison {
|
||||
i2 = new int[INVOCATIONS];
|
||||
res = new int[INVOCATIONS];
|
||||
resLong = new long[INVOCATIONS];
|
||||
resObject = new Object[INVOCATIONS];
|
||||
ro1 = new Object();
|
||||
ro2 = new Object();
|
||||
resClass = new Class[INVOCATIONS];
|
||||
rc1 = Float.class;
|
||||
rc2 = Double.class;
|
||||
resFloat = new float[INVOCATIONS];
|
||||
resDouble = new double[INVOCATIONS];
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
i1[i] = random.nextInt(INVOCATIONS);
|
||||
i2[i] = random.nextInt(INVOCATIONS);
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: int ---------
|
||||
// Signed comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalInteger() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
@ -110,8 +105,55 @@ public class IntegerComparison {
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: long ---------
|
||||
// Unsigned comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalIntegerUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Integer.compareUnsigned(i1[i], i2[i]) == 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualIntegerUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Integer.compareUnsigned(i1[i], i2[i]) != 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessIntegerUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Integer.compareUnsigned(i1[i], i2[i]) < 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualIntegerUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Integer.compareUnsigned(i1[i], i2[i]) <= 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterIntegerUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Integer.compareUnsigned(i1[i], i2[i]) > 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualIntegerUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Integer.compareUnsigned(i1[i], i2[i]) >= 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --------- result: long ---------
|
||||
// Signed comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalIntegerResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = (i1[i] == i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
@ -125,6 +167,7 @@ public class IntegerComparison {
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessIntegerResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = (i1[i] < i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
@ -138,6 +181,7 @@ public class IntegerComparison {
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterIntegerResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = (i1[i] > i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
@ -150,4 +194,226 @@ public class IntegerComparison {
|
||||
resLong[i] = (i1[i] >= i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Unsigned comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalIntegerUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) == 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualIntegerUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) != 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessIntegerUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) < 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualIntegerUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) <= 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterIntegerUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) > 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualIntegerUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) >= 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: float ---------
|
||||
// Signed comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalIntegerResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (i1[i] == i2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualIntegerResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (i1[i] != i2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessIntegerResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (i1[i] < i2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualIntegerResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (i1[i] <= i2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterIntegerResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (i1[i] > i2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualIntegerResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (i1[i] >= i2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
// Unsigned comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalIntegerUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) == 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualIntegerUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) != 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessIntegerUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) < 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualIntegerUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) <= 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterIntegerUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) > 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualIntegerUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) >= 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: double ---------
|
||||
// Signed comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalIntegerResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (i1[i] == i2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualIntegerResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (i1[i] != i2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessIntegerResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (i1[i] < i2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualIntegerResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (i1[i] <= i2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterIntegerResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (i1[i] > i2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualIntegerResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (i1[i] >= i2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
// Unsigned comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalIntegerUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) == 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualIntegerUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) != 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessIntegerUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) < 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualIntegerUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) <= 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterIntegerUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) > 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualIntegerUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) >= 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,12 +41,8 @@ public class LongComparison {
|
||||
long[] l2;
|
||||
int[] res;
|
||||
long[] resLong;
|
||||
Object[] resObject;
|
||||
Object ro1;
|
||||
Object ro2;
|
||||
Object[] resClass;
|
||||
Class rc1;
|
||||
Class rc2;
|
||||
float[] resFloat;
|
||||
double[] resDouble;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
@ -55,18 +51,17 @@ public class LongComparison {
|
||||
l2 = new long[INVOCATIONS];
|
||||
res = new int[INVOCATIONS];
|
||||
resLong = new long[INVOCATIONS];
|
||||
resObject = new Object[INVOCATIONS];
|
||||
ro1 = new Object();
|
||||
ro2 = new Object();
|
||||
resClass = new Class[INVOCATIONS];
|
||||
rc1 = Float.class;
|
||||
rc2 = Double.class;
|
||||
resFloat = new float[INVOCATIONS];
|
||||
resDouble = new double[INVOCATIONS];
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
l1[i] = random.nextLong(INVOCATIONS);
|
||||
l2[i] = random.nextLong(INVOCATIONS);
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: int ---------
|
||||
// Signed comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
@ -109,8 +104,54 @@ public class LongComparison {
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: long ---------
|
||||
// Unsigned comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalLongUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Long.compareUnsigned(l1[i], l2[i]) == 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualLongUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Long.compareUnsigned(l1[i], l2[i]) != 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessLongUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Long.compareUnsigned(l1[i], l2[i]) < 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualLongUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Long.compareUnsigned(l1[i], l2[i]) <= 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterLongUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Long.compareUnsigned(l1[i], l2[i]) > 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualLongUnsigned() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
res[i] = Long.compareUnsigned(l1[i], l2[i]) >= 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: long ---------
|
||||
// Signed comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalLongResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = (l1[i] == l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
@ -124,6 +165,7 @@ public class LongComparison {
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessLongResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = (l1[i] < l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
@ -137,6 +179,7 @@ public class LongComparison {
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterLongResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = (l1[i] > l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
@ -149,4 +192,226 @@ public class LongComparison {
|
||||
resLong[i] = (l1[i] >= l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Unsigned comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalLongUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Long.compareUnsigned(l1[i], l2[i]) == 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualLongUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Long.compareUnsigned(l1[i], l2[i]) != 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessLongUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Long.compareUnsigned(l1[i], l2[i]) < 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualLongUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Long.compareUnsigned(l1[i], l2[i]) <= 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterLongUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Long.compareUnsigned(l1[i], l2[i]) > 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualLongUnsignedResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = Long.compareUnsigned(l1[i], l2[i]) >= 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: float ---------
|
||||
// Signed comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalLongResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (l1[i] == l2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualLongResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (l1[i] != l2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessLongResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (l1[i] < l2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualLongResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (l1[i] <= l2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterLongResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (l1[i] > l2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualLongResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (l1[i] >= l2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
// Unsigned comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalLongUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) == 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualLongUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) != 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessLongUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) < 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualLongUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) <= 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterLongUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) > 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualLongUnsignedResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) >= 0 ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
// --------- result: double ---------
|
||||
// Signed comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalLongResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (l1[i] == l2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualLongResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (l1[i] != l2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessLongResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (l1[i] < l2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualLongResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (l1[i] <= l2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterLongResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (l1[i] > l2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualLongResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (l1[i] >= l2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
// Unsigned comparison
|
||||
|
||||
@Benchmark
|
||||
public void equalLongUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) == 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualLongUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) != 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessLongUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) < 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lessEqualLongUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) <= 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterLongUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) > 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void greaterEqualLongUnsignedResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) >= 0 ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,12 +44,8 @@ public class PointerComparison {
|
||||
Object[] o2;
|
||||
int[] res;
|
||||
long[] resLong;
|
||||
Object[] resObject;
|
||||
Object ro1;
|
||||
Object ro2;
|
||||
Object[] resClass;
|
||||
Class rc1;
|
||||
Class rc2;
|
||||
float[] resFloat;
|
||||
double[] resDouble;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
@ -58,12 +54,8 @@ public class PointerComparison {
|
||||
o2 = new Object[INVOCATIONS];
|
||||
res = new int[INVOCATIONS];
|
||||
resLong = new long[INVOCATIONS];
|
||||
resObject = new Object[INVOCATIONS];
|
||||
ro1 = new Object();
|
||||
ro2 = new Object();
|
||||
resClass = new Class[INVOCATIONS];
|
||||
rc1 = Float.class;
|
||||
rc2 = Double.class;
|
||||
resFloat = new float[INVOCATIONS];
|
||||
resDouble = new double[INVOCATIONS];
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
o1[i] = new Object();
|
||||
}
|
||||
@ -86,6 +78,7 @@ public class PointerComparison {
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void equalObjectResLong() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resLong[i] = (o1[i] == o2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
@ -98,4 +91,32 @@ public class PointerComparison {
|
||||
resLong[i] = (o1[i] != o2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void equalObjecResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (o1[i] == o2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualObjecResFloat() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resFloat[i] = (o1[i] != o2[i]) ? 0.1f : 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void equalObjecResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (o1[i] == o2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void notEqualObjecResDouble() {
|
||||
for (int i = 0; i < INVOCATIONS; i++) {
|
||||
resDouble[i] = (o1[i] != o2[i]) ? 0.1 : 0.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Alibaba Group Holding Limited. 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.
|
||||
*/
|
||||
|
||||
package org.openjdk.bench.vm.compiler;
|
||||
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@Fork(value = 3)
|
||||
@Warmup(iterations = 10, time = 1)
|
||||
@Measurement(iterations = 5, time = 1)
|
||||
@State(Scope.Thread)
|
||||
public class CountLeadingZeros {
|
||||
private long[] longArray = new long[1000];
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
for (int i = 0; i < longArray.length; i++) {
|
||||
longArray[i] = ThreadLocalRandom.current().nextLong();
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int benchNumberOfNibbles() {
|
||||
int sum = 0;
|
||||
for (long l : longArray) {
|
||||
sum += numberOfNibbles((int) l);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public static int numberOfNibbles(int i) {
|
||||
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(i);
|
||||
return Math.max((mag + 3) / 4, 1);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int benchClzLongConstrained() {
|
||||
int sum = 0;
|
||||
for (long l : longArray) {
|
||||
sum += clzLongConstrained(l);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public static int clzLongConstrained(long param) {
|
||||
long constrainedParam = Math.min(175, Math.max(param, 160));
|
||||
return Long.numberOfLeadingZeros(constrainedParam);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user