diff --git a/src/hotspot/cpu/aarch64/aarch64_atomic.ad b/src/hotspot/cpu/aarch64/aarch64_atomic.ad index 3b05a637215..13fbe781518 100644 --- a/src/hotspot/cpu/aarch64/aarch64_atomic.ad +++ b/src/hotspot/cpu/aarch64/aarch64_atomic.ad @@ -43,8 +43,7 @@ instruct compareAndExchangeB(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::byte, /*acquire*/ false, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::byte, memory_order_release, $res$$Register); __ sxtbw($res$$Register, $res$$Register); %} ins_pipe(pipe_slow); @@ -59,8 +58,7 @@ instruct compareAndExchangeS(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::halfword, /*acquire*/ false, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::halfword, memory_order_release, $res$$Register); __ sxthw($res$$Register, $res$$Register); %} ins_pipe(pipe_slow); @@ -75,8 +73,7 @@ instruct compareAndExchangeI(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ false, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::word, memory_order_release, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -90,8 +87,7 @@ instruct compareAndExchangeL(iRegLNoSp res, indirect mem, iRegL oldval, iRegL ne %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ false, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::xword, memory_order_release, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -106,8 +102,7 @@ instruct compareAndExchangeN(iRegNNoSp res, indirect mem, iRegN oldval, iRegN ne %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ false, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::word, memory_order_release, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -122,8 +117,7 @@ instruct compareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP ne %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ false, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::xword, memory_order_release, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -138,8 +132,7 @@ instruct compareAndExchangeBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::byte, /*acquire*/ true, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::byte, memory_order_seq_cst, $res$$Register); __ sxtbw($res$$Register, $res$$Register); %} ins_pipe(pipe_slow); @@ -155,8 +148,7 @@ instruct compareAndExchangeSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::halfword, /*acquire*/ true, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::halfword, memory_order_seq_cst, $res$$Register); __ sxthw($res$$Register, $res$$Register); %} ins_pipe(pipe_slow); @@ -172,8 +164,7 @@ instruct compareAndExchangeIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ true, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::word, memory_order_seq_cst, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -188,8 +179,7 @@ instruct compareAndExchangeLAcq(iRegLNoSp res, indirect mem, iRegL oldval, iRegL %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ true, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::xword, memory_order_seq_cst, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -204,8 +194,7 @@ instruct compareAndExchangeNAcq(iRegNNoSp res, indirect mem, iRegN oldval, iRegN %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ true, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::word, memory_order_seq_cst, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -220,8 +209,7 @@ instruct compareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ true, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::xword, memory_order_seq_cst, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -235,9 +223,7 @@ instruct compareAndSwapB(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::byte, /*acquire*/ false, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::byte, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -252,9 +238,7 @@ instruct compareAndSwapS(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::halfword, /*acquire*/ false, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::halfword, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -269,9 +253,7 @@ instruct compareAndSwapI(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ false, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -286,9 +268,7 @@ instruct compareAndSwapL(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ false, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -304,9 +284,7 @@ instruct compareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ false, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -322,9 +300,7 @@ instruct compareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ false, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -340,9 +316,7 @@ instruct compareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI new "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::byte, /*acquire*/ true, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::byte, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -358,9 +332,7 @@ instruct compareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI new "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::halfword, /*acquire*/ true, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::halfword, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -376,9 +348,7 @@ instruct compareAndSwapIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI new "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ true, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -394,9 +364,7 @@ instruct compareAndSwapLAcq(iRegINoSp res, indirect mem, iRegL oldval, iRegL new "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ true, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -412,9 +380,7 @@ instruct compareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN oldval, iRegN new "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ true, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -430,9 +396,7 @@ instruct compareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP new "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ true, /*release*/ true, - /*weak*/ false, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -447,9 +411,7 @@ instruct weakCompareAndSwapB(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::byte, /*acquire*/ false, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::byte, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -464,9 +426,7 @@ instruct weakCompareAndSwapS(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::halfword, /*acquire*/ false, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::halfword, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -481,9 +441,7 @@ instruct weakCompareAndSwapI(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ false, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -498,9 +456,7 @@ instruct weakCompareAndSwapL(iRegINoSp res, indirect mem, iRegL oldval, iRegL ne "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ false, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -516,9 +472,7 @@ instruct weakCompareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN ne "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ false, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -534,9 +488,7 @@ instruct weakCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP ne "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ false, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_release); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -552,9 +504,7 @@ instruct weakCompareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::byte, /*acquire*/ true, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::byte, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -570,9 +520,7 @@ instruct weakCompareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::halfword, /*acquire*/ true, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::halfword, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -588,9 +536,7 @@ instruct weakCompareAndSwapIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ true, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -606,9 +552,7 @@ instruct weakCompareAndSwapLAcq(iRegINoSp res, indirect mem, iRegL oldval, iRegL "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ true, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -624,9 +568,7 @@ instruct weakCompareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN oldval, iRegN "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::word, /*acquire*/ true, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -642,9 +584,7 @@ instruct weakCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::xword, /*acquire*/ true, /*release*/ true, - /*weak*/ true, noreg); + __ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_seq_cst); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); diff --git a/src/hotspot/cpu/aarch64/aarch64_atomic_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_atomic_ad.m4 index dc51754e7f9..d6b3abd1e6f 100644 --- a/src/hotspot/cpu/aarch64/aarch64_atomic_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_atomic_ad.m4 @@ -53,8 +53,7 @@ ifelse($7,Acq,INDENT(predicate(needs_acquiring_load_exclusive(n));),`dnl') %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::$4, /*acquire*/ ifelse($7,Acq,true,false), /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::$4, ifelse($7,Acq,memory_order_seq_cst,memory_order_release), $res$$Register); __ $6($res$$Register, $res$$Register); %} ins_pipe(pipe_slow); @@ -76,8 +75,7 @@ ifelse($1$6,PAcq,INDENT(predicate(needs_acquiring_load_exclusive(n) && (n->as_Lo %} ins_encode %{ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::$4, /*acquire*/ ifelse($6,Acq,true,false), /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::$4, ifelse($6,Acq,memory_order_seq_cst,memory_order_release), $res$$Register); %} ins_pipe(pipe_slow); %}')dnl @@ -112,9 +110,7 @@ ifelse($6,Acq,INDENT(predicate(needs_acquiring_load_exclusive(n));),`dnl') "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::$4, /*acquire*/ ifelse($6,Acq,true,false), /*release*/ true, - /*weak*/ ifelse($7,Weak,true,false), noreg); + __ ifelse($7,Weak,cmpxchg_weak,cmpxchg)($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::$4, ifelse($6,Acq,memory_order_seq_cst,memory_order_release)); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -137,9 +133,7 @@ ifelse($1$6,PAcq,INDENT(predicate(needs_acquiring_load_exclusive(n) && (n->as_Lo "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" %} ins_encode %{ - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, - Assembler::$4, /*acquire*/ ifelse($6,Acq,true,false), /*release*/ true, - /*weak*/ ifelse($7,Weak,true,false), noreg); + __ ifelse($7,Weak,cmpxchg_weak,cmpxchg)($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::$4, ifelse($6,Acq,memory_order_seq_cst,memory_order_release)); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index 87451b5a07a..202f3227e2d 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -1492,12 +1492,12 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { } void LIR_Assembler::casw(Register addr, Register newval, Register cmpval) { - __ cmpxchg(addr, cmpval, newval, Assembler::word, /* acquire*/ true, /* release*/ true, /* weak*/ false, rscratch1); + __ cmpxchg(addr, cmpval, newval, Assembler::word, memory_order_seq_cst, rscratch1); __ cset(rscratch1, Assembler::NE); } void LIR_Assembler::casl(Register addr, Register newval, Register cmpval) { - __ cmpxchg(addr, cmpval, newval, Assembler::xword, /* acquire*/ true, /* release*/ true, /* weak*/ false, rscratch1); + __ cmpxchg(addr, cmpval, newval, Assembler::xword, memory_order_seq_cst, rscratch1); __ cset(rscratch1, Assembler::NE); } diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index cb9e308197e..e46a338e649 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -204,8 +204,7 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register t1, // Try to lock. Transition lock-bits 0b01 => 0b00 orr(t1_mark, t1_mark, markWord::unlocked_value); eor(t3_t, t1_mark, markWord::unlocked_value); - cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword, - /*acquire*/ true, /*release*/ false, /*weak*/ false, noreg); + cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword, memory_order_acquire); br(Assembler::NE, slow_path); bind(push); @@ -285,8 +284,7 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register t1, // Try to CAS owner (no owner => current thread's _monitor_owner_id). ldr(rscratch2, Address(rthread, JavaThread::monitor_owner_id_offset())); - cmpxchg(t2_owner_addr, zr, rscratch2, Assembler::xword, /*acquire*/ true, - /*release*/ false, /*weak*/ false, t3_owner); + cmpxchg(t2_owner_addr, zr, rscratch2, Assembler::xword, memory_order_acquire, t3_owner); br(Assembler::EQ, monitor_locked); // Check if recursive. @@ -371,8 +369,7 @@ void C2_MacroAssembler::fast_unlock(Register obj, Register box, Register t1, // Try to unlock. Transition lock bits 0b00 => 0b01 assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea"); orr(t3_t, t1_mark, markWord::unlocked_value); - cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword, - /*acquire*/ false, /*release*/ true, /*weak*/ false, noreg); + cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword, memory_order_release); br(Assembler::EQ, unlocked); bind(push_and_slow_path); diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.hpp index 231710df7d7..ac4740645b8 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -66,7 +66,6 @@ public: enum { - pc_return_offset = 0, // All frames link_offset = 0, return_addr_offset = 1, diff --git a/src/hotspot/cpu/aarch64/gc/g1/g1_aarch64.ad b/src/hotspot/cpu/aarch64/gc/g1/g1_aarch64.ad index 18fc27a4af4..375a0a89760 100644 --- a/src/hotspot/cpu/aarch64/gc/g1/g1_aarch64.ad +++ b/src/hotspot/cpu/aarch64/gc/g1/g1_aarch64.ad @@ -283,7 +283,7 @@ instruct g1CompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, - false /* acquire */, true /* release */, false /* weak */, $res$$Register); + memory_order_release, $res$$Register); write_barrier_post(masm, this, $mem$$Register /* store_addr */, $newval$$Register /* new_val */, @@ -316,7 +316,7 @@ instruct g1CompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRe RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, - true /* acquire */, true /* release */, false /* weak */, $res$$Register); + memory_order_seq_cst, $res$$Register); write_barrier_post(masm, this, $mem$$Register /* store_addr */, $newval$$Register /* new_val */, @@ -346,7 +346,7 @@ instruct g1CompareAndExchangeN(iRegNNoSp res, indirect mem, iRegN oldval, iRegN RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, - false /* acquire */, true /* release */, false /* weak */, $res$$Register); + memory_order_release, $res$$Register); __ decode_heap_oop($tmp1$$Register, $newval$$Register); write_barrier_post(masm, this, $mem$$Register /* store_addr */, @@ -377,7 +377,7 @@ instruct g1CompareAndExchangeNAcq(iRegNNoSp res, indirect mem, iRegN oldval, iRe RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, - true /* acquire */, true /* release */, false /* weak */, $res$$Register); + memory_order_seq_cst, $res$$Register); __ decode_heap_oop($tmp1$$Register, $newval$$Register); write_barrier_post(masm, this, $mem$$Register /* store_addr */, @@ -409,8 +409,7 @@ instruct g1CompareAndSwapP(iRegINoSp res, indirect mem, iRegP newval, iRegPNoSp $tmp2$$Register /* tmp2 */, RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, - false /* acquire */, true /* release */, false /* weak */, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_release); __ cset($res$$Register, Assembler::EQ); write_barrier_post(masm, this, $mem$$Register /* store_addr */, @@ -442,8 +441,7 @@ instruct g1CompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP newval, iRegPNo $tmp2$$Register /* tmp2 */, RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, - true /* acquire */, true /* release */, false /* weak */, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_seq_cst); __ cset($res$$Register, Assembler::EQ); write_barrier_post(masm, this, $mem$$Register /* store_addr */, @@ -475,8 +473,7 @@ instruct g1CompareAndSwapN(iRegINoSp res, indirect mem, iRegN newval, iRegPNoSp $tmp3$$Register /* tmp2 */, RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, - false /* acquire */, true /* release */, false /* weak */, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_release); __ cset($res$$Register, Assembler::EQ); __ decode_heap_oop($tmp1$$Register, $newval$$Register); write_barrier_post(masm, this, @@ -509,8 +506,7 @@ instruct g1CompareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN newval, iRegPNo $tmp3$$Register /* tmp2 */, RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, - true /* acquire */, true /* release */, false /* weak */, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_seq_cst); __ cset($res$$Register, Assembler::EQ); __ decode_heap_oop($tmp1$$Register, $newval$$Register); write_barrier_post(masm, this, diff --git a/src/hotspot/cpu/aarch64/gc/g1/g1_aarch64.m4 b/src/hotspot/cpu/aarch64/gc/g1/g1_aarch64.m4 index 8fb1f7e8e42..63b464ceb8c 100644 --- a/src/hotspot/cpu/aarch64/gc/g1/g1_aarch64.m4 +++ b/src/hotspot/cpu/aarch64/gc/g1/g1_aarch64.m4 @@ -151,7 +151,7 @@ instruct g1CompareAndExchangeP$1(iRegPNoSp res, indirect mem, iRegP oldval, iReg RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, - $3 /* acquire */, true /* release */, false /* weak */, $res$$Register); + ifelse($1,Acq,memory_order_seq_cst,memory_order_release), $res$$Register); write_barrier_post(masm, this, $mem$$Register /* store_addr */, $newval$$Register /* new_val */, @@ -160,8 +160,8 @@ instruct g1CompareAndExchangeP$1(iRegPNoSp res, indirect mem, iRegP oldval, iReg %} ins_pipe(pipe_slow); %}')dnl -CAEP_INSN(,,false) -CAEP_INSN(Acq,_acq,true) +CAEP_INSN(,) +CAEP_INSN(Acq,_acq) dnl define(`CAEN_INSN', ` @@ -185,7 +185,7 @@ instruct g1CompareAndExchangeN$1(iRegNNoSp res, indirect mem, iRegN oldval, iReg RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, - $3 /* acquire */, true /* release */, false /* weak */, $res$$Register); + ifelse($1,Acq,memory_order_seq_cst,memory_order_release), $res$$Register); __ decode_heap_oop($tmp1$$Register, $newval$$Register); write_barrier_post(masm, this, $mem$$Register /* store_addr */, @@ -195,8 +195,8 @@ instruct g1CompareAndExchangeN$1(iRegNNoSp res, indirect mem, iRegN oldval, iReg %} ins_pipe(pipe_slow); %}')dnl -CAEN_INSN(,,false) -CAEN_INSN(Acq,_acq,true) +CAEN_INSN(,) +CAEN_INSN(Acq,_acq) dnl define(`CASP_INSN', ` @@ -221,8 +221,7 @@ instruct g1CompareAndSwapP$1(iRegINoSp res, indirect mem, iRegP newval, iRegPNoS $tmp2$$Register /* tmp2 */, RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, - $3 /* acquire */, true /* release */, false /* weak */, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, ifelse($1,Acq,memory_order_seq_cst,memory_order_release)); __ cset($res$$Register, Assembler::EQ); write_barrier_post(masm, this, $mem$$Register /* store_addr */, @@ -232,8 +231,8 @@ instruct g1CompareAndSwapP$1(iRegINoSp res, indirect mem, iRegP newval, iRegPNoS %} ins_pipe(pipe_slow); %}')dnl -CASP_INSN(,,false) -CASP_INSN(Acq,_acq,true) +CASP_INSN(,) +CASP_INSN(Acq,_acq) dnl define(`CASN_INSN', ` @@ -258,8 +257,7 @@ instruct g1CompareAndSwapN$1(iRegINoSp res, indirect mem, iRegN newval, iRegPNoS $tmp3$$Register /* tmp2 */, RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */, RegSet::of($res$$Register) /* no_preserve */); - __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, - $3 /* acquire */, true /* release */, false /* weak */, noreg); + __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, ifelse($1,Acq,memory_order_seq_cst,memory_order_release)); __ cset($res$$Register, Assembler::EQ); __ decode_heap_oop($tmp1$$Register, $newval$$Register); write_barrier_post(masm, this, @@ -270,8 +268,8 @@ instruct g1CompareAndSwapN$1(iRegINoSp res, indirect mem, iRegN newval, iRegPNoS %} ins_pipe(pipe_slow); %}')dnl -CASN_INSN(,,false) -CASN_INSN(Acq,_acq,true) +CASN_INSN(,) +CASN_INSN(Acq,_acq) dnl define(`XCHGP_INSN', ` diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp index bc8af2354c8..7406aa0c1c4 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp @@ -597,8 +597,14 @@ void ShenandoahBarrierSetAssembler::compare_and_set_c2(const MachNode* node, Mac ShenandoahBarrierStubC2::load_store_pre(masm, node, addr, tmp1, tmp2, tmp3, narrow); + atomic_memory_order order = acquire ? memory_order_seq_cst : memory_order_release; + // CAS! - __ cmpxchg(addr, oldval, newval, op_size, acquire, /* release */ true, weak, exchange ? res : noreg); + if (weak) { + __ cmpxchg_weak(addr, oldval, newval, op_size, order, exchange ? res : noreg); + } else { + __ cmpxchg(addr, oldval, newval, op_size, order, exchange ? res : noreg); + } // If we need a boolean result out of CAS, set the flag appropriately and promote the result. if (!exchange) { diff --git a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp index 1eb96cdb6e7..7c320d835e7 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp @@ -283,10 +283,7 @@ void ZBarrierSetAssembler::store_barrier_medium(MacroAssembler* masm, // If we get this far, we know there is a young raw null value in the field. __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatStoreGoodBeforeMov); __ movzw(rtmp1, barrier_Relocation::unpatched); - __ cmpxchg(rtmp2, zr, rtmp1, - Assembler::xword, - false /* acquire */, false /* release */, true /* weak */, - rtmp3); + __ cmpxchg_weak(rtmp2, zr, rtmp1, Assembler::xword, memory_order_relaxed, rtmp3); __ br(Assembler::NE, slow_path); __ bind(slow_path_continuation); diff --git a/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad b/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad index ad2e9243823..74e0395c81e 100644 --- a/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad +++ b/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad @@ -207,8 +207,7 @@ instruct zCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newva Address ref_addr($mem$$Register); z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */); z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register); - __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, - false /* acquire */, true /* release */, false /* weak */, noreg); + __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, memory_order_release); __ cset($res$$Register, Assembler::EQ); %} @@ -231,8 +230,7 @@ instruct zCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP ne Address ref_addr($mem$$Register); z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */); z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register); - __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, - true /* acquire */, true /* release */, false /* weak */, noreg); + __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, memory_order_seq_cst); __ cset($res$$Register, Assembler::EQ); %} @@ -255,7 +253,7 @@ instruct zCompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP n z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */); z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register); __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, - false /* acquire */, true /* release */, false /* weak */, $res$$Register); + memory_order_release, $res$$Register); z_uncolor(masm, this, $res$$Register); %} @@ -278,7 +276,7 @@ instruct zCompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iReg z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */); z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register); __ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, - true /* acquire */, true /* release */, false /* weak */, $res$$Register); + memory_order_seq_cst, $res$$Register); z_uncolor(masm, this, $res$$Register); %} diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 1c052b67503..d5e220fd4a3 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -2231,8 +2231,7 @@ void MacroAssembler::profile_receiver_type(Register recv, Register mdp, int mdp_ // offset is no longer needed after the address is computed. lea(rscratch2, Address(mdp, offset)); - cmpxchg(/*addr*/ rscratch2, /*expected*/ zr, /*new*/ recv, Assembler::xword, - /*acquire*/ false, /*release*/ false, /*weak*/ true, noreg); + cmpxchg_weak(/*addr*/ rscratch2, /*expected*/ zr, /*new*/ recv, Assembler::xword, memory_order_relaxed); // CAS success means the slot now has the receiver we want. CAS failure means // something had claimed the slot concurrently: it can be the same receiver we want, @@ -3494,9 +3493,33 @@ void MacroAssembler::reinit_heapbase() void MacroAssembler::cmpxchg(Register addr, Register expected, Register new_val, enum operand_size size, - bool acquire, bool release, + enum atomic_memory_order order, bool weak, Register result) { + bool acquire, release; + + switch (order) { + case memory_order_relaxed: + acquire = false; + release = false; + break; + case memory_order_acquire: + acquire = true; + release = false; + break; + case memory_order_release: + acquire = false; + release = true; + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + acquire = true; + release = true; + break; + default: + ShouldNotReachHere(); + } + if (result == noreg) result = rscratch1; BLOCK_COMMENT("cmpxchg {"); if (UseLSE) { @@ -7180,8 +7203,7 @@ void MacroAssembler::fast_lock(Register basic_lock, Register obj, Register t1, R assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea"); orr(mark, mark, markWord::unlocked_value); eor(t, mark, markWord::unlocked_value); - cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::xword, - /*acquire*/ true, /*release*/ false, /*weak*/ false, noreg); + cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::xword, memory_order_acquire); br(Assembler::NE, slow); bind(push); @@ -7249,8 +7271,7 @@ void MacroAssembler::fast_unlock(Register obj, Register t1, Register t2, Registe // Try to unlock. Transition lock bits 0b00 => 0b01 assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea"); orr(t, mark, markWord::unlocked_value); - cmpxchg(obj, mark, t, Assembler::xword, - /*acquire*/ false, /*release*/ true, /*weak*/ false, noreg); + cmpxchg(obj, mark, t, Assembler::xword, memory_order_release); br(Assembler::EQ, unlocked); bind(push_and_slow); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 8f1e662765e..9c722cd297e 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -32,6 +32,7 @@ #include "metaprogramming/enableIf.hpp" #include "oops/compressedOops.hpp" #include "oops/compressedKlass.hpp" +#include "runtime/atomicAccess.hpp" #include "runtime/vm_version.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/powerOfTwo.hpp" @@ -1239,12 +1240,25 @@ public: str(rscratch1, adr); } +private: // A generic CAS; success or failure is in the EQ flag. // Clobbers rscratch1 void cmpxchg(Register addr, Register expected, Register new_val, - enum operand_size size, - bool acquire, bool release, bool weak, - Register result); + enum operand_size size, enum atomic_memory_order order, + bool weak, Register result); + +public: + void cmpxchg(Register addr, Register expected, Register new_val, + enum operand_size size, enum atomic_memory_order order, + Register result = noreg) { + cmpxchg(addr, expected, new_val, size, order, /* weak */ false, result); + } + + void cmpxchg_weak(Register addr, Register expected, Register new_val, + enum operand_size size, enum atomic_memory_order order, + Register result = noreg) { + cmpxchg(addr, expected, new_val, size, order, /* weak */ true, result); + } #ifdef ASSERT // Template short-hand support to clean-up after a failed call to trampoline diff --git a/src/hotspot/cpu/arm/frame_arm.hpp b/src/hotspot/cpu/arm/frame_arm.hpp index 026bd993981..2ef44414e1c 100644 --- a/src/hotspot/cpu/arm/frame_arm.hpp +++ b/src/hotspot/cpu/arm/frame_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, 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 @@ -27,7 +27,6 @@ public: enum { - pc_return_offset = 0, // All frames link_offset = 0, return_addr_offset = 1, diff --git a/src/hotspot/cpu/ppc/assembler_ppc.cpp b/src/hotspot/cpu/ppc/assembler_ppc.cpp index ab16fc437e9..406d0b446a4 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.cpp @@ -75,23 +75,46 @@ int Assembler::branch_destination(int inst, int pos) { return r; } -// Low-level andi-one-instruction-macro. -void Assembler::andi(Register a, Register s, const long ui16) { - if (is_power_of_2(((unsigned long) ui16)+1)) { +// Low-level andi-one-instruction-macro. May clobber CR0. +void Assembler::andi(Register a, Register s, julong int_or_long_const) { + // Instructions which don't set CR0 are preferred. + if (int_or_long_const == 0) { + // should not be handled as pow2minus1 + li(a, 0); + } else if (is_power_of_2(int_or_long_const + 1)) { // pow2minus1 - clrldi(a, s, 64 - log2i_exact((((unsigned long) ui16)+1))); - } else if (is_power_of_2((jlong) ui16)) { - // pow2 - rlwinm(a, s, 0, 31 - log2i_exact((jlong) ui16), 31 - log2i_exact((jlong) ui16)); - } else if (is_power_of_2((jlong)-ui16)) { - // negpow2 - clrrdi(a, s, log2i_exact((jlong)-ui16)); + clrldi(a, s, 64 - log2i_exact(int_or_long_const + 1)); + } else if (is_power_of_2(-int_or_long_const)) { + // negpow2 (includes (julong)min_jlong) + clrrdi(a, s, log2i_exact(-int_or_long_const)); + } else if (is_uimm((jlong)int_or_long_const, 32) && has_consecutive_ones(int_or_long_const)) { + // consecutive ones + rlwinm(a, s, 0, count_leading_zeros((uint32_t)int_or_long_const), + 31 - count_trailing_zeros((uint32_t)int_or_long_const)); + } else if (is_uimm((jlong)int_or_long_const, 16)) { + // side effect: clobbers CR0 + andi_(a, s, int_or_long_const); } else { - assert(is_uimm(ui16, 16), "must be 16-bit unsigned immediate"); - andi_(a, s, ui16); + assert(is_uimm((jlong)int_or_long_const, 32) && (int_or_long_const & 0xFFFF) == 0, + "not encodable: " UINT64_FORMAT_X, int_or_long_const); + // side effect: clobbers CR0 + andis_(a, s, int_or_long_const >> 16); } } +// Check if int_or_long_const is supported by Assembler::andi. +bool Assembler::andi_supports(julong int_or_long_const) { + // 16 bit always possible by andi_ (but other instructions are preferred) + if (is_uimm((jlong)int_or_long_const, 16)) return true; + + // special cases 32 bit: higher 16 bit and consecutive ones are supported + if (is_uimm((jlong)int_or_long_const, 32) && + ((int_or_long_const & 0xFFFF) == 0 || has_consecutive_ones(int_or_long_const))) return true; + + // special cases 64 bit: clrldi, clrrdi + return is_power_of_2(int_or_long_const + 1) || is_power_of_2(-int_or_long_const); +} + // RegisterOrConstant version. void Assembler::ld(Register d, RegisterOrConstant roc, Register s1) { if (roc.is_constant()) { diff --git a/src/hotspot/cpu/ppc/assembler_ppc.hpp b/src/hotspot/cpu/ppc/assembler_ppc.hpp index f62c93e466c..77c7f63cd06 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.hpp @@ -1048,6 +1048,13 @@ class Assembler : public AbstractAssembler { return (julong)x < maxplus1; } + // Test if x has exactly one consecutive range of one bits (e.g. 00111000) + static bool has_consecutive_ones(julong x) { + if (x == max_julong) return true; + if (x == 0) return false; + return is_power_of_2((x >> count_trailing_zeros(x)) + 1); + } + protected: // helpers @@ -1606,7 +1613,8 @@ class Assembler : public AbstractAssembler { inline void isel_0( Register d, ConditionRegister cr, Condition cc, Register b = noreg); // PPC 1, section 3.3.11, Fixed-Point Logical Instructions - void andi( Register a, Register s, long ui16); // optimized version + void andi( Register a, Register s, julong int_or_long_const); // optimized version, may clobber CR0 + static bool andi_supports(julong int_or_long_const); inline void andi_( Register a, Register s, int ui16); inline void andis_( Register a, Register s, int ui16); inline void ori( Register a, Register s, int ui16); diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index 78fae5c2677..1ec710aad29 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -1669,26 +1669,40 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr d = dest->as_register_lo(); l = left->as_register_lo(); } - long uimms = (unsigned long)uimm >> 16, - uimmss = (unsigned long)uimm >> 32; + long uimms = (unsigned long)uimm >> 16; switch (code) { case lir_logic_and: - if (uimmss != 0 || (uimms != 0 && (uimm & 0xFFFF) != 0) || is_power_of_2(uimm)) { - __ andi(d, l, uimm); // special cases - } else if (uimms != 0) { __ andis_(d, l, uimms); } - else { __ andi_(d, l, uimm); } + if (Assembler::andi_supports(uimm)) { + __ andi(d, l, uimm); // includes andis_ and special cases + } else { // for operands which are not generated by LIRGenerator::do_LogicOp + __ load_const_optimized(R0, uimm); + __ andr(d, l, R0); + } break; case lir_logic_or: - if (uimms != 0) { assert((uimm & 0xFFFF) == 0, "sanity"); __ oris(d, l, uimms); } - else { __ ori(d, l, uimm); } + if (Assembler::is_uimm(uimm, 16)) { + __ ori(d, l, uimm); + } else if ((uimm & 0xFFFF) == 0 && Assembler::is_uimm(uimms, 16)) { + __ oris(d, l, uimms); + } else { // for operands which are not generated by LIRGenerator::do_LogicOp + __ load_const_optimized(R0, uimm); + __ orr(d, l, R0); + } break; case lir_logic_xor: - if (uimm == -1) { __ nand(d, l, l); } // special case - else if (uimms != 0) { assert((uimm & 0xFFFF) == 0, "sanity"); __ xoris(d, l, uimms); } - else { __ xori(d, l, uimm); } + if (Assembler::is_uimm(uimm, 16)) { + __ xori(d, l, uimm); + } else if ((uimm & 0xFFFF) == 0 && Assembler::is_uimm(uimms, 16)) { + __ xoris(d, l, uimms); + } else if (uimm == -1) { + __ nand(d, l, l); // special case + } else { // for operands which are not generated by LIRGenerator::do_LogicOp + __ load_const_optimized(R0, uimm); + __ xorr(d, l, R0); + } break; default: ShouldNotReachHere(); diff --git a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp index a652a155f62..56c069053c6 100644 --- a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp @@ -578,18 +578,13 @@ inline bool can_handle_logic_op_as_uimm(ValueType *type, Bytecodes::Code bc) { Assembler::is_uimm((jlong)((julong)int_or_long_const >> 16), 16)) return true; // see Assembler::andi - if (bc == Bytecodes::_iand && - (is_power_of_2(int_or_long_const+1) || - is_power_of_2(int_or_long_const) || - is_power_of_2(-int_or_long_const))) return true; - if (bc == Bytecodes::_land && - (is_power_of_2((unsigned long)int_or_long_const+1) || - (Assembler::is_uimm(int_or_long_const, 32) && is_power_of_2(int_or_long_const)) || - (int_or_long_const != min_jlong && is_power_of_2(-int_or_long_const)))) return true; + if ((bc == Bytecodes::_iand || bc == Bytecodes::_land)) + return Assembler::andi_supports(int_or_long_const); // special case: xor -1 - if ((bc == Bytecodes::_ixor || bc == Bytecodes::_lxor) && - int_or_long_const == -1) return true; + if ((bc == Bytecodes::_ixor || bc == Bytecodes::_lxor)) + return (int_or_long_const == -1); + return false; } diff --git a/src/hotspot/cpu/ppc/frame_ppc.hpp b/src/hotspot/cpu/ppc/frame_ppc.hpp index 14743c7d75a..bf49bbb7e01 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.hpp +++ b/src/hotspot/cpu/ppc/frame_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2025 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -391,8 +391,6 @@ } enum { - // normal return address is 1 bundle past PC - pc_return_offset = 0, // size, in words, of frame metadata (e.g. pc and link) metadata_words = sizeof(java_abi) >> LogBytesPerWord, // size, in words, of metadata at frame bottom, i.e. it is not part of the diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index e7464feb4ab..896128f99cc 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -9155,61 +9155,14 @@ instruct andI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ ins_pipe(pipe_class_default); %} -// Left shifted Immediate And -instruct andI_reg_immIhi16(iRegIdst dst, iRegIsrc src1, immIhi16 src2, flagsRegCR0 cr0) %{ +instruct andI_reg_immI(iRegIdst dst, iRegIsrc src1, immI src2, flagsRegCR0 cr0) %{ match(Set dst (AndI src1 src2)); + predicate(Assembler::andi_supports((juint)(n->in(2)->get_int()))); effect(KILL cr0); - format %{ "ANDIS $dst, $src1, $src2.hi" %} - size(4); - ins_encode %{ - __ andis_($dst$$Register, $src1$$Register, (int)((unsigned short)(($src2$$constant & 0xFFFF0000) >> 16))); - %} - ins_pipe(pipe_class_default); -%} - -// Immediate And -instruct andI_reg_uimm16(iRegIdst dst, iRegIsrc src1, uimmI16 src2, flagsRegCR0 cr0) %{ - match(Set dst (AndI src1 src2)); - effect(KILL cr0); - format %{ "ANDI $dst, $src1, $src2" %} size(4); ins_encode %{ - // FIXME: avoid andi_ ? - __ andi_($dst$$Register, $src1$$Register, $src2$$constant); - %} - ins_pipe(pipe_class_default); -%} - -// Immediate And where the immediate is a negative power of 2. -instruct andI_reg_immInegpow2(iRegIdst dst, iRegIsrc src1, immInegpow2 src2) %{ - match(Set dst (AndI src1 src2)); - format %{ "ANDWI $dst, $src1, $src2" %} - size(4); - ins_encode %{ - __ clrrdi($dst$$Register, $src1$$Register, log2i_exact(-(juint)$src2$$constant)); - %} - ins_pipe(pipe_class_default); -%} - -instruct andI_reg_immIpow2minus1(iRegIdst dst, iRegIsrc src1, immIpow2minus1 src2) %{ - match(Set dst (AndI src1 src2)); - format %{ "ANDWI $dst, $src1, $src2" %} - size(4); - ins_encode %{ - __ clrldi($dst$$Register, $src1$$Register, 64 - log2i_exact((juint)$src2$$constant + 1u)); - %} - ins_pipe(pipe_class_default); -%} - -instruct andI_reg_immIpowerOf2(iRegIdst dst, iRegIsrc src1, immIpowerOf2 src2) %{ - match(Set dst (AndI src1 src2)); - predicate(UseRotateAndMaskInstructionsPPC64); - format %{ "ANDWI $dst, $src1, $src2" %} - size(4); - ins_encode %{ - int bitpos = 31 - log2i_exact((juint)$src2$$constant); - __ rlwinm($dst$$Register, $src1$$Register, 0, bitpos, bitpos); + __ andi($dst$$Register, $src1$$Register, (juint)$src2$$constant); // optimized version %} ins_pipe(pipe_class_default); %} @@ -9227,50 +9180,27 @@ instruct andL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ ins_pipe(pipe_class_default); %} -// Immediate And long -instruct andL_reg_uimm16(iRegLdst dst, iRegLsrc src1, uimmL16 src2, flagsRegCR0 cr0) %{ +instruct andL_reg_immL(iRegLdst dst, iRegLsrc src1, immL src2, flagsRegCR0 cr0) %{ match(Set dst (AndL src1 src2)); + predicate(Assembler::andi_supports(n->in(2)->get_long())); effect(KILL cr0); - format %{ "ANDI $dst, $src1, $src2 \t// long" %} size(4); ins_encode %{ - // FIXME: avoid andi_ ? - __ andi_($dst$$Register, $src1$$Register, $src2$$constant); - %} - ins_pipe(pipe_class_default); -%} - -// Immediate And Long where the immediate is a negative power of 2. -instruct andL_reg_immLnegpow2(iRegLdst dst, iRegLsrc src1, immLnegpow2 src2) %{ - match(Set dst (AndL src1 src2)); - format %{ "ANDDI $dst, $src1, $src2" %} - size(4); - ins_encode %{ - __ clrrdi($dst$$Register, $src1$$Register, log2i_exact(-(julong)$src2$$constant)); - %} - ins_pipe(pipe_class_default); -%} - -instruct andL_reg_immLpow2minus1(iRegLdst dst, iRegLsrc src1, immLpow2minus1 src2) %{ - match(Set dst (AndL src1 src2)); - format %{ "ANDDI $dst, $src1, $src2" %} - size(4); - ins_encode %{ - __ clrldi($dst$$Register, $src1$$Register, 64 - log2i_exact((julong)$src2$$constant + 1ull)); + __ andi($dst$$Register, $src1$$Register, $src2$$constant); // optimized version %} ins_pipe(pipe_class_default); %} // AndL + ConvL2I. -instruct convL2I_andL_reg_immLpow2minus1(iRegIdst dst, iRegLsrc src1, immLpow2minus1 src2) %{ +instruct convL2I_andL_reg_immL(iRegIdst dst, iRegLsrc src1, immL src2, flagsRegCR0 cr0) %{ match(Set dst (ConvL2I (AndL src1 src2))); - ins_cost(DEFAULT_COST); - - format %{ "ANDDI $dst, $src1, $src2 \t// long + l2i" %} + predicate(Assembler::andi_supports(n->in(1)->in(2)->get_long())); + effect(KILL cr0); + format %{ "ANDI $dst, $src1, $src2 \t// long + l2i" %} size(4); ins_encode %{ - __ clrldi($dst$$Register, $src1$$Register, 64 - log2i_exact((julong)$src2$$constant + 1ull)); + __ andi($dst$$Register, $src1$$Register, $src2$$constant); // optimized version %} ins_pipe(pipe_class_default); %} diff --git a/src/hotspot/cpu/riscv/frame_riscv.hpp b/src/hotspot/cpu/riscv/frame_riscv.hpp index ce5a8dde230..d5f04ee3ff7 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.hpp +++ b/src/hotspot/cpu/riscv/frame_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -103,8 +103,6 @@ public: enum { - pc_return_offset = 0, - // All frames link_offset = -2, return_addr_offset = -1, diff --git a/src/hotspot/cpu/s390/frame_s390.hpp b/src/hotspot/cpu/s390/frame_s390.hpp index bcdeec43e1a..664a49fdd21 100644 --- a/src/hotspot/cpu/s390/frame_s390.hpp +++ b/src/hotspot/cpu/s390/frame_s390.hpp @@ -542,14 +542,6 @@ unsigned long flags, int max_frames = 0); enum { - // This enum value specifies the offset from the pc remembered by - // call instructions to the location where control returns to - // after a normal return. Most architectures remember the return - // location directly, i.e. the offset is zero. This is the case - // for z/Architecture, too. - // - // Normal return address is the instruction following the branch. - pc_return_offset = 0, metadata_words = 0, metadata_words_at_bottom = 0, metadata_words_at_top = 0, diff --git a/src/hotspot/cpu/x86/frame_x86.hpp b/src/hotspot/cpu/x86/frame_x86.hpp index 546c40fffe4..d97e6b847b4 100644 --- a/src/hotspot/cpu/x86/frame_x86.hpp +++ b/src/hotspot/cpu/x86/frame_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, 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 @@ -54,7 +54,6 @@ public: enum { - pc_return_offset = 0, // All frames link_offset = 0, return_addr_offset = 1, diff --git a/src/hotspot/cpu/zero/frame_zero.hpp b/src/hotspot/cpu/zero/frame_zero.hpp index 19096615594..45d1cb82e82 100644 --- a/src/hotspot/cpu/zero/frame_zero.hpp +++ b/src/hotspot/cpu/zero/frame_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,7 +30,6 @@ public: enum { - pc_return_offset = 0, metadata_words = 0, // size, in words, of metadata at frame bottom, i.e. it is not part of the // caller/callee overlap diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 2b74cccb072..0fc636483f5 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -6387,7 +6387,7 @@ void os::jfr_report_memory_info() { // Send the RSS JFR event EventResidentSetSize event; event.set_size(pmex.WorkingSetSize); - event.set_peak(pmex.PeakWorkingSetSize); + event.set_peak(MAX2(pmex.PeakWorkingSetSize, pmex.WorkingSetSize)); event.commit(); } else { // Log a warning diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index f48df178ce6..3ede62e14cd 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -261,13 +261,16 @@ void RiscvHwprobe::add_features_from_query_result() { // ====== non-extensions ====== // - if (is_valid(RISCV_HWPROBE_KEY_MARCHID)) { + // For value-type keys, the kernel returns (uint64_t)-1 when CPUs in the + // query set disagree (different core types). Skip these as the value is + // not meaningful for the system as a whole. + if (is_valid(RISCV_HWPROBE_KEY_MARCHID) && query[RISCV_HWPROBE_KEY_MARCHID].value != (uint64_t)-1) { VM_Version::marchid.enable_feature(query[RISCV_HWPROBE_KEY_MARCHID].value); } - if (is_valid(RISCV_HWPROBE_KEY_MIMPID)) { + if (is_valid(RISCV_HWPROBE_KEY_MIMPID) && query[RISCV_HWPROBE_KEY_MIMPID].value != (uint64_t)-1) { VM_Version::mimpid.enable_feature(query[RISCV_HWPROBE_KEY_MIMPID].value); } - if (is_valid(RISCV_HWPROBE_KEY_MVENDORID)) { + if (is_valid(RISCV_HWPROBE_KEY_MVENDORID) && query[RISCV_HWPROBE_KEY_MVENDORID].value != (uint64_t)-1) { VM_Version::mvendorid.enable_feature(query[RISCV_HWPROBE_KEY_MVENDORID].value); } // RISCV_HWPROBE_KEY_CPUPERF_0 is deprecated and returns similar values diff --git a/src/hotspot/share/code/aotCodeCache.cpp b/src/hotspot/share/code/aotCodeCache.cpp index 7e1391ed0f0..b70f89b2645 100644 --- a/src/hotspot/share/code/aotCodeCache.cpp +++ b/src/hotspot/share/code/aotCodeCache.cpp @@ -2424,9 +2424,6 @@ int AOTCodeAddressTable::id_for_address(address addr, RelocIterator reloc, CodeB id = search_address(addr, _stubs_addr, _stubs_max); if (id == BAD_ADDRESS_ID) { StubCodeDesc* desc = StubCodeDesc::desc_for(addr); - if (desc == nullptr) { - desc = StubCodeDesc::desc_for(addr + frame::pc_return_offset); - } const char* sub_name = (desc != nullptr) ? desc->name() : ""; assert(false, "Address " INTPTR_FORMAT " for Stub:%s is missing in AOT Code Cache addresses table", p2i(addr), sub_name); } else { diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 27f01797d39..5d7df498102 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -3783,9 +3783,6 @@ const char* nmethod::reloc_string_for(u_char* begin, u_char* end) { address dest = r->destination(); if (StubRoutines::contains(dest)) { StubCodeDesc* desc = StubCodeDesc::desc_for(dest); - if (desc == nullptr) { - desc = StubCodeDesc::desc_for(dest + frame::pc_return_offset); - } if (desc != nullptr) { st.print(" Stub::%s", desc->name()); return st.as_string(); diff --git a/src/hotspot/share/code/oopRecorder.cpp b/src/hotspot/share/code/oopRecorder.cpp index c37651892cc..93c74be27b9 100644 --- a/src/hotspot/share/code/oopRecorder.cpp +++ b/src/hotspot/share/code/oopRecorder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, 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 @@ -302,9 +302,6 @@ void ExternalsRecorder::print_statistics() { if (addr != nullptr) { if (StubRoutines::contains(addr)) { StubCodeDesc* desc = StubCodeDesc::desc_for(addr); - if (desc == nullptr) { - desc = StubCodeDesc::desc_for(addr + frame::pc_return_offset); - } const char* stub_name = (desc != nullptr) ? desc->name() : ""; tty->print(" stub: %s", stub_name); } else { diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp index 73e4b6de7b4..5295dc0f287 100644 --- a/src/hotspot/share/code/relocInfo.cpp +++ b/src/hotspot/share/code/relocInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, 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 @@ -922,9 +922,6 @@ void RelocIterator::print_current_on(outputStream* st) { st->print(" | [destination=" INTPTR_FORMAT "]", p2i(dest)); if (StubRoutines::contains(dest)) { StubCodeDesc* desc = StubCodeDesc::desc_for(dest); - if (desc == nullptr) { - desc = StubCodeDesc::desc_for(dest + frame::pc_return_offset); - } if (desc != nullptr) { st->print(" Stub::%s", desc->name()); } diff --git a/src/hotspot/share/compiler/disassembler.cpp b/src/hotspot/share/compiler/disassembler.cpp index 2c1ef235e07..9dc8956d98d 100644 --- a/src/hotspot/share/compiler/disassembler.cpp +++ b/src/hotspot/share/compiler/disassembler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, 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 @@ -591,9 +591,6 @@ void decode_env::print_address(address adr) { if (Universe::is_fully_initialized()) { if (StubRoutines::contains(adr)) { StubCodeDesc* desc = StubCodeDesc::desc_for(adr); - if (desc == nullptr) { - desc = StubCodeDesc::desc_for(adr + frame::pc_return_offset); - } if (desc != nullptr) { st->print("Stub::%s", desc->name()); if (desc->begin() != adr) { diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 7396c1ee9ce..eaa6afb5efa 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1654,6 +1654,9 @@ void G1CollectedHeap::stop() { // that are destroyed during shutdown. _cr->stop(); _service_thread->stop(); + VM_G1StopMarking op; + VMThread::execute(&op); + _cm->stop(); } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 11c93b092b1..6f9e4e2e9cf 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -2036,6 +2036,26 @@ void G1ConcurrentMark::print_stats() { } } +bool G1ConcurrentMark::shutdown_cleanup_needed() const { + // Cleanup (aborting threads, setting abort flags) is needed throughout the whole cycle before + // stopping the CM thread. + return is_fully_initialized() && is_in_concurrent_cycle(); +} + +void G1ConcurrentMark::shutdown_concurrent_cycle() { + assert_at_safepoint_on_vm_thread(); + + abort_root_region_scan_at_safepoint(); + abort_marking_threads(); + + SATBMarkQueueSet& satb_mq_set = G1BarrierSet::satb_mark_queue_set(); + satb_mq_set.abandon_partial_marking(); + // This can be called either during or outside marking, we'll read + // the expected_active value from the SATB queue set. + satb_mq_set.set_active_all_threads(false, /* new active value */ + satb_mq_set.is_active() /* expected_active */); +} + bool G1ConcurrentMark::concurrent_cycle_abort() { assert_at_safepoint_on_vm_thread(); assert(_g1h->collector_state()->is_in_full_gc(), "must be"); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index 21518423957..73dabc12863 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -608,6 +608,8 @@ public: bool mark_stack_empty() const { return _global_mark_stack.is_empty(); } void concurrent_cycle_start(); + bool shutdown_cleanup_needed() const; + void shutdown_concurrent_cycle(); // Abandon current marking iteration due to a Full GC. bool concurrent_cycle_abort(); void concurrent_cycle_end(bool mark_cycle_completed); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp index a22442c2b7f..a1c684ecf59 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp @@ -50,7 +50,8 @@ class G1ConcurrentMarkThread: public ConcurrentGCThread { Atomic _state; - ServiceState state() const { return _state.load_relaxed(); } + ServiceState state() const { return _state.load_acquire(); } + void set_state(ServiceState new_state) { _state.release_store(new_state); } // Returns whether we are in a "Full" cycle. bool is_in_full_concurrent_cycle() const; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp index bea6fe4e451..3225c253dbb 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp @@ -48,31 +48,31 @@ inline bool G1ConcurrentMarkThread::is_in_full_concurrent_cycle() const { inline void G1ConcurrentMarkThread::set_idle() { // Concurrent cycle may be aborted any time. assert(!is_idle(), "must not be idle"); - _state.store_relaxed(Idle); + set_state(Idle); } inline void G1ConcurrentMarkThread::start_full_cycle() { assert(SafepointSynchronize::is_at_safepoint(), "must be"); assert(is_idle(), "cycle in progress"); - _state.store_relaxed(FullCycleMarking); + set_state(FullCycleMarking); } inline void G1ConcurrentMarkThread::start_undo_cycle() { assert(SafepointSynchronize::is_at_safepoint(), "must be"); assert(is_idle(), "cycle in progress"); - _state.store_relaxed(UndoCycleResetForNextCycle); + set_state(UndoCycleResetForNextCycle); } inline void G1ConcurrentMarkThread::set_full_cycle_rebuild_and_scrub() { assert(SafepointSynchronize::is_at_safepoint(), "must be"); assert(state() == FullCycleMarking, "must be"); - _state.store_relaxed(FullCycleRebuildOrScrub); + set_state(FullCycleRebuildOrScrub); } inline void G1ConcurrentMarkThread::set_full_cycle_reset_for_next_cycle() { assert(SafepointSynchronize::is_at_safepoint(), "must be"); assert(state() == FullCycleRebuildOrScrub, "must be"); - _state.store_relaxed(FullCycleResetForNextCycle); + set_state(FullCycleResetForNextCycle); } inline bool G1ConcurrentMarkThread::is_in_marking() const { diff --git a/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp b/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp index 7553936bb26..b913bdc2525 100644 --- a/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp +++ b/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp @@ -114,12 +114,5 @@ public: }; void G1SATBMarkQueueSet::filter(SATBMarkQueue& queue) { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - if (g1h->collector_state()->is_in_marking()) { - apply_filter(G1SATBMarkQueueFilterFn(), queue); - } else { - // is_in_marking() covers both the concurrent marking and the Remark pause. Outside - // of that, there can be no entry that requires SATB marking. - queue.set_empty(); - } + apply_filter(G1SATBMarkQueueFilterFn(), queue); } diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index 86e55e8ac4f..373ec9660da 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -130,8 +130,13 @@ void VM_G1CollectForAllocation::doit() { } void VM_G1PauseConcurrent::doit() { - GCIdMark gc_id_mark(_gc_id); G1CollectedHeap* g1h = G1CollectedHeap::heap(); + if (_is_shutting_down) { + g1h->concurrent_mark()->shutdown_concurrent_cycle(); + return; + } + + GCIdMark gc_id_mark(_gc_id); GCTraceCPUTime tcpu(g1h->concurrent_mark()->gc_tracer_cm()); // GCTraceTime(...) only supports sub-phases, so a more verbose version @@ -150,12 +155,9 @@ void VM_G1PauseConcurrent::doit() { bool VM_G1PauseConcurrent::doit_prologue() { Heap_lock->lock(); G1CollectedHeap* g1h = G1CollectedHeap::heap(); - if (g1h->is_shutting_down()) { + _is_shutting_down = g1h->is_shutting_down(); + if (_is_shutting_down && !g1h->concurrent_mark()->shutdown_cleanup_needed()) { Heap_lock->unlock(); - // JVM shutdown has started. Abort concurrent marking to ensure that any further - // concurrent VM operations will not try to start and interfere with the shutdown - // process. - g1h->concurrent_mark()->abort_marking_threads(); return false; } return true; @@ -177,3 +179,19 @@ void VM_G1PauseCleanup::work() { G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark(); cm->cleanup(); } + +bool VM_G1StopMarking::doit_prologue() { + G1CollectedHeap* g1h = G1CollectedHeap::heap(); +#ifdef ASSERT + { + MutexLocker ml(Heap_lock); + assert(g1h->is_shutting_down(), "must be"); + } +#endif + return g1h->concurrent_mark()->shutdown_cleanup_needed(); +} + +void VM_G1StopMarking::doit() { + G1ConcurrentMark* cm = G1CollectedHeap::heap()->concurrent_mark(); + cm->shutdown_concurrent_cycle(); +} diff --git a/src/hotspot/share/gc/g1/g1VMOperations.hpp b/src/hotspot/share/gc/g1/g1VMOperations.hpp index 458d638b04e..7d56ea1916f 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.hpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.hpp @@ -80,11 +80,12 @@ public: // Concurrent G1 stop-the-world operations such as remark and cleanup. class VM_G1PauseConcurrent : public VM_Operation { uint _gc_id; + bool _is_shutting_down; const char* _message; protected: VM_G1PauseConcurrent(const char* message) : - _gc_id(GCId::current()), _message(message) { } + _gc_id(GCId::current()), _is_shutting_down(false), _message(message) { } virtual void work() = 0; // Does this concurrent pause affect the memory pools? If so, update the collectionUsage() @@ -116,4 +117,15 @@ public: void work() override; }; +class VM_G1StopMarking : public VM_Operation { +public: + VM_G1StopMarking() : VM_Operation() { } + VMOp_Type type() const override { return VMOp_G1StopMarking; } + + bool doit_prologue() override; + void doit() override; + + bool is_gc_operation() const override { return true; } +}; + #endif // SHARE_GC_G1_G1VMOPERATIONS_HPP diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index 7aa88110fc8..ea3a85861b8 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -315,17 +315,16 @@ HeapWord* ParallelScavengeHeap::mem_allocate_work(size_t size, bool is_tlab) { return result; } + // Ensure that is_init_completed() does not transition while expanding the heap. + ConditionalMutexLocker ml_init(InitCompleted_lock, !is_init_completed(), Mutex::_no_safepoint_check_flag); if (!is_init_completed()) { - // Double checked locking, this ensure that is_init_completed() does not - // transition while expanding the heap. - MonitorLocker ml(InitCompleted_lock, Monitor::_no_safepoint_check_flag); - if (!is_init_completed()) { - result = expand_heap_and_allocate(size, is_tlab); - // Return the result if it's tlab-allocation. If the result is null, callers will retry - // non-tlab allocation. - if (result != nullptr || is_tlab) { - return result; - } + // Rechecked !is_init_completed() implies we have mutual exclusion via + // `Heap_lock` and `InitCompleted_lock` + result = expand_heap_and_allocate(size, is_tlab); + // Return the result if it's tlab-allocation. If the result is null, + // callers will retry non-tlab allocation. + if (result != nullptr || is_tlab) { + return result; } } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp index 0f2a5b48d84..f57a9b20957 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp @@ -144,7 +144,7 @@ void ShenandoahEvacuateUpdateRootClosureBase::do_oop( template template void ShenandoahEvacuateUpdateRootClosureBase::do_oop_work(T* p) { - assert(_heap->is_concurrent_weak_root_in_progress() || + assert((_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) || _heap->is_concurrent_strong_root_in_progress(), "Only do this in root processing phase"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp index 3116ec30665..d1c25eb49b4 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp @@ -111,7 +111,7 @@ public: return; } - { + if (_heap->is_evacuation_in_progress()) { ShenandoahNMethodLocker locker(nm_data->lock()); // Heal oops diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index eddeca57fd1..28f04de2f86 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -183,7 +183,7 @@ bool ShenandoahConcurrentGC::collect(GCCause::Cause cause) { assert(heap->is_concurrent_weak_root_in_progress(), "Must be doing weak roots now"); - // Concurrent stack processing + // Finish all thread/stack roots if needed. This completes stack watermark processing. if (heap->is_evacuation_in_progress()) { entry_thread_roots(); } @@ -211,6 +211,9 @@ bool ShenandoahConcurrentGC::collect(GCCause::Cause cause) { entry_strong_roots(); } + // Roots processing is complete, put the weak roots flag down. + entry_final_roots(); + // Continue the cycle with evacuation and optional update-refs. // This may be skipped if there is nothing to evacuate. // If so, evac_in_progress would be unset by collection set preparation code. @@ -249,9 +252,18 @@ bool ShenandoahConcurrentGC::collect(GCCause::Cause cause) { entry_cleanup_complete(); } else { _abbreviated = true; - if (!entry_final_roots()) { - assert(_degen_point != _degenerated_unset, "Need to know where to start degenerated cycle"); - return false; + + if (heap->mode()->is_generational()) { + entry_complete_abbreviated_cycle(); + + // If the promote-in-place operation was cancelled, we can have the degenerated + // cycle complete the operation. It will see that no evacuations are in progress, + // and that there are regions wanting promotion. The risk with not handling the + // cancellation would be failing to restore top for these regions and leaving + // them unable to serve allocations for the old generation. + if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_evac)) { + return false; + } } // In normal cycle, final-update-refs would verify at the end of the cycle. @@ -275,34 +287,34 @@ bool ShenandoahConcurrentGC::collect(GCCause::Cause cause) { return true; } -bool ShenandoahConcurrentGC::complete_abbreviated_cycle() { +void ShenandoahConcurrentGC::entry_complete_abbreviated_cycle() { shenandoah_assert_generational(); ShenandoahGenerationalHeap* const heap = ShenandoahGenerationalHeap::heap(); + TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); + static const char* msg = "Concurrent complete abbreviated cycle"; + ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::complete_abbreviated); + EventMark em("%s", msg); + + ShenandoahWorkerScope scope(heap->workers(), + ShenandoahWorkerPolicy::calc_workers_for_conc_evac(), + msg); + // We chose not to evacuate because we found sufficient immediate garbage. // However, there may still be regions to promote in place, so do that now. if (heap->old_generation()->has_in_place_promotions()) { - entry_promote_in_place(); - - // If the promote-in-place operation was cancelled, we can have the degenerated - // cycle complete the operation. It will see that no evacuations are in progress, - // and that there are regions wanting promotion. The risk with not handling the - // cancellation would be failing to restore top for these regions and leaving - // them unable to serve allocations for the old generation.This will leave the weak - // roots flag set (the degenerated cycle will unset it). - if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_evac)) { - return false; - } + ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::complete_abbreviated_promote_in_place); + ShenandoahGCWorkerPhase worker_phase(ShenandoahPhaseTimings::complete_abbreviated_promote_in_place); + heap->promote_regions_in_place(_generation, true); } // At this point, the cycle is effectively complete. If the cycle has been cancelled here, // the control thread will detect it on its next iteration and run a degenerated young cycle. - if (!_generation->is_old()) { + if (!heap->cancelled_gc() && !_generation->is_old()) { + ShenandoahTimingsTracker tracker(ShenandoahPhaseTimings::complete_abbreviated_update_region_ages); heap->update_region_ages(_generation->complete_marking_context()); } - - return true; } void ShenandoahConcurrentGC::vmop_entry_init_mark() { @@ -582,16 +594,6 @@ void ShenandoahConcurrentGC::entry_evacuate() { op_evacuate(); } -void ShenandoahConcurrentGC::entry_promote_in_place() const { - shenandoah_assert_generational(); - - ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::promote_in_place); - ShenandoahGCWorkerPhase worker_phase(ShenandoahPhaseTimings::promote_in_place); - EventMark em("%s", "Promote in place"); - - ShenandoahGenerationalHeap::heap()->promote_regions_in_place(_generation, true); -} - void ShenandoahConcurrentGC::entry_update_thread_roots() { ShenandoahHeap* const heap = ShenandoahHeap::heap(); TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); @@ -1227,26 +1229,14 @@ void ShenandoahConcurrentGC::op_final_update_refs() { } } -bool ShenandoahConcurrentGC::entry_final_roots() { +void ShenandoahConcurrentGC::entry_final_roots() { ShenandoahHeap* const heap = ShenandoahHeap::heap(); TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters()); - - const char* msg = conc_final_roots_event_message(); ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::conc_final_roots); EventMark em("%s", msg); - ShenandoahWorkerScope scope(heap->workers(), - ShenandoahWorkerPolicy::calc_workers_for_conc_evac(), - msg); - - if (heap->mode()->is_generational()) { - if (!complete_abbreviated_cycle()) { - return false; - } - } heap->concurrent_final_roots(); - return true; } void ShenandoahConcurrentGC::op_verify_final() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp index fde585b4aa9..e763d1853e3 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp @@ -91,6 +91,8 @@ protected: void entry_class_unloading(); void entry_strong_roots(); void entry_cleanup_early(); + void entry_complete_abbreviated_cycle(); + void entry_final_roots(); void entry_evacuate(); void entry_update_thread_roots(); void entry_update_card_table(); @@ -98,12 +100,6 @@ protected: void entry_update_refs(); void entry_cleanup_complete(); - // This is the last phase of a cycle which performs no evacuations - bool entry_final_roots(); - - // Called when the collection set is empty, but the generational mode has regions to promote in place - void entry_promote_in_place() const; - // Actual work for the phases void op_reset(); void op_init_mark(); @@ -135,8 +131,6 @@ protected: private: void start_mark(); - bool complete_abbreviated_cycle(); - static bool has_in_place_promotions(ShenandoahHeap* heap); // Messages for GC trace events, they have to be immortal for diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index e60db88974a..ae0c873fa58 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1236,7 +1236,6 @@ void ShenandoahHeap::concurrent_prepare_for_update_refs() { // A cancellation at this point means the degenerated cycle must resume from update-refs. set_gc_state_concurrent(EVACUATION, false); - set_gc_state_concurrent(WEAK_ROOTS, false); set_gc_state_concurrent(UPDATE_REFS, true); } @@ -1252,35 +1251,24 @@ void ShenandoahHeap::concurrent_prepare_for_update_refs() { _update_refs_iterator.reset(); } -class ShenandoahCompositeHandshakeClosure : public HandshakeClosure { - HandshakeClosure* _handshake_1; - HandshakeClosure* _handshake_2; - public: - ShenandoahCompositeHandshakeClosure(HandshakeClosure* handshake_1, HandshakeClosure* handshake_2) : - HandshakeClosure(handshake_2->name()), - _handshake_1(handshake_1), _handshake_2(handshake_2) {} - - void do_thread(Thread* thread) override { - _handshake_1->do_thread(thread); - _handshake_2->do_thread(thread); - } -}; - -void ShenandoahHeap::concurrent_final_roots(HandshakeClosure* handshake_closure) { +void ShenandoahHeap::concurrent_final_roots() { { - assert(!is_evacuation_in_progress(), "Should not evacuate for abbreviated or old cycles"); MutexLocker lock(Threads_lock); + +#ifdef ASSERT + for (JavaThreadIteratorWithHandle jtiwh; JavaThread* jt = jtiwh.next();) { + StackWatermark* sw = StackWatermarkSet::get(jt, StackWatermarkKind::gc); + assert(sw == nullptr || sw->processing_completed(), + "Cannot turn off weak roots before stack watermark processing is complete"); + } +#endif + set_gc_state_concurrent(WEAK_ROOTS, false); } ShenandoahGCStatePropagatorHandshakeClosure propagator(_gc_state.raw_value()); Threads::non_java_threads_do(&propagator); - if (handshake_closure == nullptr) { - Handshake::execute(&propagator); - } else { - ShenandoahCompositeHandshakeClosure composite(&propagator, handshake_closure); - Handshake::execute(&composite); - } + Handshake::execute(&propagator); } oop ShenandoahHeap::evacuate_object(oop p, Thread* thread) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 86707c7e831..9810b316c21 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -493,8 +493,8 @@ private: // Retires LABs used for evacuation void concurrent_prepare_for_update_refs(); - // Turn off weak roots flag, purge old satb buffers in generational mode - void concurrent_final_roots(HandshakeClosure* handshake_closure = nullptr); + // Turn off weak roots flag + void concurrent_final_roots(); virtual void update_heap_references(ShenandoahGeneration* generation, bool concurrent); // Final update region states diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp index 5b24cfc979a..b0573c3f677 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp @@ -124,7 +124,7 @@ void ShenandoahNMethod::heal_nmethod(nmethod* nm) { assert(data->lock()->owned_by_self(), "Must hold the lock"); ShenandoahHeap* const heap = ShenandoahHeap::heap(); - if (heap->is_concurrent_weak_root_in_progress() || + if ((heap->is_concurrent_weak_root_in_progress() && heap->is_evacuation_in_progress()) || heap->is_concurrent_strong_root_in_progress()) { heal_nmethod_metadata(data); } else if (heap->is_concurrent_mark_in_progress()) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp index ff441a0c868..df41069d922 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp @@ -134,7 +134,7 @@ bool ShenandoahOldGC::collect(GCCause::Cause cause) { // return from here with weak roots in progress. This is not a valid gc state // for any young collections (or allocation failures) that interrupt the old // collection. - heap->concurrent_final_roots(); + entry_final_roots(); // After concurrent old marking finishes, we reclaim immediate garbage. Further, we may also want to expand OLD in order // to make room for anticipated promotions and/or for mixed evacuations. Mixed evacuations are especially likely to diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp index bc52d755139..dfb42e0b76f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp @@ -106,8 +106,10 @@ class outputStream; " CE: ") \ SHENANDOAH_SIMPLE_PHASE_DEF(f, conc_update_card_table, "Concurrent Update Cards") \ SHENANDOAH_SIMPLE_PHASE_DEF(f, conc_final_roots, "Concurrent Final Roots") \ - SHENANDOAH_WORKER_PHASE_DEF(f, promote_in_place, " Promote Regions", \ + SHENANDOAH_SIMPLE_PHASE_DEF(f, complete_abbreviated, "Complete Abbreviated Cycle") \ + SHENANDOAH_WORKER_PHASE_DEF(f, complete_abbreviated_promote_in_place, " Promote Regions", \ " PIP: ") \ + SHENANDOAH_SIMPLE_PHASE_DEF(f, complete_abbreviated_update_region_ages, " Update Region Ages") \ SHENANDOAH_SIMPLE_PHASE_DEF(f, final_verify_gross, "Pause Final Verify (G)") \ SHENANDOAH_SIMPLE_PHASE_DEF(f, final_verify, "Pause Final Verify (N)") \ SHENANDOAH_SIMPLE_PHASE_DEF(f, init_update_refs_gross, "Pause Init Update Refs (G)") \ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahStackWatermark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahStackWatermark.cpp index 81c584dfa37..8df2449f8b6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahStackWatermark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahStackWatermark.cpp @@ -67,14 +67,13 @@ ShenandoahStackWatermark::ShenandoahStackWatermark(JavaThread* jt) : OopClosure* ShenandoahStackWatermark::closure_from_context(void* context) { if (context != nullptr) { - assert(_heap->is_concurrent_weak_root_in_progress() || + assert((_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) || _heap->is_concurrent_mark_in_progress(), "Only these two phases"); assert(Thread::current()->is_Worker_thread(), "Unexpected thread passing in context: " PTR_FORMAT, p2i(context)); return reinterpret_cast(context); } else { - if (_heap->is_concurrent_weak_root_in_progress()) { - assert(_heap->is_evacuation_in_progress(), "Nothing to evacuate"); + if (_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) { return &_evac_update_oop_cl; } else if (_heap->is_concurrent_mark_in_progress()) { return &_keep_alive_cl; @@ -87,11 +86,9 @@ OopClosure* ShenandoahStackWatermark::closure_from_context(void* context) { void ShenandoahStackWatermark::start_processing_impl(void* context) { NoSafepointVerifier nsv; - ShenandoahHeap* const heap = ShenandoahHeap::heap(); // Process the non-frame part of the thread - if (heap->is_concurrent_weak_root_in_progress()) { - assert(heap->is_evacuation_in_progress(), "Should not be armed"); + if (_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) { // Retire the TLABs, which will force threads to reacquire their TLABs. // This is needed for two reasons. Strong one: new allocations would be with new freeset, // which would be outside the collection set, so no cset writes would happen there. @@ -100,7 +97,7 @@ void ShenandoahStackWatermark::start_processing_impl(void* context) { retire_tlab(); _jt->oops_do_no_frames(closure_from_context(context), &_nm_cl); - } else if (heap->is_concurrent_mark_in_progress()) { + } else if (_heap->is_concurrent_mark_in_progress()) { // We need to reset all TLABs because they might be below the TAMS, and we need to mark // the objects in them. Do not let mutators allocate any new objects in their current TLABs. // It is also a good place to resize the TLAB sizes for future allocations. @@ -129,9 +126,8 @@ void ShenandoahStackWatermark::retire_tlab() { void ShenandoahStackWatermark::process(const frame& fr, RegisterMap& register_map, void* context) { OopClosure* oops = closure_from_context(context); assert(oops != nullptr, "Should not get to here"); - ShenandoahHeap* const heap = ShenandoahHeap::heap(); - assert((heap->is_concurrent_weak_root_in_progress() && heap->is_evacuation_in_progress()) || - heap->is_concurrent_mark_in_progress(), + assert((_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) || + _heap->is_concurrent_mark_in_progress(), "Only these two phases"); fr.oops_do(oops, &_nm_cl, ®ister_map, DerivedPointerIterationMode::_directly); } diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 1f51cdc1d39..e5f91875516 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -3497,22 +3497,38 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f ResourceMark rm; Unique_Node_List wq; wq.push(n); + + + // When we remove a CastPP, we need to pin all of its transitive users under the control of + // the removed node. The simplest approach is to pin all of the uses of the removed CastPP, + // but it is overly conservative, as an AddP does not really need pinning. As a result, we + // look through those nodes that do not need pinning and only pin memory access nodes under + // n->in(0). for (uint next = 0; next < wq.size(); ++next) { Node *m = wq.at(next); for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) { Node* use = m->fast_out(i); - if (use->is_Mem() || use->is_EncodeNarrowPtr()) { + int use_op = use->Opcode(); + if (use->is_CFG() || use->pinned() || // already pinned at the exact control + use->is_Cmp() || use_op == Op_CastP2X || use_op == Op_Conv2B) { // pure computations + continue; + } else if (use->is_EncodeNarrowPtr() || // EncodeP remembers whether its input is nullable, so it must be pinned + use_op == Op_PartialSubtypeCheck || // This accesses its pointer inputs, so it must depend on them being not-null + use->is_Mem() || use->is_memory_access_intrinsic()) { use->ensure_control_or_add_prec(n->in(0)); + } else if (use_op == Op_AddP || + use_op == Op_CastPP || use_op == Op_CheckCastPP || + use_op == Op_CMoveP || use_op == Op_CMoveN || + use_op == Op_DecodeN || use_op == Op_DecodeNKlass || + use_op == Op_VerifyVectorAlignment) { + // Look through use to find memory accesses if use does not need pinning + wq.push(use); } else { - switch(use->Opcode()) { - case Op_AddP: - case Op_DecodeN: - case Op_DecodeNKlass: - case Op_CheckCastPP: - case Op_CastPP: - wq.push(use); - break; - } + // Should have handled all kinds of nodes, verify that we do not unexpectedly arrive + // here + assert(false, "unexpected node %s", use->Name()); + // Be conservative in product and pin the unexpected use + use->ensure_control_or_add_prec(n->in(0)); } } } diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index 2f7cc6d1c1d..726a3ea1b55 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -3018,6 +3018,27 @@ bool Node::is_data_proj_of_pure_function(const Node* maybe_pure_function) const return Opcode() == Op_Proj && as_Proj()->_con == TypeFunc::Parms && maybe_pure_function->is_CallLeafPure(); } +// Whether this is an intrinsic node that accesses memory and has a memory input, such as array +// equal intrinsic. Some nodes do access memory but do not have a memory input, such as +// PartialSubTypeCheck, they are not included here. +bool Node::is_memory_access_intrinsic() const { + switch (Opcode()) { + case Op_StrComp: + case Op_StrEquals: + case Op_StrIndexOf: + case Op_StrIndexOfChar: + case Op_StrCompressedCopy: + case Op_StrInflatedCopy: + case Op_AryEq: + case Op_CountPositives: + case Op_VectorizedHashCode: + case Op_EncodeISOArray: + return true; + default: + return false; + } +} + //--------------------------has_non_debug_uses------------------------------ // Checks whether the node has any non-debug uses or not. bool Node::has_non_debug_uses() const { diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 443f4bfbe8a..b3de7498e50 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1069,6 +1069,7 @@ public: uint is_Copy() const { return (_flags & Flag_is_Copy); } virtual bool is_CFG() const { return false; } + bool is_memory_access_intrinsic() const; // If this node is control-dependent on a test, can it be rerouted to a dominating equivalent // test? This means that the node can be executed safely as long as it happens after the test diff --git a/src/hotspot/share/runtime/cpuTimeCounters.cpp b/src/hotspot/share/runtime/cpuTimeCounters.cpp index e174407089c..3374a1c5db3 100644 --- a/src/hotspot/share/runtime/cpuTimeCounters.cpp +++ b/src/hotspot/share/runtime/cpuTimeCounters.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023 Google LLC. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -25,6 +25,7 @@ #include "runtime/atomicAccess.hpp" #include "runtime/cpuTimeCounters.hpp" +#include "utilities/globalCounter.inline.hpp" const char* CPUTimeGroups::to_string(CPUTimeType val) { switch (val) { @@ -77,6 +78,10 @@ void CPUTimeCounters::inc_gc_total_cpu_time(jlong diff) { } void CPUTimeCounters::publish_gc_total_cpu_time() { + GlobalCounter::CriticalSection cs(Thread::current()); + if (!UsePerfData || !PerfDataManager::has_PerfData()) { + return; + } CPUTimeCounters* instance = CPUTimeCounters::get_instance(); // Atomically fetch the current _gc_total_cpu_time_diff and reset it to zero. jlong new_value = 0; @@ -103,6 +108,10 @@ PerfCounter* CPUTimeCounters::get_counter(CPUTimeGroups::CPUTimeType name) { } void CPUTimeCounters::update_counter(CPUTimeGroups::CPUTimeType name, jlong total) { + GlobalCounter::CriticalSection cs(Thread::current()); + if (!UsePerfData || !PerfDataManager::has_PerfData()) { + return; + } CPUTimeCounters* instance = CPUTimeCounters::get_instance(); PerfCounter* counter = instance->get_counter(name); jlong prev_value = counter->get_value(); diff --git a/src/hotspot/share/runtime/cpuTimeCounters.hpp b/src/hotspot/share/runtime/cpuTimeCounters.hpp index c2e636bdb1d..15f680c06e1 100644 --- a/src/hotspot/share/runtime/cpuTimeCounters.hpp +++ b/src/hotspot/share/runtime/cpuTimeCounters.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023 Google LLC. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -79,6 +79,8 @@ private: static void inc_gc_total_cpu_time(jlong diff); + static PerfCounter* get_counter(CPUTimeGroups::CPUTimeType name); + public: static void initialize() { assert(_instance == nullptr, "we can only allocate one CPUTimeCounters object"); @@ -91,7 +93,6 @@ public: } static void create_counter(CPUTimeGroups::CPUTimeType name); - static PerfCounter* get_counter(CPUTimeGroups::CPUTimeType name); static void update_counter(CPUTimeGroups::CPUTimeType name, jlong total); static void publish_gc_total_cpu_time(); diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index d5dccc820f3..e9143a3c4e3 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -673,7 +673,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread // as interpreted so the skeleton frame will be walkable // The correct pc will be set when the skeleton frame is completely filled out // The final pc we store in the loop is wrong and will be overwritten below - frame_pcs[number_of_frames - 1 - index ] = Interpreter::deopt_entry(vtos, 0) - frame::pc_return_offset; + frame_pcs[number_of_frames - 1 - index ] = Interpreter::deopt_entry(vtos, 0); callee_parameters = array->element(index)->method()->size_of_parameters(); callee_locals = array->element(index)->method()->max_locals(); diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index d99d36571ad..ae04d398043 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -206,9 +206,9 @@ address frame::raw_pc() const { if (is_deoptimized_frame()) { nmethod* nm = cb()->as_nmethod_or_null(); assert(nm != nullptr, "only nmethod is expected here"); - return nm->deopt_handler_entry() - pc_return_offset; + return nm->deopt_handler_entry(); } else { - return (pc() - pc_return_offset); + return pc(); } } diff --git a/src/hotspot/share/runtime/hotCodeSampler.cpp b/src/hotspot/share/runtime/hotCodeSampler.cpp index 94242b718a5..e033765c1f2 100644 --- a/src/hotspot/share/runtime/hotCodeSampler.cpp +++ b/src/hotspot/share/runtime/hotCodeSampler.cpp @@ -61,15 +61,13 @@ bool ThreadSampler::sample_all_java_threads() { continue; } - if (CodeCache::contains(pc)) { - nmethod* nm = CodeCache::find_blob(pc)->as_nmethod_or_null(); - if (nm != nullptr) { - bool created = false; - int *count = _samples.put_if_absent(nm, 0, &created); - (*count)++; - if (created) { - _samples.maybe_grow(); - } + CodeBlob* cb = CodeCache::find_blob(pc); + if (cb != nullptr && cb->is_nmethod()) { + bool created = false; + int *count = _samples.put_if_absent(cb->as_nmethod(), 0, &created); + (*count)++; + if (created) { + _samples.maybe_grow(); } } } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index b799063d58e..5489735da39 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -1810,7 +1810,7 @@ JRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address cal nmethod* caller = cb->as_nmethod(); // Get the return PC for the passed caller PC. - address return_pc = caller_pc + frame::pc_return_offset; + address return_pc = caller_pc; if (!caller->is_in_use() || !NativeCall::is_call_before(return_pc)) { return; diff --git a/src/hotspot/share/runtime/vmOperation.hpp b/src/hotspot/share/runtime/vmOperation.hpp index e22d11cf1a8..af9aa68c7ec 100644 --- a/src/hotspot/share/runtime/vmOperation.hpp +++ b/src/hotspot/share/runtime/vmOperation.hpp @@ -59,6 +59,7 @@ template(G1PauseCleanup) \ template(G1TryInitiateConcMark) \ template(G1RendezvousGCThreads) \ + template(G1StopMarking) \ template(ZMarkEndOld) \ template(ZMarkEndYoung) \ template(ZMarkFlushOperation) \ diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 856ff947dc4..3868510691a 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1709,8 +1709,6 @@ /**********************/ \ NOT_ZERO(PPC64_ONLY(declare_constant(frame::entry_frame_locals_size))) \ \ - declare_constant(frame::pc_return_offset) \ - \ /*************/ \ /* vmSymbols */ \ /*************/ \ diff --git a/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmDecomposer.java b/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmDecomposer.java index 565ed8f6128..61b1236e9bc 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmDecomposer.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmDecomposer.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, IBM Corporation. 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 @@ -172,9 +173,18 @@ class SSLAlgorithmDecomposer extends AlgorithmDecomposer { case B_AES_128_GCM: components.add("AES_128_GCM"); break; + case B_AES_128_GCM_IV: + components.add("AES_128_GCM"); + break; case B_AES_256_GCM: components.add("AES_256_GCM"); break; + case B_AES_256_GCM_IV: + components.add("AES_256_GCM"); + break; + case B_CC20_P1305: + components.add("CHACHA20_POLY1305"); + break; } return components; diff --git a/src/java.base/share/data/cacerts/luxtrustglobalrootca b/src/java.base/share/data/cacerts/luxtrustglobalrootca deleted file mode 100644 index 7fb3d818f80..00000000000 --- a/src/java.base/share/data/cacerts/luxtrustglobalrootca +++ /dev/null @@ -1,28 +0,0 @@ -Owner: CN=LuxTrust Global Root, O=LuxTrust s.a., C=LU -Issuer: CN=LuxTrust Global Root, O=LuxTrust s.a., C=LU -Serial number: bb8 -Valid from: Thu Mar 17 09:51:37 GMT 2011 until: Wed Mar 17 09:51:37 GMT 2021 -Signature algorithm name: SHA256withRSA -Subject Public Key Algorithm: 2048-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIDZDCCAkygAwIBAgICC7gwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCTFUx -FjAUBgNVBAoTDUx1eFRydXN0IHMuYS4xHTAbBgNVBAMTFEx1eFRydXN0IEdsb2Jh -bCBSb290MB4XDTExMDMxNzA5NTEzN1oXDTIxMDMxNzA5NTEzN1owRDELMAkGA1UE -BhMCTFUxFjAUBgNVBAoTDUx1eFRydXN0IHMuYS4xHTAbBgNVBAMTFEx1eFRydXN0 -IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsn+n -QPAiygz267Hxyw6VV0B1r6A/Ps7sqjJX5hmxZ0OYWmt8s7j6eJyqpoSyYBuAQc5j -zR8XCJmk9e8+EsdMsFeaXHhAePxFjdqRZ9w6Ubltc+a3OY52OrQfBfVpVfmTz3iI -Sr6qm9d7R1tGBEyCFqY19vx039a0r9jitScRdFmiwmYsaArhmIiIPIoFdRTjuK7z -CISbasE/MRivJ6VLm6T9eTHemD0OYcqHmMH4ijCc+j4z1aXEAwfh95Z0GAAnOCfR -K6qq4UFFi2/xJcLcopeVx0IUM115hCNq52XAV6DYXaljAeew5Ivo+MVjuOVsdJA9 -x3f8K7p56aTGEnin/wIDAQABo2AwXjAMBgNVHRMEBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjAfBgNVHSMEGDAWgBQXFYWJCS8kh28/HRvk8pZ5g0gTzjAdBgNVHQ4EFgQU -FxWFiQkvJIdvPx0b5PKWeYNIE84wDQYJKoZIhvcNAQELBQADggEBAFrwHNDUUM9B -fua4nX3DcNBeNv9ujnov3kgR1TQuPLdFwlQlp+HBHjeDtpSutkVIA+qVvuucarQ3 -XB8u02uCgUNbCj8RVWOs+nwIAjegPDkEM/6XMshS5dklTbDG7mgfcKpzzlcD3H0K -DTPy0lrfCmw7zBFRlxqkIaKFNQLXgCLShLL4wKpov9XrqsMLq6F8K/f1O4fhVFfs -BSTveUJO84ton+Ruy4KZycwq3FPCH3CDqyEPVrRI/98HIrOM+R2mBN8tAza53W/+ -MYhm/2xtRDSvCHc+JtJy9LtHVpM8mGPhM7uZI5K1g3noHZ9nrWLWidb2/CfeMifL -hNp3hSGhEiE= ------END CERTIFICATE----- diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Frame.java index 978fb39ad1c..0258fea6808 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Frame.java @@ -75,12 +75,6 @@ public abstract class Frame implements Cloneable { /** Size of ConstMethod for computing BCI from BCP (FIXME: hack) */ private static long ConstMethodSize; - private static int pcReturnOffset; - - public static int pcReturnOffset() { - return pcReturnOffset; - } - protected void adjustForDeopt() { if (pc != null) { // Look for a deopt pc and if it is deopted convert to original pc @@ -104,8 +98,6 @@ public abstract class Frame implements Cloneable { // FIXME: not sure whether alignment here is correct or how to // force it (round up to address size?) ConstMethodSize = ConstMethodType.getSize(); - - pcReturnOffset = db.lookupIntConstant("frame::pc_return_offset").intValue(); } protected int bcpToBci(Address bcp, ConstMethod cm) { diff --git a/test/hotspot/jtreg/ProblemList-Virtual.txt b/test/hotspot/jtreg/ProblemList-Virtual.txt index 705cded007a..b30a09a7710 100644 --- a/test/hotspot/jtreg/ProblemList-Virtual.txt +++ b/test/hotspot/jtreg/ProblemList-Virtual.txt @@ -29,6 +29,11 @@ serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java 8308026 generic-al serviceability/jvmti/Heap/IterateHeapWithEscapeAnalysisEnabled.java 8264699 generic-all vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_a/TestDescription.java 8308367 generic-all +vmTestbase/nsk/jvmti/unit/functions/Dispose/JvmtiTest/TestDescription.java 8387429 generic-all +vmTestbase/nsk/jvmti/scenarios/capability/CM02/cm02t001/TestDescription.java 8299217 generic-all +vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002/TestDescription.java 8327967 generic-all + + #### ## Classes not unloaded as expected (TODO, need to check if FJ keeps a reference) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 8d9de094323..a9f70fc97a4 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -70,6 +70,8 @@ compiler/c2/aarch64/TestStaticCallStub.java 8359963 generic-aarch64 compiler/unsafe/AlignmentGapAccess.java 8373487 generic-all +compiler/escapeAnalysis/TestBCEscapeAnalyzerOverflow.java 8387392 windows-aarch64 + ############################################################################# # :hotspot_gc @@ -160,6 +162,7 @@ vmTestbase/metaspace/gc/firstGC_default/TestDescription.java 8208250 generic-all vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/TestDescription.java 8073470 linux-all vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t006/TestDescription.java 8372206 generic-all vmTestbase/nsk/jvmti/InterruptThread/intrpthrd003/TestDescription.java 8288911 macosx-all +vmTestbase/nsk/jvmti/unit/timers/JvmtiTest/TestDescription.java 8235348 windows-x64 vmTestbase/jit/escape/LockCoarsening/LockCoarsening001.java 8148743 generic-all vmTestbase/jit/escape/LockCoarsening/LockCoarsening002.java 8208259 generic-all diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index e09235f6a39..f400aa22f0b 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -314,7 +314,8 @@ tier1_gc_shenandoah = \ gc/shenandoah/compiler/ \ gc/shenandoah/mxbeans/ \ gc/shenandoah/TestSmallHeap.java \ - gc/shenandoah/oom/ + gc/shenandoah/oom/ \ + gtest/ShenandoahGtests.java tier2_gc_shenandoah = \ runtime/MemberName/MemberNameLeak.java \ diff --git a/test/hotspot/jtreg/compiler/c2/ReachabilityFenceTest.java b/test/hotspot/jtreg/compiler/c2/ReachabilityFenceTest.java index d0bce024696..14c4f7b5a48 100644 --- a/test/hotspot/jtreg/compiler/c2/ReachabilityFenceTest.java +++ b/test/hotspot/jtreg/compiler/c2/ReachabilityFenceTest.java @@ -38,7 +38,7 @@ import compiler.lib.ir_framework.*; * @summary Tests to ensure that reachabilityFence() correctly keeps objects from being collected prematurely. * @modules java.base/jdk.internal.misc * @library /test/lib / - * @run main/othervm -Xbatch compiler.c2.ReachabilityFenceTest + * @run driver ${test.main.class} */ public class ReachabilityFenceTest { private static final int SIZE = 100; diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java index 5e6a757dd5f..99143f04dcd 100644 --- a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java +++ b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, 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 @@ -38,7 +38,7 @@ import java.util.Random; * @summary Test merging of consecutive stores * @modules java.base/jdk.internal.misc * @library /test/lib / - * @run main/timeout=480 compiler.c2.TestMergeStores aligned + * @run driver/timeout=480 ${test.main.class} aligned */ /* @@ -48,7 +48,7 @@ import java.util.Random; * @summary Test merging of consecutive stores * @modules java.base/jdk.internal.misc * @library /test/lib / - * @run main/timeout=480 compiler.c2.TestMergeStores unaligned + * @run driver/timeout=480 ${test.main.class} unaligned */ /* @@ -58,7 +58,7 @@ import java.util.Random; * @summary Test merging of consecutive stores * @modules java.base/jdk.internal.misc * @library /test/lib / - * @run main/timeout=480 compiler.c2.TestMergeStores StressIGVN + * @run driver/timeout=480 ${test.main.class} StressIGVN */ public class TestMergeStores { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ConstructorBarriers.java b/test/hotspot/jtreg/compiler/c2/irTests/ConstructorBarriers.java index ba7e7d851b0..66dabcebf80 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ConstructorBarriers.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ConstructorBarriers.java @@ -31,7 +31,7 @@ import compiler.lib.ir_framework.*; * @summary Test barriers emitted in constructors * @library /test/lib / * @requires os.arch=="aarch64" | os.arch=="riscv64" | os.arch=="x86_64" | os.arch=="amd64" - * @run main compiler.c2.irTests.ConstructorBarriers + * @run driver ${test.main.class} */ public class ConstructorBarriers { public static void main(String[] args) { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java index 5524b5d7b6c..9556fce988d 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2023, Red Hat, Inc. All rights reserved. - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, 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 @@ -26,7 +26,6 @@ package compiler.c2.irTests; import compiler.lib.ir_framework.*; import jdk.test.lib.Utils; -import jdk.test.whitebox.WhiteBox; import jdk.internal.misc.Unsafe; import java.util.Random; import java.util.Arrays; @@ -40,15 +39,12 @@ import java.util.List; * @summary C2: vectorization fails on simple ByteBuffer loop * @modules java.base/jdk.internal.misc * @library /test/lib / - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI compiler.c2.irTests.TestVectorizationMismatchedAccess + * @run driver ${test.main.class} */ public class TestVectorizationMismatchedAccess { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static final Random RANDOM = Utils.getRandomInstance(); - private final static WhiteBox wb = WhiteBox.getWhiteBox(); public static void main(String[] args) { TestFramework framework = new TestFramework(); diff --git a/test/hotspot/jtreg/compiler/c2/riscv64/TestIntegerReverse.java b/test/hotspot/jtreg/compiler/c2/riscv64/TestIntegerReverse.java index 8b3abbb0300..82bb79d3c1f 100644 --- a/test/hotspot/jtreg/compiler/c2/riscv64/TestIntegerReverse.java +++ b/test/hotspot/jtreg/compiler/c2/riscv64/TestIntegerReverse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2025, Rivos Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,7 +30,7 @@ * * @library /test/lib / * @requires os.arch == "riscv64" & vm.cpu.features ~= ".*zbkb.*" - * @run main/othervm compiler.c2.riscv64.TestIntegerReverse + * @run driver ${test.main.class} */ package compiler.c2.riscv64; diff --git a/test/hotspot/jtreg/compiler/c2/riscv64/TestLongReverse.java b/test/hotspot/jtreg/compiler/c2/riscv64/TestLongReverse.java index 01c3b871ffa..807a58a18f3 100644 --- a/test/hotspot/jtreg/compiler/c2/riscv64/TestLongReverse.java +++ b/test/hotspot/jtreg/compiler/c2/riscv64/TestLongReverse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2025, Rivos Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,7 +30,7 @@ * * @library /test/lib / * @requires os.arch == "riscv64" & vm.cpu.features ~= ".*zbkb.*" - * @run main/othervm compiler.c2.riscv64.TestLongReverse + * @run driver ${test.main.class} */ package compiler.c2.riscv64; diff --git a/test/hotspot/jtreg/compiler/controldependency/TestRemoveCastPPWithCMoveUse.java b/test/hotspot/jtreg/compiler/controldependency/TestRemoveCastPPWithCMoveUse.java new file mode 100644 index 00000000000..3d752cc74f5 --- /dev/null +++ b/test/hotspot/jtreg/compiler/controldependency/TestRemoveCastPPWithCMoveUse.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026, 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. + */ +package compiler.controldependency; + +/* + * @test + * @bug 8385420 + * @summary C2 correctly handles the case when the removed CastPPNode has a CMove use. + * @run main ${test.main.class} + * @run main/othervm -Xbatch -XX:CompileOnly=${test.main.class}::test + * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM ${test.main.class} + * + */ +public class TestRemoveCastPPWithCMoveUse { + public static void main(String[] args) { + for (int i = 0; i < 10_000; i++) { + test(null, false); + test(null, true); + test("", false); + test("", true); + } + } + + static int test(String a, boolean flag) { + StringBuilder sb = new StringBuilder(); + if (a == null) { + sb.append(""); + } else { + sb.append(flag ? a : ""); + } + return sb.length(); + } +} diff --git a/test/hotspot/jtreg/compiler/exceptions/TestDebugDuringExceptionCatching.java b/test/hotspot/jtreg/compiler/exceptions/TestDebugDuringExceptionCatching.java index 9be192d1f55..026b2d15b77 100644 --- a/test/hotspot/jtreg/compiler/exceptions/TestDebugDuringExceptionCatching.java +++ b/test/hotspot/jtreg/compiler/exceptions/TestDebugDuringExceptionCatching.java @@ -43,7 +43,7 @@ import test.java.lang.invoke.lib.InstructionHelper; * @library /test/lib /test/jdk/java/lang/invoke/common / * @build test.java.lang.invoke.lib.InstructionHelper * - * @run main/othervm ${test.main.class} + * @run driver ${test.main.class} */ public class TestDebugDuringExceptionCatching { diff --git a/test/hotspot/jtreg/compiler/hotcode/HotCodeCollectorMoveFunction.java b/test/hotspot/jtreg/compiler/hotcode/HotCodeCollectorMoveFunction.java index 5677ca88eb2..2b93c24e255 100644 --- a/test/hotspot/jtreg/compiler/hotcode/HotCodeCollectorMoveFunction.java +++ b/test/hotspot/jtreg/compiler/hotcode/HotCodeCollectorMoveFunction.java @@ -79,6 +79,8 @@ public class HotCodeCollectorMoveFunction { private static final int C2_LEVEL = 4; private static final int FUNC_RUN_MILLIS = 60_000; + private static volatile int blackholeCount = 0; + static { try { method = Runner.class.getMethod("func"); @@ -111,7 +113,15 @@ public class HotCodeCollectorMoveFunction { public static void func() { long start = System.currentTimeMillis(); - while (System.currentTimeMillis() - start < FUNC_RUN_MILLIS) {} + while (System.currentTimeMillis() - start < FUNC_RUN_MILLIS) { + // Perform multiplicative LCG to ensure the compiler does not optimize away the code. + // Integer overflow is used for the modulus so the loop terminates after (2^32)/4 iterations + int num = 1; + do { + blackholeCount++; + num *= 69069; + } while (num != 1); + } } } } diff --git a/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java index c5ef1640721..ab40a2ea234 100644 --- a/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java +++ b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, 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 @@ -27,7 +27,7 @@ * @summary Ranges can be proven to be disjoint but not orderable (thanks to unsigned range) * Comparing such values in such range with != should always be true. * @library /test/lib / - * @run main compiler.igvn.CmpDisjointButNonOrderedRangesLong + * @run driver ${test.main.class} */ package compiler.igvn; diff --git a/test/hotspot/jtreg/compiler/longcountedloops/TestShortRunningLongCountedLoop.java b/test/hotspot/jtreg/compiler/longcountedloops/TestShortRunningLongCountedLoop.java index 7e55353e0f7..ed65deb6c85 100644 --- a/test/hotspot/jtreg/compiler/longcountedloops/TestShortRunningLongCountedLoop.java +++ b/test/hotspot/jtreg/compiler/longcountedloops/TestShortRunningLongCountedLoop.java @@ -32,14 +32,11 @@ import java.util.Objects; * @bug 8342692 * @summary C2: long counted loop/long range checks: don't create loop-nest for short running loops * @library /test/lib / - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI compiler.longcountedloops.TestShortRunningLongCountedLoop + * @run driver ${test.main.class} */ public class TestShortRunningLongCountedLoop { private static volatile int volatileField; - private final static WhiteBox wb = WhiteBox.getWhiteBox(); public static void main(String[] args) { // IR rules expect a single loop so disable unrolling @@ -351,8 +348,9 @@ public class TestShortRunningLongCountedLoop { throw new RuntimeException("incorrect result: " + res); } } - wb.enqueueMethodForCompilation(info.getTest(), CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); - if (!wb.isMethodCompiled(info.getTest())) { + WhiteBox whitebox = WhiteBox.getWhiteBox(); + whitebox.enqueueMethodForCompilation(info.getTest(), CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!whitebox.isMethodCompiled(info.getTest())) { throw new RuntimeException("Should be compiled now"); } for (int i = 0; i < 10; i++) { diff --git a/test/hotspot/jtreg/compiler/loopopts/TestHasTruncationWrap.java b/test/hotspot/jtreg/compiler/loopopts/TestHasTruncationWrap.java index 9a68a2fcb77..143933ed6ea 100644 --- a/test/hotspot/jtreg/compiler/loopopts/TestHasTruncationWrap.java +++ b/test/hotspot/jtreg/compiler/loopopts/TestHasTruncationWrap.java @@ -27,14 +27,14 @@ * @summary Test CountedLoopConverter::has_truncation_wrap logic that checks if * a truncated iv (e.g. byte or char iv) is still a valid counted loop. * @library /test/lib / - * @run main ${test.main.class} + * @run driver ${test.main.class} */ /* * @test id=Xcomp * @bug 8385855 * @library /test/lib / - * @run main ${test.main.class} -Xcomp -XX:-TieredCompilation -XX:CompileCommand=compileonly,${test.main.class}::test* + * @run driver ${test.main.class} -Xcomp -XX:-TieredCompilation -XX:CompileCommand=compileonly,${test.main.class}::test* */ package compiler.loopopts; diff --git a/test/hotspot/jtreg/compiler/loopopts/TestRedundantSafepointElimination.java b/test/hotspot/jtreg/compiler/loopopts/TestRedundantSafepointElimination.java index 69f86a2bf1d..f557a491160 100644 --- a/test/hotspot/jtreg/compiler/loopopts/TestRedundantSafepointElimination.java +++ b/test/hotspot/jtreg/compiler/loopopts/TestRedundantSafepointElimination.java @@ -30,7 +30,7 @@ import compiler.lib.ir_framework.*; * @bug 8347499 * @summary Tests that redundant safepoints can be eliminated in loops. * @library /test/lib / - * @run main compiler.loopopts.TestRedundantSafepointElimination + * @run driver ${test.main.class} */ public class TestRedundantSafepointElimination { public static void main(String[] args) { diff --git a/test/hotspot/jtreg/compiler/rangechecks/TestFoldCompares.java b/test/hotspot/jtreg/compiler/rangechecks/TestFoldCompares.java index bec3e442403..b0df68b209a 100644 --- a/test/hotspot/jtreg/compiler/rangechecks/TestFoldCompares.java +++ b/test/hotspot/jtreg/compiler/rangechecks/TestFoldCompares.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, 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 @@ -27,14 +27,14 @@ * @summary Test logic in IfNode::fold_compares, which folds 2 signed comparisons * into a single comparison. * @library /test/lib / - * @run main ${test.main.class} + * @run driver ${test.main.class} */ /* * @test id=Xcomp * @bug 8346420 * @library /test/lib / - * @run main ${test.main.class} -Xcomp -XX:-TieredCompilation -XX:CompileCommand=compileonly,${test.main.class}::test* + * @run driver ${test.main.class} -Xcomp -XX:-TieredCompilation -XX:CompileCommand=compileonly,${test.main.class}::test* */ package compiler.rangechecks; diff --git a/test/hotspot/jtreg/compiler/stable/LazyConstantsIrTest.java b/test/hotspot/jtreg/compiler/stable/LazyConstantsIrTest.java index b9f9343dd39..8f967fae560 100644 --- a/test/hotspot/jtreg/compiler/stable/LazyConstantsIrTest.java +++ b/test/hotspot/jtreg/compiler/stable/LazyConstantsIrTest.java @@ -27,7 +27,7 @@ * @modules java.base/jdk.internal.lang * @library /test/lib / * @enablePreview - * @run main ${test.main.class} + * @run driver ${test.main.class} */ package compiler.stable; diff --git a/test/hotspot/jtreg/compiler/vectorization/TestRotateByteAndShortVector.java b/test/hotspot/jtreg/compiler/vectorization/TestRotateByteAndShortVector.java index 79cde2f0d26..4c448564a87 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestRotateByteAndShortVector.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestRotateByteAndShortVector.java @@ -29,7 +29,7 @@ * @key randomness * @summary Test vectorization of rotate byte and short * @library /test/lib / - * @run main/othervm TestRotateByteAndShortVector + * @run driver ${test.main.class} */ import java.util.Random; diff --git a/test/hotspot/jtreg/compiler/vectorization/TestRoundVectorDoubleRandom.java b/test/hotspot/jtreg/compiler/vectorization/TestRoundVectorDoubleRandom.java index 78dd4f50a06..e5a6966cdcf 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestRoundVectorDoubleRandom.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestRoundVectorDoubleRandom.java @@ -31,7 +31,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.math * @requires os.arch == "riscv64" & vm.cpu.features ~= ".*rvv.*" - * @run main compiler.vectorization.TestRoundVectorDoubleRandom + * @run driver ${test.main.class} */ package compiler.vectorization; diff --git a/test/hotspot/jtreg/compiler/vectorization/TestRoundVectorFloatRandom.java b/test/hotspot/jtreg/compiler/vectorization/TestRoundVectorFloatRandom.java index 474601346e8..92b6d3b9840 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestRoundVectorFloatRandom.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestRoundVectorFloatRandom.java @@ -31,7 +31,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.math * @requires os.arch == "riscv64" & vm.cpu.features ~= ".*rvv.*" - * @run main compiler.vectorization.TestRoundVectorFloatRandom + * @run driver ${test.main.class} */ package compiler.vectorization; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayCopyTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayCopyTest.java index 48b2ff754ad..f1140533d25 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayCopyTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayCopyTest.java @@ -24,18 +24,10 @@ /* * @test * @summary Vectorization test on array copy + * @requires vm.compiler2.enabled * @library /test/lib / * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.ArrayCopyTest - * - * @requires vm.compiler2.enabled + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java index 8d0ba2be589..3708fc87f29 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, 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 @@ -26,18 +26,10 @@ * @test * @summary Vectorization test on array index fill * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.ArrayIndexFillTest - * * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayInvariantFillTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayInvariantFillTest.java index b7044b1c79d..90e4955bee3 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayInvariantFillTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayInvariantFillTest.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. + * Copyright (c) 2026, 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 @@ -25,24 +26,11 @@ * @test * @summary Vectorization test on array invariant fill * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * -XX:-OptimizeFill - * compiler.vectorization.runner.ArrayInvariantFillTest - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * -XX:+OptimizeFill - * compiler.vectorization.runner.ArrayInvariantFillTest - * * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} NoOptimizeFill + * @run driver ${test.main.class} OptimizeFill */ package compiler.vectorization.runner; @@ -68,11 +56,22 @@ public class ArrayInvariantFillTest extends VectorizationTestRunner { doubleInv = ran.nextDouble(); } + // We must pass the flags directly to the Test VM, and not the Driver VM in the @run above. + @Override + protected String[] testVMFlags(String[] args) { + return switch (args[0]) { + case "NoOptimizeFill" -> new String[]{"-XX:-OptimizeFill"}; + case "OptimizeFill" -> new String[]{"-XX:+OptimizeFill"}; + default -> throw new RuntimeException("Test argument not recognized: " + args[0]); + }; + } + // ---------------- Simple Fill ---------------- @Test - @IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true", "rvv", "true"}, - applyIf = {"OptimizeFill", "false"}, - counts = {IRNode.REPLICATE_B, ">0"}) + // TODO 8387402 + //@IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true", "rvv", "true"}, + // applyIf = {"OptimizeFill", "false"}, + // counts = {IRNode.REPLICATE_B, ">0"}) @IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true", "rvv", "true"}, applyIf = {"OptimizeFill", "true"}, counts = {IRNode.REPLICATE_B, "0"}) diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java index e2d28cbf083..2699afda5cc 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2025, Rivos Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,18 +28,10 @@ * @bug 8183390 8332905 * @summary Vectorization test on bug-prone shift operation * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.ArrayShiftOpTest - * * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java index f9c5f6199f1..d6f2febb06f 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java @@ -27,33 +27,12 @@ * @bug 8183390 8340010 8342095 * @summary Vectorization test on array type conversions * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * * @requires vm.compiler2.enabled * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.ArrayTypeConvertTest nCOH_nAV - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.ArrayTypeConvertTest nCOH_yAV - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.ArrayTypeConvertTest yCOH_nAV - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.ArrayTypeConvertTest yCOH_yAV + * @run driver ${test.main.class} nCOH_nAV + * @run driver ${test.main.class} nCOH_yAV + * @run driver ${test.main.class} yCOH_nAV + * @run driver ${test.main.class} yCOH_yAV */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayUnsafeOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayUnsafeOpTest.java index 8b4513b8490..f6874a03ffb 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayUnsafeOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayUnsafeOpTest.java @@ -25,17 +25,9 @@ * @test * @summary Vectorization test on array unsafe operations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.ArrayUnsafeOpTest - * * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicBooleanOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicBooleanOpTest.java index ba82013e182..3a61b365800 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicBooleanOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicBooleanOpTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, 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 @@ -27,17 +27,9 @@ * @summary Vectorization test on basic boolean operations * @requires vm.opt.StressUnstableIfTraps == null | !vm.opt.StressUnstableIfTraps * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.BasicBooleanOpTest - * * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicByteOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicByteOpTest.java index a336b32f7b9..acbf44c471c 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicByteOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicByteOpTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, 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 @@ -26,19 +26,9 @@ * @test * @summary Vectorization test on basic byte operations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * -XX:CompileCommand=CompileOnly,compiler.vectorization.runner.BasicByteOpTest::* - * -XX:LoopUnrollLimit=1000 - * compiler.vectorization.runner.BasicByteOpTest - * * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; @@ -64,6 +54,12 @@ public class BasicByteOpTest extends VectorizationTestRunner { } } + // We must pass the flags directly to the test-VM, and not the driver vm in the @run above. + @Override + protected String[] testVMFlags(String[] args) { + return new String[]{"-XX:CompileCommand=CompileOnly,compiler.vectorization.runner.BasicByteOpTest::*", "-XX:LoopUnrollLimit=1000"}; + } + // ---------------- Arithmetic ---------------- @Test @IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true", "rvv", "true"}, diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java index 4211d5eec5e..be462f0be16 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java @@ -25,17 +25,9 @@ * @test * @summary Vectorization test on basic char operations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.BasicCharOpTest - * * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java index 8d5925ec8c6..1adb89591a5 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2025, Rivos Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -27,18 +27,10 @@ * @test * @summary Vectorization test on basic double operations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.BasicDoubleOpTest - * * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicFloatOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicFloatOpTest.java index b89d068d8af..870b8746baf 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicFloatOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicFloatOpTest.java @@ -25,18 +25,10 @@ * @test * @summary Vectorization test on basic float operations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.BasicFloatOpTest - * * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java index e096f7878ab..8849418e609 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicIntOpTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, 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 @@ -26,17 +26,9 @@ * @test * @summary Vectorization test on basic int operations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.BasicIntOpTest - * * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java index a6767054958..5404d943bbc 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, 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 @@ -26,18 +26,10 @@ * @test * @summary Vectorization test on basic long operations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.BasicLongOpTest - * * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java index b957a00278a..4c7221dea52 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java @@ -27,17 +27,9 @@ * @bug 8183390 8342095 * @summary Vectorization test on basic short operations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.BasicShortOpTest - * * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopArrayIndexComputeTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopArrayIndexComputeTest.java index c8a3c71bdee..27058012f36 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopArrayIndexComputeTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopArrayIndexComputeTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, 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 @@ -26,26 +26,13 @@ * @test * @summary Vectorization test on loop array index computation * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopArrayIndexComputeTest nAV_ySAC - * - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopArrayIndexComputeTest yAV_ySAC - * - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopArrayIndexComputeTest nAV_nSAC - * - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopArrayIndexComputeTest yAV_nSAC - * * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} nAV_ySAC + * @run driver ${test.main.class} yAV_ySAC + * @run driver ${test.main.class} nAV_nSAC + * @run driver ${test.main.class} yAV_nSAC */ package compiler.vectorization.runner; @@ -60,10 +47,10 @@ public class LoopArrayIndexComputeTest extends VectorizationTestRunner { @Override protected String[] testVMFlags(String[] args) { return switch (args[0]) { - case "nAV_ySAC" -> new String[]{"-XX:-AlignVector", "-XX:+UseAutoVectorizationSpeculativeAliasingChecks"}; - case "yAV_ySAC" -> new String[]{"-XX:+AlignVector", "-XX:+UseAutoVectorizationSpeculativeAliasingChecks"}; - case "nAV_nSAC" -> new String[]{"-XX:-AlignVector", "-XX:-UseAutoVectorizationSpeculativeAliasingChecks"}; - case "yAV_nSAC" -> new String[]{"-XX:+AlignVector", "-XX:-UseAutoVectorizationSpeculativeAliasingChecks"}; + case "nAV_ySAC" -> new String[]{"-XX:+UnlockDiagnosticVMOptions", "-XX:-AlignVector", "-XX:+UseAutoVectorizationSpeculativeAliasingChecks"}; + case "yAV_ySAC" -> new String[]{"-XX:+UnlockDiagnosticVMOptions", "-XX:+AlignVector", "-XX:+UseAutoVectorizationSpeculativeAliasingChecks"}; + case "nAV_nSAC" -> new String[]{"-XX:+UnlockDiagnosticVMOptions", "-XX:-AlignVector", "-XX:-UseAutoVectorizationSpeculativeAliasingChecks"}; + case "yAV_nSAC" -> new String[]{"-XX:+UnlockDiagnosticVMOptions", "-XX:+AlignVector", "-XX:-UseAutoVectorizationSpeculativeAliasingChecks"}; default -> { throw new RuntimeException("Test argument not recognized: " + args[0]); } }; } diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java index c46b2e11612..714de5b3c6b 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, 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 @@ -26,33 +26,12 @@ * @test * @summary Vectorization test on combined operations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * * @requires vm.compiler2.enabled * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopCombinedOpTest nCOH_nAV - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopCombinedOpTest nCOH_yAV - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopCombinedOpTest yCOH_nAV - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopCombinedOpTest yCOH_yAV + * @run driver ${test.main.class} nCOH_nAV + * @run driver ${test.main.class} nCOH_yAV + * @run driver ${test.main.class} yCOH_nAV + * @run driver ${test.main.class} yCOH_yAV */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopControlFlowTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopControlFlowTest.java index e36e4097813..51326956983 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopControlFlowTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopControlFlowTest.java @@ -25,17 +25,9 @@ * @test * @summary Vectorization test on simple control flow in loop * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopControlFlowTest - * * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopLiveOutNodesTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopLiveOutNodesTest.java index 06a3eb33bc3..cad2af04a9b 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopLiveOutNodesTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopLiveOutNodesTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, 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 @@ -26,17 +26,9 @@ * @test * @summary Vectorization test on loops with live out nodes * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopLiveOutNodesTest - * * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopRangeStrideTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopRangeStrideTest.java index 2db565461ac..a36d11198e7 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopRangeStrideTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopRangeStrideTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, 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 @@ -26,18 +26,10 @@ * @test * @summary Vectorization test on different loop ranges and strides * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopRangeStrideTest - * * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java index 546d99f5cce..9b9dcb03f6e 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java @@ -25,19 +25,10 @@ * @test * @summary Vectorization test on reduction operations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.LoopReductionOpTest - * * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") * @requires vm.compiler2.enabled * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/MultipleLoopsTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/MultipleLoopsTest.java index 4dbfba02a43..4be74d20733 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/MultipleLoopsTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/MultipleLoopsTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, 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 @@ -26,17 +26,9 @@ * @test * @summary Vectorization test on multiple loops in a method * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.vectorization.runner.MultipleLoopsTest - * * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/StripMinedLoopTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/StripMinedLoopTest.java index dbc999647ad..347571fc95b 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/StripMinedLoopTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/StripMinedLoopTest.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. + * Copyright (c) 2026, 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 @@ -25,18 +26,9 @@ * @test * @summary Vectorization test with small strip mining iterations * @library /test/lib / - * - * @build jdk.test.whitebox.WhiteBox - * compiler.vectorization.runner.VectorizationTestRunner - * - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * -XX:LoopStripMiningIter=10 - * compiler.vectorization.runner.StripMinedLoopTest - * * @requires vm.compiler2.enabled + * + * @run driver ${test.main.class} */ package compiler.vectorization.runner; @@ -59,6 +51,12 @@ public class StripMinedLoopTest extends VectorizationTestRunner { } } + // We must pass the flags directly to the Test VM, and not the Driver VM in the @run above. + @Override + protected String[] testVMFlags(String[] args) { + return new String[]{"-XX:LoopStripMiningIter=10"}; + } + @Test @IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true", "rvv", "true"}, counts = {IRNode.STORE_VECTOR, ">0"}) diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/VectorizationTestRunner.java b/test/hotspot/jtreg/compiler/vectorization/runner/VectorizationTestRunner.java index 7f8e4ec3b39..9adebf30d31 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/VectorizationTestRunner.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/VectorizationTestRunner.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. + * Copyright (c) 2026, 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 @@ -29,14 +30,23 @@ import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import jdk.test.lib.Utils; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.ProcessTools; import jdk.test.whitebox.WhiteBox; public class VectorizationTestRunner { - private static final WhiteBox WB = WhiteBox.getWhiteBox(); + private static final String VERIFY_CORRECTNESS_ARG = "--verify-vectorization-correctness"; + + private static class Flags { + private static final WhiteBox WHITEBOX = WhiteBox.getWhiteBox(); + } private static final int COMP_LEVEL_INTP = 0; private static final int COMP_LEVEL_C2 = 4; @@ -52,6 +62,35 @@ public class VectorizationTestRunner { // invokes it twice - first time in the interpreter and second time compiled // by C2. Then this runner compares the two return values. Hence we require // each test method returning a primitive value or an array of primitive type. + runCorrectnessTestsInTestVM(args); + + // 2) Vectorization ability test + // To test vectorizability, invoke the IR test framework to check existence of + // expected C2 IR node. + TestFramework irTest = new TestFramework(klass); + irTest.addFlags(testVMFlags(args)); + irTest.start(); + } + + private void runCorrectnessTestsInTestVM(String[] args) { + List command = new ArrayList<>(); + command.addAll(Arrays.asList(testVMFlags(args))); + command.add("-Xbootclasspath/a:."); + command.add("-XX:+UnlockDiagnosticVMOptions"); + command.add("-XX:+WhiteBoxAPI"); + command.add(getClass().getName()); + command.add(VERIFY_CORRECTNESS_ARG); + command.add(getClass().getName()); + try { + ClassFileInstaller.main("jdk.test.whitebox.WhiteBox"); + ProcessTools.executeTestJava(command).shouldHaveExitValue(0); + } catch (Exception e) { + throw new RuntimeException("Vectorization correctness test failed", e); + } + } + + private void runCorrectnessTests() { + Class klass = getClass(); for (Method method : klass.getDeclaredMethods()) { try { if (method.isAnnotationPresent(Test.class)) { @@ -63,13 +102,6 @@ public class VectorizationTestRunner { "." + method.getName() + ": " + e.getMessage()); } } - - // 2) Vectorization ability test - // To test vectorizability, invoke the IR test framework to check existence of - // expected C2 IR node. - TestFramework irTest = new TestFramework(klass); - irTest.addFlags(testVMFlags(args)); - irTest.start(); } // Override this to add extra flags. @@ -111,20 +143,20 @@ public class VectorizationTestRunner { // Temporarily disable the compiler and invoke the method to get reference // result from the interpreter - WB.setBooleanVMFlag("UseCompiler", false); + Flags.WHITEBOX.setBooleanVMFlag("UseCompiler", false); try { expected = method.invoke(this); } catch (Exception e) { e.printStackTrace(); fail("Exception is thrown in test method invocation (interpreter)."); } - assert(WB.getMethodCompilationLevel(method) == COMP_LEVEL_INTP); - WB.setBooleanVMFlag("UseCompiler", true); + assert(Flags.WHITEBOX.getMethodCompilationLevel(method) == COMP_LEVEL_INTP); + Flags.WHITEBOX.setBooleanVMFlag("UseCompiler", true); // Compile the method and invoke it again long enqueueTime = System.currentTimeMillis(); - WB.enqueueMethodForCompilation(method, COMP_LEVEL_C2); - while (WB.getMethodCompilationLevel(method) != COMP_LEVEL_C2) { + Flags.WHITEBOX.enqueueMethodForCompilation(method, COMP_LEVEL_C2); + while (Flags.WHITEBOX.getMethodCompilationLevel(method) != COMP_LEVEL_C2) { Thread.sleep(100 /*ms*/); } try { @@ -133,7 +165,7 @@ public class VectorizationTestRunner { e.printStackTrace(); fail("Exception is thrown in test method invocation (C2)."); } - assert(WB.getMethodCompilationLevel(method) == COMP_LEVEL_C2); + assert(Flags.WHITEBOX.getMethodCompilationLevel(method) == COMP_LEVEL_C2); // Check if two invocations return the same Class retType = method.getReturnType(); @@ -172,11 +204,10 @@ public class VectorizationTestRunner { } private static VectorizationTestRunner createTestInstance(String testName) { - if (!testName.toLowerCase().endsWith(".java")) { - fail("Invalid test file name " + testName); + if (testName.toLowerCase().endsWith(".java")) { + testName = testName.substring(0, testName.length() - 5); + testName = testName.replace('/', '.'); } - testName = testName.substring(0, testName.length() - 5); - testName = testName.replace('/', '.'); VectorizationTestRunner instance = null; try { @@ -196,7 +227,13 @@ public class VectorizationTestRunner { } public static void main(String[] args) { - VectorizationTestRunner testObj = createTestInstance(Utils.TEST_NAME); + VectorizationTestRunner testObj; + if (args.length > 0 && args[0].equals(VERIFY_CORRECTNESS_ARG)) { + testObj = createTestInstance(args[1]); + testObj.runCorrectnessTests(); + return; + } + testObj = createTestInstance(Utils.TEST_NAME); testObj.run(args); } } diff --git a/test/hotspot/jtreg/gtest/ShenandoahGtests.java b/test/hotspot/jtreg/gtest/ShenandoahGtests.java new file mode 100644 index 00000000000..1e8c404fc12 --- /dev/null +++ b/test/hotspot/jtreg/gtest/ShenandoahGtests.java @@ -0,0 +1,31 @@ +/* + * Copyright Amazon.com Inc. 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 + * @summary Run Shenandoah gtests + * @library /test/lib + * @requires vm.gc.Shenandoah + * @requires vm.debug + * @run main/native GTestWrapper --gtest_filter=Shenandoah* + */ diff --git a/test/hotspot/jtreg/runtime/cds/TestCDSVMCrash.java b/test/hotspot/jtreg/runtime/cds/TestCDSVMCrash.java index 8241b0f9a2e..2c796243cbf 100644 --- a/test/hotspot/jtreg/runtime/cds/TestCDSVMCrash.java +++ b/test/hotspot/jtreg/runtime/cds/TestCDSVMCrash.java @@ -62,7 +62,7 @@ public class TestCDSVMCrash { throw new Error("Expected VM to crash"); } catch(RuntimeException e) { if (!e.getMessage().contains("A fatal error has been detected")) { - throw new Error("Expected message: A fatal error has been detected"); + throw new Error("Expected message: A fatal error has been detected. Instead message is: " + e.getMessage()); } } System.out.println("PASSED"); diff --git a/test/jdk/javax/net/ssl/ciphersuites/BulkCipherDisabledAlgorithms.java b/test/jdk/javax/net/ssl/ciphersuites/BulkCipherDisabledAlgorithms.java new file mode 100644 index 00000000000..11f3efb1518 --- /dev/null +++ b/test/jdk/javax/net/ssl/ciphersuites/BulkCipherDisabledAlgorithms.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2026, IBM Corporation. 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 8387124 + * @summary Test TLS cipher suite disabling via jdk.tls.disabledAlgorithms, + * including matching on bulk cipher components, covering both + * visibility and handshake behavior. + * @library /test/lib + * /javax/net/ssl/TLSCommon + * /javax/net/ssl/templates + * @run main/othervm BulkCipherDisabledAlgorithms visibility + * @run main/othervm BulkCipherDisabledAlgorithms handshake + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.net.ssl.*; + +import jdk.test.lib.process.Proc; + +import java.security.NoSuchAlgorithmException; +import java.security.Security; + +public class BulkCipherDisabledAlgorithms { + + public static void main(String[] args) throws Exception { + if (args.length == 0) { + throw new RuntimeException("Missing mode argument"); + } + + String mode = args[0]; + boolean isVisibilityTest = "visibility".equals(mode); + boolean isHandshakeTest = "handshake".equals(mode); + + if (args.length == 1) { + List tests = buildTests(isVisibilityTest); + + for (String[] test : tests) { + String suite = test[0]; + String disabled = test[1]; + String expected = test[2]; + + System.out.println("================================================="); + System.out.println("Testing: " + mode + + ", suite=" + suite + + ", disabled=" + disabled + + ", expected=" + expected); + + Proc p = Proc.create( + BulkCipherDisabledAlgorithms.class.getName()) + .args(mode, suite, expected) + .secprop("jdk.tls.disabledAlgorithms", disabled) + .inheritIO(); + + p.start().waitFor(0); + } + + System.out.println("TEST PASS - OK"); + return; + } + + String suite = args[1]; + String expected = args[2]; + boolean expectedDisabled = "disabled".equals(expected); + + if (isVisibilityTest) { + testCipherSuiteVisibility(suite, expectedDisabled); + } + + if (isHandshakeTest) { + testHandshake(suite, expectedDisabled); + } + } + + // Returns cipher suites for testing. + // - true: use all supported suites (independent of disabledAlgorithms) + // - false: use default enabled suites (candidates for handshake) + private static CipherSuite[] getCipherSuites(boolean useSupportedSuites) + throws NoSuchAlgorithmException { + SSLEngine engine = SSLContext.getDefault().createSSLEngine(); + String[] suites = useSupportedSuites + ? engine.getSupportedCipherSuites() + : engine.getEnabledCipherSuites(); + + return Arrays.stream(suites) + .map(CipherSuite::cipherSuite) + .filter(cs -> cs != CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + .toArray(CipherSuite[]::new); + } + + private static List buildTests(boolean useSupportedSuites) + throws NoSuchAlgorithmException { + if (useSupportedSuites) { + // disabledAlgorithms limits supported suites; clear to list all + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + } + + List tests = new ArrayList<>(); + CipherSuite[] suites = getCipherSuites(useSupportedSuites); + + for (CipherSuite suite : suites) { + String suiteName = suite.name(); + String bulk = extractBulkCipher(suiteName); + + tests.add(new String[] { suiteName, suiteName, "disabled" }); + tests.add(new String[] { suiteName, bulk, "disabled" }); + + for (CipherSuite other : suites) { + // Negative test case: disable a different bulk cipher than the one + // used by the current suite. This ensures that the suite remains + // enabled and a successful TLS handshake can still be negotiated. + if (other == suite) { + continue; + } + + String otherBulk = extractBulkCipher(other.name()); + + if (!bulk.equals(otherBulk) + && !suiteName.contains(otherBulk)) { + tests.add(new String[] { suiteName, otherBulk, "enabled" }); + break; + } + } + } + + return tests; + } + + /** + * Separator used in TLS cipher suite names to mark the start of + * the bulk cipher component (e.g. TLS_RSA_WITH_AES_128_CBC_SHA). + */ + private static final String WITH = "_WITH_"; + + private static String extractBulkCipher(String suite) { + if (suite.contains(WITH)) { + String after = suite.substring(suite.indexOf(WITH) + WITH.length()); + int last = after.lastIndexOf('_'); + return after.substring(0, last); + } else { + int first = suite.indexOf('_'); + int last = suite.lastIndexOf('_'); + return suite.substring(first + 1, last); + } + } + + private static void testCipherSuiteVisibility(String suite, boolean expectedDisabled) + throws NoSuchAlgorithmException { + boolean visible = Arrays.asList(getCipherSuites(true)) + .contains(CipherSuite.cipherSuite(suite)); + + if (!expectedDisabled && !visible) { + throw new RuntimeException( + "Cipher suite '" + suite + "' not visible but expected to be enabled"); + } else if (expectedDisabled && visible) { + throw new RuntimeException( + "Cipher suite '" + suite + "' visible but expected to be disabled"); + } + } + + private static void testHandshake(String suite, boolean expectedDisabled) throws Exception { + try { + new TLSHandshakeTest(suite).run(); + + if (expectedDisabled) { + throw new RuntimeException( + "Handshake succeeded but should fail: " + suite); + } + } catch (SSLHandshakeException e) { + if (!expectedDisabled) { + throw new RuntimeException( + "Handshake failed unexpectedly: " + suite, e); + } + } + } + + private static class TLSHandshakeTest extends SSLSocketTemplate { + private final String suite; + + TLSHandshakeTest(String suite) { + this.suite = suite; + } + + @Override + protected void configureClientSocket(SSLSocket socket) { + socket.setEnabledCipherSuites(new String[] { suite }); + } + + @Override + protected void configureServerSocket(SSLServerSocket socket) { + socket.setEnabledCipherSuites(new String[] { suite }); + } + } +} diff --git a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java index c2c58b36c38..82b6a6c257e 100644 --- a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java +++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java @@ -28,7 +28,7 @@ * 8223499 8225392 8232019 8234245 8233223 8225068 8225069 8243321 8243320 * 8243559 8225072 8258630 8259312 8256421 8225081 8225082 8225083 8245654 * 8305975 8304760 8307134 8295894 8314960 8317373 8317374 8318759 8319187 - * 8321408 8316138 8341057 8303770 8350498 8359170 8361212 8372351 + * 8321408 8316138 8341057 8303770 8350498 8359170 8361212 8372351 8387123 * @summary Check root CA entries in cacerts file */ import java.io.ByteArrayInputStream; @@ -47,12 +47,12 @@ public class VerifyCACerts { + File.separator + "security" + File.separator + "cacerts"; // The numbers of certs now. - private static final int COUNT = 111; + private static final int COUNT = 110; // SHA-256 of cacerts, can be generated with // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 private static final String CHECKSUM - = "26:75:A0:AA:6E:7C:15:8B:BC:CF:11:81:38:3E:E7:94:31:9E:36:2D:F9:A6:BC:88:E1:A5:F8:46:9A:4C:1D:D7"; + = "AA:C2:64:41:28:06:1F:83:92:54:7C:DD:95:82:61:4C:8F:FA:09:7B:17:64:A7:A8:7C:A9:F6:27:25:95:2D:BB"; // Hex formatter to upper case with ":" delimiter private static final HexFormat HEX = HexFormat.ofDelimiter(":").withUpperCase(); @@ -143,8 +143,6 @@ public class VerifyCACerts { "96:BC:EC:06:26:49:76:F3:74:60:77:9A:CF:28:C5:A7:CF:E8:A3:C0:AA:E1:1A:8F:FC:EE:05:C0:BD:DF:08:C6"); put("letsencryptisrgx2 [jdk]", "69:72:9B:8E:15:A8:6E:FC:17:7A:57:AF:B7:17:1D:FC:64:AD:D2:8C:2F:CA:8C:F1:50:7E:34:45:3C:CB:14:70"); - put("luxtrustglobalrootca [jdk]", - "A1:B2:DB:EB:64:E7:06:C6:16:9E:3C:41:18:B2:3B:AA:09:01:8A:84:27:66:6D:8B:F0:E2:88:91:EC:05:19:50"); put("quovadisrootca [jdk]", "A4:5E:DE:3B:BB:F0:9C:8A:E1:5C:72:EF:C0:72:68:D6:93:A2:1C:99:6F:D5:1E:67:CA:07:94:60:FD:6D:88:73"); put("quovadisrootca1g3 [jdk]", @@ -296,8 +294,6 @@ public class VerifyCACerts { add("addtrustexternalca [jdk]"); // Valid until: Sat May 30 10:44:50 GMT 2020 add("addtrustqualifiedca [jdk]"); - // Valid until: Wed Mar 17 02:51:37 PDT 2021 - add("luxtrustglobalrootca [jdk]"); // Valid until: Wed Mar 17 11:33:33 PDT 2021 add("quovadisrootca [jdk]"); // Valid until: Sat May 21 04:00:00 GMT 2022 diff --git a/test/jdk/sun/security/ssl/CipherSuite/TLS13BulkCipherDisabledCipherSuite.java b/test/jdk/sun/security/ssl/CipherSuite/TLS13BulkCipherDisabledCipherSuite.java new file mode 100644 index 00000000000..87a6f156152 --- /dev/null +++ b/test/jdk/sun/security/ssl/CipherSuite/TLS13BulkCipherDisabledCipherSuite.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2026, IBM Corporation. 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 8387124 + * @summary Test disabling TLS 1.3 cipher suites with bulk ciphers names + * @run testng/othervm TLS13BulkCipherDisabledCipherSuite + */ + +import static org.testng.AssertJUnit.assertTrue; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.security.Security; +import java.util.List; + +public class TLS13BulkCipherDisabledCipherSuite extends AbstractDisableCipherSuites { + + private static final String SECURITY_PROPERTY = "jdk.tls.disabledAlgorithms"; + private static final String TEST_ALGORITHMS = "AES_256_GCM," + + " AES_128_GCM," + + " CHACHA20_POLY1305"; + private static final String[] CIPHER_SUITES = new String[] { + "TLS_AES_256_GCM_SHA384", + "TLS_AES_128_GCM_SHA256", + "TLS_CHACHA20_POLY1305_SHA256" + }; + static final List CIPHER_SUITES_IDS = List.of( + 0x1301, + 0x1302, + 0x1303); + + @Override + protected String getProtocol() { + return "TLSv1.3"; + } + + @BeforeTest + void setUp() throws Exception { + Security.setProperty(SECURITY_PROPERTY, TEST_ALGORITHMS); + } + + @Test + public void testDefault() throws Exception { + assertTrue(testDefaultCase(CIPHER_SUITES_IDS)); + } + + @Test + public void testAddDisabled() throws Exception { + assertTrue(testEngAddDisabled(CIPHER_SUITES, CIPHER_SUITES_IDS)); + } + + @Test + public void testOnlyDisabled() throws Exception { + assertTrue(testEngOnlyDisabled(CIPHER_SUITES)); + } +} diff --git a/test/lib/jdk/test/lib/cds/CDSTestUtils.java b/test/lib/jdk/test/lib/cds/CDSTestUtils.java index 59e4a1bbbde..8060eb92a87 100644 --- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java @@ -703,7 +703,7 @@ public class CDSTestUtils { static String getCrashMessage(String stdOut) { int start = stdOut.indexOf("# A fatal error has been detected by the Java Runtime Environment:"); - int end = stdOut.indexOf(".log", start) + 4; + int end = stdOut.indexOf("# JRE version", start); return stdOut.substring(start, end); }