Author SHA1 Message Date
DingliZhang c7a5e95ad5 8367293: RISC-V: enable vectorapi test for VectorMask.laneIsSet
OpenJDK GHA Sanity Checks / Prepare the run (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-nopch (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-zero (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-minimal (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-optimized (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-static (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-static-libs (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-cross-compile (push) Has been cancelled
OpenJDK GHA Sanity Checks / alpine-linux-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / macos-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / macos-aarch64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / windows-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / windows-aarch64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / docs (push) Has been cancelled
2025-09-10 10:18:56 +08:00
erifan 53b3e0567d 8366588: VectorAPI: Re-intrinsify VectorMask.laneIsSet where the input index is a variable
Reviewed-by: shade, xgong, epeter
2025-09-10 01:49:55 +00:00
Leonid Mesnik 8cd4e7d856 8365192: post_meth_exit should be in vm state when calling get_jvmti_thread_state
Reviewed-by: mdoerr, dholmes
2025-09-09 23:50:33 +00:00
Dean LongandMartin Doerr f96403986b 8361376: Regressions 1-6% in several Renaissance in 26-b4 only MacOSX aarch64
Co-authored-by: Martin Doerr <mdoerr@openjdk.org>
Reviewed-by: mdoerr, aph, eosterlund
2025-09-09 23:27:33 +00:00
Justin Lu 24a734938e 8366733: Re-examine older java.text NF, DF, and DFS serialization tests
Reviewed-by: naoto
2025-09-09 22:03:25 +00:00
Naoto Sato a12e9fcebd 8366261: Provide utility methods for sun.security.util.Password
Reviewed-by: smarks, weijun
2025-09-09 19:37:57 +00:00
Daniel Jeliński cc6d34b2fa 8366971: C2: Remove unused nop_list from PhaseOutput::init_buffer
Reviewed-by: epeter, dlong
2025-09-09 15:08:30 +00:00
Kim Barrett b653ae92d5 8367051: Build failure with clang on linux and AIX after switch to C++17
Reviewed-by: dholmes, ayang, mbaesken, mdoerr
2025-09-09 15:02:54 +00:00
Saint Wesonga f10c85fbc3 8367027: java/lang/ProcessBuilder/Basic.java fails on Windows AArch64
Reviewed-by: rriggs
2025-09-09 13:13:08 +00:00
Marc Chevalier 0632617670 8367135: Test compiler/loopstripmining/CheckLoopStripMining.java needs internal timeouts adjusted
Reviewed-by: thartmann, chagedorn
2025-09-09 11:17:48 +00:00
Stefan Karlsson a1ab12b772 8366854: Extend jtreg failure handler with THP info
Reviewed-by: ayang, shade, tschatzl, lmesnik, sjohanss
2025-09-09 11:17:33 +00:00
Magnus Ihse Bursie a25dde6279 8365231: Don't build gtest with /EHsc
Reviewed-by: kbarrett, stuefe
2025-09-09 10:58:21 +00:00
Johannes Bechberger 002f936ef2 8366082: Improve queue size computation in CPU-time sampler
Reviewed-by: jbachorik
2025-09-09 10:16:22 +00:00
Johannes Bechberger 4fc917c250 8366486: Test jdk/jfr/event/profiling/TestCPUTimeSampleMultipleRecordings.java is timing out
Reviewed-by: jbachorik
2025-09-09 10:15:53 +00:00
Hamlin Li f51e442b0e 8367098: RISC-V: sync CPU features with related JVM flags for dependant ones
Reviewed-by: fyang
2025-09-09 09:29:23 +00:00
Paul Hübner cfb809344c 8364103: Convert existing sprintf-chains to stringStream
Reviewed-by: kbarrett, dholmes, iklam
2025-09-09 09:01:46 +00:00
Johan Sjölen e16c510071 8367231: [BACKOUT] JDK-8366363: MemBaseline accesses VMT without using lock
Reviewed-by: kbarrett, dholmes
2025-09-09 08:14:55 +00:00
Francesco Andreuzzi 67bb22f3d6 8367085: Sort os/posix includes
Reviewed-by: ayang, dholmes
2025-09-09 07:36:57 +00:00
Johan SjölenandCasper Norrbin ecfba66d3d 8366363: MemBaseline accesses VMT without using lock
Co-authored-by: Casper Norrbin <cnorrbin@openjdk.org>
Reviewed-by: azafari, cnorrbin
2025-09-09 07:31:14 +00:00
erifan 680bf75898 8365911: AArch64: Fix encoding error in sve_cpy for negative floats
Reviewed-by: aph, epeter
2025-09-09 06:58:00 +00:00
78 changed files with 1468 additions and 1143 deletions
+2 -3
View File
@@ -62,13 +62,13 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBGTEST, \
DISABLED_WARNINGS_gcc := format-nonliteral maybe-uninitialized undef \
unused-result zero-as-null-pointer-constant, \
DISABLED_WARNINGS_clang := format-nonliteral undef unused-result, \
DISABLED_WARNINGS_microsoft := 4530, \
DEFAULT_CFLAGS := false, \
CFLAGS := $(JVM_CFLAGS) \
-I$(GTEST_FRAMEWORK_SRC)/googletest \
-I$(GTEST_FRAMEWORK_SRC)/googletest/include \
-I$(GTEST_FRAMEWORK_SRC)/googlemock \
-I$(GTEST_FRAMEWORK_SRC)/googlemock/include, \
CFLAGS_windows := -EHsc, \
CFLAGS_macosx := -DGTEST_OS_MAC=1, \
OPTIMIZATION := $(JVM_OPTIMIZATION), \
COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
@@ -98,7 +98,6 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \
-I$(GTEST_FRAMEWORK_SRC)/googletest/include \
-I$(GTEST_FRAMEWORK_SRC)/googlemock/include \
$(addprefix -I, $(GTEST_TEST_SRC)), \
CFLAGS_windows := -EHsc, \
CFLAGS_macosx := -DGTEST_OS_MAC=1, \
DISABLED_WARNINGS_gcc := $(DISABLED_WARNINGS_gcc) \
undef stringop-overflow, \
@@ -110,7 +109,7 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \
self-assign-overloaded, \
DISABLED_WARNINGS_clang_test_g1ServiceThread.cpp := delete-abstract-non-virtual-dtor, \
DISABLED_WARNINGS_clang_test_logDecorations.cpp := missing-field-initializers, \
DISABLED_WARNINGS_microsoft := $(DISABLED_WARNINGS_microsoft), \
DISABLED_WARNINGS_microsoft := $(DISABLED_WARNINGS_microsoft) 4530, \
LD_SET_ORIGIN := false, \
DEFAULT_LDFLAGS := false, \
LDFLAGS := $(JVM_LDFLAGS), \
-3
View File
@@ -5965,9 +5965,6 @@ attributes %{
instruction_unit_size = 4; // An instruction is 4 bytes long
instruction_fetch_unit_size = 64; // The processor fetches one line
instruction_fetch_units = 1; // of 64 bytes
// List of nop instructions
nops( MachNop );
%}
// We don't use an actual pipeline model so don't care about resources
@@ -3814,7 +3814,11 @@ private:
starti;
assert(T != Q, "invalid size");
int sh = 0;
if (imm8 <= 127 && imm8 >= -128) {
if (isFloat) {
assert(T != B, "invalid size");
assert((imm8 >> 8) == 0, "invalid immediate");
sh = 0;
} else if (imm8 <= 127 && imm8 >= -128) {
sh = 0;
} else if (T != B && imm8 <= 32512 && imm8 >= -32768 && (imm8 & 0xff) == 0) {
sh = 1;
@@ -3824,7 +3828,7 @@ private:
}
int m = isMerge ? 1 : 0;
f(0b00000101, 31, 24), f(T, 23, 22), f(0b01, 21, 20);
prf(Pg, 16), f(isFloat ? 1 : 0, 15), f(m, 14), f(sh, 13), sf(imm8, 12, 5), rf(Zd, 0);
prf(Pg, 16), f(isFloat ? 1 : 0, 15), f(m, 14), f(sh, 13), f(imm8 & 0xff, 12, 5), rf(Zd, 0);
}
public:
@@ -3834,7 +3838,7 @@ public:
}
// SVE copy floating-point immediate to vector elements (predicated)
void sve_cpy(FloatRegister Zd, SIMD_RegVariant T, PRegister Pg, double d) {
sve_cpy(Zd, T, Pg, checked_cast<int8_t>(pack(d)), /*isMerge*/true, /*isFloat*/true);
sve_cpy(Zd, T, Pg, checked_cast<uint8_t>(pack(d)), /*isMerge*/true, /*isFloat*/true);
}
// SVE conditionally select elements from two vectors
@@ -115,8 +115,22 @@ public:
return Atomic::load_acquire(guard_addr());
}
void set_value(int value) {
Atomic::release_store(guard_addr(), value);
void set_value(int value, int bit_mask) {
if (bit_mask == ~0) {
Atomic::release_store(guard_addr(), value);
return;
}
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
value &= bit_mask;
int old_value = Atomic::load(guard_addr());
while (true) {
// Only bits in the mask are changed
int new_value = value | (old_value & ~bit_mask);
if (new_value == old_value) break;
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
if (v == old_value) break;
old_value = v;
}
}
bool check_barrier(err_msg& msg) const;
@@ -179,7 +193,7 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
new_frame->pc = SharedRuntime::get_handle_wrong_method_stub();
}
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
if (!supports_entry_barrier(nm)) {
return;
}
@@ -196,7 +210,7 @@ void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
}
NativeNMethodBarrier barrier(nm);
barrier.set_value(value);
barrier.set_value(value, bit_mask);
}
int BarrierSetNMethod::guard_value(nmethod* nm) {
-3
View File
@@ -2638,9 +2638,6 @@ attributes %{
instruction_unit_size = 4; // An instruction is 4 bytes long
instruction_fetch_unit_size = 16; // The processor fetches one line
instruction_fetch_units = 1; // of 16 bytes
// List of nop instructions
nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR );
%}
//----------RESOURCES----------------------------------------------------------
@@ -51,8 +51,22 @@ public:
return Atomic::load_acquire(guard_addr());
}
void set_value(int value) {
Atomic::release_store(guard_addr(), value);
void set_value(int value, int bit_mask) {
if (bit_mask == ~0) {
Atomic::release_store(guard_addr(), value);
return;
}
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
value &= bit_mask;
int old_value = Atomic::load(guard_addr());
while (true) {
// Only bits in the mask are changed
int new_value = value | (old_value & ~bit_mask);
if (new_value == old_value) break;
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
if (v == old_value) break;
old_value = v;
}
}
void verify() const;
@@ -115,7 +129,7 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
new_frame->pc = SharedRuntime::get_handle_wrong_method_stub();
}
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
if (!supports_entry_barrier(nm)) {
return;
}
@@ -123,7 +137,7 @@ void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
// Disarms the nmethod guard emitted by BarrierSetAssembler::nmethod_entry_barrier.
// Symmetric "LDR; DMB ISHLD" is in the nmethod barrier.
NativeNMethodBarrier* barrier = native_nmethod_barrier(nm);
barrier->set_value(value);
barrier->set_value(value, bit_mask);
}
int BarrierSetNMethod::guard_value(nmethod* nm) {
@@ -183,12 +183,9 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register t
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
assert_different_registers(tmp, R0);
__ block_comment("nmethod_entry_barrier (nmethod_entry_barrier) {");
__ align(8); // must align the following block which requires atomic updates
// Load stub address using toc (fixed instruction size, unlike load_const_optimized)
__ calculate_address_from_global_toc(tmp, StubRoutines::method_entry_barrier(),
true, true, false); // 2 instructions
__ mtctr(tmp);
__ block_comment("nmethod_entry_barrier (nmethod_entry_barrier) {");
// This is a compound instruction. Patching support is provided by NativeMovRegMem.
// Actual patching is done in (platform-specific part of) BarrierSetNMethod.
@@ -198,6 +195,11 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register t
__ ld(R0, in_bytes(bs_nm->thread_disarmed_guard_value_offset()), R16_thread);
__ cmpw(CR0, R0, tmp);
// Load stub address using toc (fixed instruction size, unlike load_const_optimized)
__ calculate_address_from_global_toc(tmp, StubRoutines::method_entry_barrier(),
true, true, false); // 2 instructions
__ mtctr(tmp);
__ bnectrl(CR0);
// Oops may have been changed. Make those updates observable.
@@ -38,7 +38,7 @@ class NativeNMethodBarrier: public NativeInstruction {
NativeMovRegMem* get_patchable_instruction_handle() const {
// Endianness is handled by NativeMovRegMem
return reinterpret_cast<NativeMovRegMem*>(get_barrier_start_address() + 3 * 4);
return reinterpret_cast<NativeMovRegMem*>(get_barrier_start_address());
}
public:
@@ -47,7 +47,7 @@ public:
return get_patchable_instruction_handle()->offset();
}
void release_set_guard_value(int value) {
void release_set_guard_value(int value, int bit_mask) {
// Patching is not atomic.
// Stale observations of the "armed" state is okay as invoking the barrier stub in that case has no
// unwanted side effects. Disarming is thus a non-critical operation.
@@ -55,8 +55,37 @@ public:
OrderAccess::release(); // Release modified oops
// Set the guard value (naming of 'offset' function is misleading).
get_patchable_instruction_handle()->set_offset(value);
if (bit_mask == ~0) {
// Set the guard value (naming of 'offset' function is misleading).
get_patchable_instruction_handle()->set_offset(value);
return;
}
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
value &= bit_mask;
NativeMovRegMem* mov = get_patchable_instruction_handle();
assert(align_up(mov->instruction_address(), sizeof(uint64_t)) ==
align_down(mov->instruction_address(), sizeof(uint64_t)), "instruction not aligned");
uint64_t *instr = (uint64_t*)mov->instruction_address();
assert(NativeMovRegMem::instruction_size == sizeof(*instr), "must be");
union {
u_char buf[NativeMovRegMem::instruction_size];
uint64_t u64;
} new_mov_instr, old_mov_instr;
new_mov_instr.u64 = old_mov_instr.u64 = Atomic::load(instr);
while (true) {
// Only bits in the mask are changed
int old_value = nativeMovRegMem_at(old_mov_instr.buf)->offset();
int new_value = value | (old_value & ~bit_mask);
if (new_value == old_value) return; // skip icache flush if nothing changed
nativeMovRegMem_at(new_mov_instr.buf)->set_offset(new_value, false /* no icache flush */);
// Swap in the new value
uint64_t v = Atomic::cmpxchg(instr, old_mov_instr.u64, new_mov_instr.u64, memory_order_relaxed);
if (v == old_mov_instr.u64) break;
old_mov_instr.u64 = v;
}
ICache::ppc64_flush_icache_bytes(addr_at(0), NativeMovRegMem::instruction_size);
}
void verify() const {
@@ -66,12 +95,6 @@ public:
uint* current_instruction = reinterpret_cast<uint*>(get_barrier_start_address());
// calculate_address_from_global_toc (compound instruction)
verify_op_code_manually(current_instruction, MacroAssembler::is_addis(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_addi(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_mtctr(*current_instruction));
get_patchable_instruction_handle()->verify();
current_instruction += 2;
@@ -80,6 +103,12 @@ public:
// cmpw (mnemonic)
verify_op_code(current_instruction, Assembler::CMP_OPCODE);
// calculate_address_from_global_toc (compound instruction)
verify_op_code_manually(current_instruction, MacroAssembler::is_addis(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_addi(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_mtctr(*current_instruction));
// bnectrl (mnemonic) (weak check; not checking the exact type)
verify_op_code(current_instruction, Assembler::BCCTR_OPCODE);
@@ -117,13 +146,13 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
// Thus, there's nothing to do here.
}
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
if (!supports_entry_barrier(nm)) {
return;
}
NativeNMethodBarrier* barrier = get_nmethod_barrier(nm);
barrier->release_set_guard_value(value);
barrier->release_set_guard_value(value, bit_mask);
}
int BarrierSetNMethod::guard_value(nmethod* nm) {
+4 -2
View File
@@ -462,7 +462,7 @@ class NativeMovRegMem: public NativeInstruction {
return ((*hi_ptr) << 16) | ((*lo_ptr) & 0xFFFF);
}
void set_offset(intptr_t x) {
void set_offset(intptr_t x, bool flush_icache = true) {
#ifdef VM_LITTLE_ENDIAN
short *hi_ptr = (short*)(addr_at(0));
short *lo_ptr = (short*)(addr_at(4));
@@ -472,7 +472,9 @@ class NativeMovRegMem: public NativeInstruction {
#endif
*hi_ptr = x >> 16;
*lo_ptr = x & 0xFFFF;
ICache::ppc64_flush_icache_bytes(addr_at(0), NativeMovRegMem::instruction_size);
if (flush_icache) {
ICache::ppc64_flush_icache_bytes(addr_at(0), NativeMovRegMem::instruction_size);
}
}
void add_offset_in_bytes(intptr_t radd_offset) {
-4
View File
@@ -4920,10 +4920,6 @@ attributes %{
// ...in one line
instruction_fetch_units = 1
// Unused, list one so that array generated by adlc is not empty.
// Aix compiler chokes if _nop_count = 0.
nops(fxNop);
%}
//----------RESOURCES----------------------------------------------------------
@@ -109,8 +109,22 @@ public:
return Atomic::load_acquire(guard_addr());
}
void set_value(int value) {
Atomic::release_store(guard_addr(), value);
void set_value(int value, int bit_mask) {
if (bit_mask == ~0) {
Atomic::release_store(guard_addr(), value);
return;
}
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
value &= bit_mask;
int old_value = Atomic::load(guard_addr());
while (true) {
// Only bits in the mask are changed
int new_value = value | (old_value & ~bit_mask);
if (new_value == old_value) break;
int v = Atomic::cmpxchg(guard_addr(), old_value, new_value, memory_order_release);
if (v == old_value) break;
old_value = v;
}
}
bool check_barrier(err_msg& msg) const;
@@ -192,7 +206,7 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
new_frame->pc = SharedRuntime::get_handle_wrong_method_stub();
}
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
if (!supports_entry_barrier(nm)) {
return;
}
@@ -209,7 +223,7 @@ void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
}
NativeNMethodBarrier barrier(nm);
barrier.set_value(value);
barrier.set_value(value, bit_mask);
}
int BarrierSetNMethod::guard_value(nmethod* nm) {
-3
View File
@@ -3845,9 +3845,6 @@ attributes %{
// ...in one line.
instruction_fetch_units = 1;
// List of nop instructions
nops( MachNop );
%}
// We don't use an actual pipeline model so don't care about resources
@@ -182,11 +182,6 @@ void VM_Version::common_initialize() {
}
if (UseZicboz) {
if (zicboz_block_size.enabled()) {
assert(UseZic64b ? zicboz_block_size.value()== 64 : true, "Zicboz block size should be 64 when UseZic64b is true");
assert(is_power_of_2(zicboz_block_size.value()), "CacheLineSize must be a power of 2");
FLAG_SET_DEFAULT(CacheLineSize, zicboz_block_size.value());
}
if (FLAG_IS_DEFAULT(UseBlockZeroing)) {
FLAG_SET_DEFAULT(UseBlockZeroing, true);
}
+60 -59
View File
@@ -86,25 +86,27 @@ class VM_Version : public Abstract_VM_Version {
} \
} \
#define UPDATE_DEFAULT_DEP(flag, dep) \
void update_flag() { \
assert(enabled(), "Must be."); \
/* dep must be declared before */ \
assert((uintptr_t)(this) > \
(uintptr_t)(&dep), "Invalid");\
if (FLAG_IS_DEFAULT(flag)) { \
if (dep.enabled()) { \
FLAG_SET_DEFAULT(flag, true); \
} else { \
FLAG_SET_DEFAULT(flag, false); \
} \
} else { \
/* Sync CPU features with flags */ \
if (!flag) { \
disable_feature(); \
} \
} \
} \
#define UPDATE_DEFAULT_DEP(flag, dep) \
void update_flag() { \
assert(enabled(), "Must be."); \
/* dep must be declared before */ \
assert((uintptr_t)(this) > \
(uintptr_t)(&dep), "Invalid"); \
if (FLAG_IS_DEFAULT(flag)) { \
if (dep.enabled()) { \
FLAG_SET_DEFAULT(flag, true); \
} else { \
FLAG_SET_DEFAULT(flag, false); \
/* Sync CPU features with flags */ \
disable_feature(); \
} \
} else { \
/* Sync CPU features with flags */ \
if (!flag) { \
disable_feature(); \
} \
} \
} \
#define NO_UPDATE_DEFAULT \
void update_flag() {} \
@@ -160,46 +162,45 @@ class VM_Version : public Abstract_VM_Version {
// Note: the order matters, depender should be after their dependee. E.g. ext_V before ext_Zvbb.
// declaration name , extension name, bit pos ,in str, mapped flag)
#define RV_FEATURE_FLAGS(decl) \
decl(ext_I , "i" , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_M , "m" , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_A , "a" , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_F , "f" , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_D , "d" , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_C , "c" , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \
decl(ext_Q , "q" , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_H , "h" , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_V , "v" , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \
decl(ext_Zicbom , "Zicbom" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \
decl(ext_Zicboz , "Zicboz" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \
decl(ext_Zicbop , "Zicbop" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \
decl(ext_Zba , "Zba" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \
decl(ext_Zbb , "Zbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \
decl(ext_Zbc , "Zbc" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zbs , "Zbs" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \
decl(ext_Zbkb , "Zbkb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \
decl(ext_Zcb , "Zcb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \
decl(ext_Zfa , "Zfa" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \
decl(ext_Zfh , "Zfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \
decl(ext_Zfhmin , "Zfhmin" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \
decl(ext_Zicsr , "Zicsr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zicntr , "Zicntr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zifencei , "Zifencei" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zic64b , "Zic64b" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \
decl(ext_Ztso , "Ztso" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \
decl(ext_Zihintpause , "Zihintpause" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \
decl(ext_Zacas , "Zacas" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \
decl(ext_Zvbb , "Zvbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, ext_V)) \
decl(ext_Zvbc , "Zvbc" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, ext_V)) \
decl(ext_Zvfh , "Zvfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, ext_V)) \
decl(ext_Zvkn , "Zvkn" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, ext_V)) \
decl(ext_Zicond , "Zicond" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \
decl(mvendorid , "VendorId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(marchid , "ArchId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(mimpid , "ImpId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(unaligned_access , "Unaligned" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(satp_mode , "SATP" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(zicboz_block_size, "ZicbozBlockSize", RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
#define RV_FEATURE_FLAGS(decl) \
decl(ext_I , "i" , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_M , "m" , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_A , "a" , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_F , "f" , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_D , "d" , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_C , "c" , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \
decl(ext_Q , "q" , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_H , "h" , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_V , "v" , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \
decl(ext_Zicbom , "Zicbom" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \
decl(ext_Zicboz , "Zicboz" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \
decl(ext_Zicbop , "Zicbop" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \
decl(ext_Zba , "Zba" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \
decl(ext_Zbb , "Zbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \
decl(ext_Zbc , "Zbc" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zbs , "Zbs" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \
decl(ext_Zbkb , "Zbkb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \
decl(ext_Zcb , "Zcb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \
decl(ext_Zfa , "Zfa" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \
decl(ext_Zfh , "Zfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \
decl(ext_Zfhmin , "Zfhmin" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \
decl(ext_Zicsr , "Zicsr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zicntr , "Zicntr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zifencei , "Zifencei" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zic64b , "Zic64b" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \
decl(ext_Ztso , "Ztso" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \
decl(ext_Zihintpause , "Zihintpause" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \
decl(ext_Zacas , "Zacas" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \
decl(ext_Zvbb , "Zvbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, ext_V)) \
decl(ext_Zvbc , "Zvbc" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, ext_V)) \
decl(ext_Zvfh , "Zvfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, ext_V)) \
decl(ext_Zvkn , "Zvkn" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, ext_V)) \
decl(ext_Zicond , "Zicond" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \
decl(mvendorid , "VendorId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(marchid , "ArchId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(mimpid , "ImpId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(unaligned_access, "Unaligned" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(satp_mode , "SATP" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
#define DECLARE_RV_FEATURE(NAME, PRETTY, BIT, FSTRING, FLAGF) \
struct NAME##RVFeatureValue : public RVFeatureValue { \
@@ -53,11 +53,26 @@ class NativeMethodBarrier: public NativeInstruction {
return *((int32_t*)data_addr);
}
void set_guard_value(int value) {
int32_t* data_addr = (int32_t*)get_patchable_data_address();
void set_guard_value(int value, int bit_mask) {
if (bit_mask == ~0) {
int32_t* data_addr = (int32_t*)get_patchable_data_address();
// Set guard instruction value
*data_addr = value;
// Set guard instruction value
*data_addr = value;
return;
}
assert((value & ~bit_mask) == 0, "trying to set bits outside the mask");
value &= bit_mask;
int32_t* data_addr = (int32_t*)get_patchable_data_address();
int old_value = Atomic::load(data_addr);
while (true) {
// Only bits in the mask are changed
int new_value = value | (old_value & ~bit_mask);
if (new_value == old_value) break;
int v = Atomic::cmpxchg(data_addr, old_value, new_value, memory_order_release);
if (v == old_value) break;
old_value = v;
}
}
#ifdef ASSERT
@@ -100,13 +115,13 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
return;
}
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
if (!supports_entry_barrier(nm)) {
return;
}
NativeMethodBarrier* barrier = get_nmethod_barrier(nm);
barrier->set_guard_value(value);
barrier->set_guard_value(value, bit_mask);
}
int BarrierSetNMethod::guard_value(nmethod* nm) {
@@ -50,8 +50,31 @@ public:
address instruction_address() const { return addr_at(0); }
address immediate_address() const { return addr_at(imm_offset); }
NativeNMethodCmpBarrier* nativeNMethodCmpBarrier_at(address a) { return (NativeNMethodCmpBarrier*)a; }
jint get_immediate() const { return int_at(imm_offset); }
void set_immediate(jint imm) { set_int_at(imm_offset, imm); }
void set_immediate(jint imm, int bit_mask) {
if (bit_mask == ~0) {
set_int_at(imm_offset, imm);
return;
}
assert((imm & ~bit_mask) == 0, "trying to set bits outside the mask");
imm &= bit_mask;
assert(align_up(immediate_address(), sizeof(jint)) ==
align_down(immediate_address(), sizeof(jint)), "immediate not aligned");
jint* data_addr = (jint*)immediate_address();
jint old_value = Atomic::load(data_addr);
while (true) {
// Only bits in the mask are changed
jint new_value = imm | (old_value & ~bit_mask);
if (new_value == old_value) break;
jint v = Atomic::cmpxchg(data_addr, old_value, new_value, memory_order_release);
if (v == old_value) break;
old_value = v;
}
}
bool check_barrier(err_msg& msg) const;
void verify() const {
#ifdef ASSERT
@@ -159,13 +182,13 @@ static NativeNMethodCmpBarrier* native_nmethod_barrier(nmethod* nm) {
return barrier;
}
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
if (!supports_entry_barrier(nm)) {
return;
}
NativeNMethodCmpBarrier* cmp = native_nmethod_barrier(nm);
cmp->set_immediate(value);
cmp->set_immediate(value, bit_mask);
}
int BarrierSetNMethod::guard_value(nmethod* nm) {
-3
View File
@@ -3429,9 +3429,6 @@ attributes %{
instruction_unit_size = 1; // An instruction is 1 bytes long
instruction_fetch_unit_size = 16; // The processor fetches one line
instruction_fetch_units = 1; // of 16 bytes
// List of nop instructions
nops( MachNop );
%}
//----------RESOURCES----------------------------------------------------------
@@ -29,7 +29,7 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
ShouldNotReachHere();
}
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value) {
void BarrierSetNMethod::set_guard_value(nmethod* nm, int value, int bit_mask) {
ShouldNotReachHere();
}
@@ -24,19 +24,19 @@
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "os_posix.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/os.inline.hpp"
#include "os_posix.hpp"
#include "services/attachListener.hpp"
#include "utilities/checkedCast.hpp"
#include "utilities/macros.hpp"
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#if INCLUDE_SERVICES
#ifndef AIX
+2 -3
View File
@@ -70,14 +70,13 @@
#include <grp.h>
#include <locale.h>
#include <netdb.h>
#include <pwd.h>
#include <pthread.h>
#include <pwd.h>
#include <signal.h>
#include <spawn.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <spawn.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/types.h>
+2 -2
View File
@@ -30,9 +30,9 @@
#include "runtime/mutex.hpp"
#include "runtime/os.hpp"
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/socket.h>
#include <unistd.h>
// Aix does not have NUMA support but need these for compilation.
inline bool os::numa_has_group_homing() { AIX_ONLY(ShouldNotReachHere();) return false; }
+6 -7
View File
@@ -40,15 +40,14 @@
#include "os_linux.hpp"
#endif
// put OS-includes here
# include <sys/types.h>
# include <sys/mman.h>
# include <errno.h>
# include <stdio.h>
# include <unistd.h>
# include <sys/stat.h>
# include <signal.h>
# include <pwd.h>
# include <signal.h>
# include <stdio.h>
# include <sys/mman.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <unistd.h>
#if defined(LINUX)
# include <sys/file.h>
+1 -1
View File
@@ -32,8 +32,8 @@
#ifdef SAFEFETCH_METHOD_SIGSETJMP
// For SafeFetch we need POSIX TLS and sigsetjmp/longjmp.
#include <setjmp.h>
#include <pthread.h>
#include <setjmp.h>
static pthread_key_t g_jmpbuf_key;
struct InitTLSKey { InitTLSKey() { pthread_key_create(&g_jmpbuf_key, nullptr); } };
+2 -1
View File
@@ -25,9 +25,10 @@
#ifndef __APPLE__
#include "os_posix.hpp"
#include "runtime/os.hpp"
#include "utilities/debug.hpp"
// POSIX unnamed semaphores are not supported on OS X.
#include "semaphore_posix.hpp"
#include "utilities/debug.hpp"
#include <semaphore.h>
PosixSemaphore::PosixSemaphore(uint value) {
@@ -24,6 +24,7 @@
#include "runtime/threadLocalStorage.hpp"
#include "utilities/debug.hpp"
#include <pthread.h>
static pthread_key_t _thread_key;
@@ -88,7 +88,6 @@
#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)
#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6
#ifndef NR_riscv_hwprobe
#ifndef NR_arch_specific_syscall
@@ -115,8 +114,7 @@ static struct riscv_hwprobe query[] = {{RISCV_HWPROBE_KEY_MVENDORID, 0},
{RISCV_HWPROBE_KEY_MIMPID, 0},
{RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0},
{RISCV_HWPROBE_KEY_IMA_EXT_0, 0},
{RISCV_HWPROBE_KEY_CPUPERF_0, 0},
{RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE, 0}};
{RISCV_HWPROBE_KEY_CPUPERF_0, 0}};
bool RiscvHwprobe::probe_features() {
assert(!rw_hwprobe_completed, "Called twice.");
@@ -246,7 +244,4 @@ void RiscvHwprobe::add_features_from_query_result() {
VM_Version::unaligned_access.enable_feature(
query[RISCV_HWPROBE_KEY_CPUPERF_0].value & RISCV_HWPROBE_MISALIGNED_MASK);
}
if (is_valid(RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE)) {
VM_Version::zicboz_block_size.enable_feature(query[RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE].value);
}
}
+2 -30
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1507,36 +1507,8 @@ void ADLParser::pipe_parse(void) {
}
if (!strcmp(ident, "nops")) {
parse_err(WARN, "Using obsolete token, nops");
skipws();
if (_curchar != '(') {
parse_err(SYNERR, "expected `(`, found '%c'\n", _curchar);
break;
}
next_char(); skipws();
while (_curchar != ')') {
ident = get_ident();
if (ident == nullptr) {
parse_err(SYNERR, "expected identifier for nop instruction, found '%c'\n", _curchar);
break;
}
pipeline->_noplist.addName(ident);
pipeline->_nopcnt++;
skipws();
if (_curchar == ',') {
next_char(); skipws();
}
}
next_char(); skipws();
if (_curchar == ';') {
next_char(); skipws();
}
continue;
}
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -511,8 +511,6 @@ PipelineForm::PipelineForm()
, _stagecnt (0)
, _classlist ()
, _classcnt (0)
, _noplist ()
, _nopcnt (0)
, _variableSizeInstrs (false)
, _branchHasDelaySlot (false)
, _maxInstrsPerBundle (0)
@@ -533,7 +531,6 @@ void PipelineForm::output(FILE *fp) { // Write info to output files
const char *res;
const char *stage;
const char *cls;
const char *nop;
int count = 0;
fprintf(fp,"\nPipeline:");
@@ -574,9 +571,6 @@ void PipelineForm::output(FILE *fp) { // Write info to output files
for ( _classlist.reset(); (cls = _classlist.iter()) != nullptr; )
_classdict[cls]->is_pipeclass()->output(fp);
fprintf(fp,"\nNop Instructions:");
for ( _noplist.reset(); (nop = _noplist.iter()) != nullptr; )
fprintf(fp, " \"%s\"", nop);
fprintf(fp,"\n");
}
+1 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -386,9 +386,6 @@ public:
FormDict _classdict; // Class Name -> PipeClassForm mapping
int _classcnt; // Number of classes
NameList _noplist; // List of NOP instructions
int _nopcnt; // Number of nop instructions
bool _variableSizeInstrs; // Indicates if this architecture has variable sized instructions
bool _branchHasDelaySlot; // Indicates that branches have delay slot instructions
int _maxInstrsPerBundle; // Indicates the maximum number of instructions for ILP
+1 -13
View File
@@ -977,18 +977,6 @@ void ArchDesc::build_pipe_classes(FILE *fp_cpp) {
}
fprintf(fp_cpp, "}\n\n");
// Output the list of nop nodes
fprintf(fp_cpp, "// Descriptions for emitting different functional unit nops\n");
const char *nop;
int nopcnt = 0;
for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != nullptr; nopcnt++ );
fprintf(fp_cpp, "void Bundle::initialize_nops(MachNode * nop_list[%d]) {\n", nopcnt);
int i = 0;
for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != nullptr; i++ ) {
fprintf(fp_cpp, " nop_list[%d] = (MachNode *) new %sNode();\n", i, nop);
}
fprintf(fp_cpp, "};\n\n");
fprintf(fp_cpp, "#ifndef PRODUCT\n");
fprintf(fp_cpp, "void Bundle::dump(outputStream *st) const {\n");
fprintf(fp_cpp, " static const char * bundle_flags[] = {\n");
@@ -1004,7 +992,7 @@ void ArchDesc::build_pipe_classes(FILE *fp_cpp) {
fprintf(fp_cpp, " static const char *resource_names[%d] = {", _pipeline->_rescount);
// Don't add compound resources to the list of resource names
const char* resource;
i = 0;
int i = 0;
for (_pipeline->_reslist.reset(); (resource = _pipeline->_reslist.iter()) != nullptr;) {
if (_pipeline->_resdict[resource]->is_resource()->is_discrete()) {
fprintf(fp_cpp, " \"%s\"%c", resource, i < _pipeline->_rescount - 1 ? ',' : ' ');
-6
View File
@@ -1115,12 +1115,6 @@ void ArchDesc::declare_pipe_classes(FILE *fp_hpp) {
fprintf(fp_hpp, " bool use_delay() { return ((_flags & _use_delay) != 0); }\n");
fprintf(fp_hpp, " bool used_in_delay() { return ((_flags & _used_in_delay) != 0); }\n\n");
fprintf(fp_hpp, " enum {\n");
fprintf(fp_hpp, " _nop_count = %d\n",
_pipeline->_nopcnt);
fprintf(fp_hpp, " };\n\n");
fprintf(fp_hpp, " static void initialize_nops(MachNode *nop_list[%d]);\n\n",
_pipeline->_nopcnt);
fprintf(fp_hpp, "#ifndef PRODUCT\n");
fprintf(fp_hpp, " void dump(outputStream *st = tty) const;\n");
fprintf(fp_hpp, "#endif\n");
+24 -45
View File
@@ -2583,85 +2583,64 @@ class BacktraceIterator : public StackObj {
};
// Print stack trace element to resource allocated buffer
// Print stack trace element to the specified output stream.
// The output is formatted into a stringStream and written to the outputStream in one step.
static void print_stack_element_to_stream(outputStream* st, Handle mirror, int method_id,
int version, int bci, Symbol* name) {
ResourceMark rm;
stringStream ss;
// Get strings and string lengths
InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror()));
const char* klass_name = holder->external_name();
int buf_len = (int)strlen(klass_name);
char* method_name = name->as_C_string();
buf_len += (int)strlen(method_name);
ss.print("\tat %s.%s(", klass_name, method_name);
// Print module information
ModuleEntry* module = holder->module();
if (module->is_named()) {
char* module_name = module->name()->as_C_string();
if (module->version() != nullptr) {
char* module_version = module->version()->as_C_string();
ss.print("%s@%s/", module_name, module_version);
} else {
ss.print("%s/", module_name);
}
}
char* source_file_name = nullptr;
Symbol* source = Backtrace::get_source_file_name(holder, version);
if (source != nullptr) {
source_file_name = source->as_C_string();
buf_len += (int)strlen(source_file_name);
}
char *module_name = nullptr, *module_version = nullptr;
ModuleEntry* module = holder->module();
if (module->is_named()) {
module_name = module->name()->as_C_string();
buf_len += (int)strlen(module_name);
if (module->version() != nullptr) {
module_version = module->version()->as_C_string();
buf_len += (int)strlen(module_version);
}
}
// Allocate temporary buffer with extra space for formatting and line number
const size_t buf_size = buf_len + 64;
char* buf = NEW_RESOURCE_ARRAY(char, buf_size);
// Print stack trace line in buffer
int buf_off = os::snprintf(buf, buf_size, "\tat %s.%s(", klass_name, method_name);
assert(static_cast<size_t>(buf_off) < buf_size, "buffer is wrong size");
// Print module information
if (module_name != nullptr) {
if (module_version != nullptr) {
buf_off += os::snprintf(buf + buf_off, buf_size - buf_off, "%s@%s/", module_name, module_version);
assert(static_cast<size_t>(buf_off) < buf_size, "buffer is wrong size");
} else {
buf_off += os::snprintf(buf + buf_off, buf_size - buf_off, "%s/", module_name);
assert(static_cast<size_t>(buf_off) < buf_size, "buffer is wrong size");
}
}
// The method can be null if the requested class version is gone
Method* method = holder->method_with_orig_idnum(method_id, version);
if (!version_matches(method, version)) {
strcat(buf, "Redefined)");
ss.print("Redefined)");
} else {
int line_number = Backtrace::get_line_number(method, bci);
if (line_number == -2) {
strcat(buf, "Native Method)");
ss.print("Native Method)");
} else {
if (source_file_name != nullptr && (line_number != -1)) {
// Sourcename and linenumber
buf_off += os::snprintf(buf + buf_off, buf_size - buf_off, "%s:%d)", source_file_name, line_number);
assert(static_cast<size_t>(buf_off) < buf_size, "buffer is wrong size");
ss.print("%s:%d)", source_file_name, line_number);
} else if (source_file_name != nullptr) {
// Just sourcename
buf_off += os::snprintf(buf + buf_off, buf_size - buf_off, "%s)", source_file_name);
assert(static_cast<size_t>(buf_off) < buf_size, "buffer is wrong size");
ss.print("%s)", source_file_name);
} else {
// Neither sourcename nor linenumber
buf_off += os::snprintf(buf + buf_off, buf_size - buf_off, "Unknown Source)");
assert(static_cast<size_t>(buf_off) < buf_size, "buffer is wrong size");
ss.print("Unknown Source)");
}
nmethod* nm = method->code();
if (WizardMode && nm != nullptr) {
os::snprintf_checked(buf + buf_off, buf_size - buf_off, "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm);
ss.print("(nmethod " INTPTR_FORMAT ")", p2i(nm));
}
}
}
st->print_cr("%s", buf);
ss.cr();
st->print_raw(ss.freeze(), ss.size());
}
void java_lang_Throwable::print_stack_element(outputStream *st, Method* method, int bci) {
@@ -72,21 +72,12 @@ bool BarrierSetNMethod::supports_entry_barrier(nmethod* nm) {
}
void BarrierSetNMethod::disarm(nmethod* nm) {
guard_with(nm, disarmed_guard_value());
set_guard_value(nm, disarmed_guard_value());
}
void BarrierSetNMethod::guard_with(nmethod* nm, int value) {
assert((value & not_entrant) == 0, "not_entrant bit is reserved");
// Enter critical section. Does not block for safepoint.
ConditionalMutexLocker ml(NMethodEntryBarrier_lock, !NMethodEntryBarrier_lock->owned_by_self(), Mutex::_no_safepoint_check_flag);
// Do not undo sticky bit
if (is_not_entrant(nm)) {
value |= not_entrant;
}
if (guard_value(nm) != value) {
// Patch the code only if needed.
set_guard_value(nm, value);
}
set_guard_value(nm, value);
}
bool BarrierSetNMethod::is_armed(nmethod* nm) {
@@ -119,6 +110,8 @@ bool BarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) {
return true;
}
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, Thread::current()));
// If the nmethod is the only thing pointing to the oops, and we are using a
// SATB GC, then it is important that this code marks them live.
// Also, with concurrent GC, it is possible that frames in continuation stack
@@ -179,10 +172,6 @@ void BarrierSetNMethod::arm_all_nmethods() {
}
int BarrierSetNMethod::nmethod_stub_entry_barrier(address* return_address_ptr) {
// Enable WXWrite: the function is called directly from nmethod_entry_barrier
// stub.
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, Thread::current()));
address return_address = *return_address_ptr;
AARCH64_PORT_ONLY(return_address = pauth_strip_pointer(return_address));
CodeBlob* cb = CodeCache::find_blob(return_address);
@@ -243,13 +232,7 @@ oop BarrierSetNMethod::oop_load_phantom(const nmethod* nm, int index) {
// nmethod_stub_entry_barrier() may appear to be spurious, because is_armed() still returns
// false and nmethod_entry_barrier() is not called.
void BarrierSetNMethod::make_not_entrant(nmethod* nm) {
// Enter critical section. Does not block for safepoint.
ConditionalMutexLocker ml(NMethodEntryBarrier_lock, !NMethodEntryBarrier_lock->owned_by_self(), Mutex::_no_safepoint_check_flag);
int value = guard_value(nm) | not_entrant;
if (guard_value(nm) != value) {
// Patch the code only if needed.
set_guard_value(nm, value);
}
set_guard_value(nm, not_entrant, not_entrant);
}
bool BarrierSetNMethod::is_not_entrant(nmethod* nm) {
@@ -36,17 +36,18 @@ class nmethod;
class BarrierSetNMethod: public CHeapObj<mtGC> {
private:
int _current_phase;
void deoptimize(nmethod* nm, address* return_addr_ptr);
protected:
enum {
not_entrant = 1 << 31, // armed sticky bit, see make_not_entrant
armed = 0,
initial = 1,
};
void deoptimize(nmethod* nm, address* return_addr_ptr);
protected:
virtual int guard_value(nmethod* nm);
void set_guard_value(nmethod* nm, int value);
int guard_value(nmethod* nm);
void set_guard_value(nmethod* nm, int value, int bit_mask = ~not_entrant);
public:
BarrierSetNMethod() : _current_phase(initial) {}
@@ -60,13 +61,13 @@ public:
static int nmethod_stub_entry_barrier(address* return_address_ptr);
bool nmethod_osr_entry_barrier(nmethod* nm);
virtual bool is_armed(nmethod* nm);
bool is_armed(nmethod* nm);
void arm(nmethod* nm) { guard_with(nm, armed); }
void disarm(nmethod* nm);
virtual void make_not_entrant(nmethod* nm);
virtual bool is_not_entrant(nmethod* nm);
void make_not_entrant(nmethod* nm);
bool is_not_entrant(nmethod* nm);
virtual void guard_with(nmethod* nm, int value);
void guard_with(nmethod* nm, int value);
virtual void arm_all_nmethods();
@@ -106,34 +106,6 @@ oop ZBarrierSetNMethod::oop_load_phantom(const nmethod* nm, int index) {
return ZNMethod::oop_load_phantom(nm, index);
}
void ZBarrierSetNMethod::guard_with(nmethod* nm, int value) {
assert((value & not_entrant) == 0, "not_entrant bit is reserved");
ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
// Preserve the sticky bit
if (is_not_entrant(nm)) {
value |= not_entrant;
}
if (guard_value(nm) != value) {
// Patch the code only if needed.
set_guard_value(nm, value);
}
}
bool ZBarrierSetNMethod::is_armed(nmethod* nm) {
int value = guard_value(nm) & ~not_entrant;
return value != disarmed_guard_value();
}
void ZBarrierSetNMethod::make_not_entrant(nmethod* nm) {
ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
int value = guard_value(nm) | not_entrant; // permanent sticky value
set_guard_value(nm, value);
}
bool ZBarrierSetNMethod::is_not_entrant(nmethod* nm) {
return (guard_value(nm) & not_entrant) != 0;
}
uintptr_t ZBarrierSetNMethod::color(nmethod* nm) {
// color is stored at low order bits of int; conversion to uintptr_t is fine
return uintptr_t(guard_value(nm) & ~not_entrant);
@@ -30,10 +30,6 @@
class nmethod;
class ZBarrierSetNMethod : public BarrierSetNMethod {
enum : int {
not_entrant = 1 << 31, // armed sticky bit, see make_not_entrant
};
protected:
virtual bool nmethod_entry_barrier(nmethod* nm);
@@ -46,10 +42,6 @@ public:
virtual oop oop_load_no_keepalive(const nmethod* nm, int index);
virtual oop oop_load_phantom(const nmethod* nm, int index);
virtual void make_not_entrant(nmethod* nm);
virtual bool is_not_entrant(nmethod* nm);
virtual void guard_with(nmethod* nm, int value);
virtual bool is_armed(nmethod* nm);
virtual void arm_all_nmethods() { ShouldNotCallThis(); }
};
@@ -25,7 +25,6 @@
#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp"
#include "logging/log.hpp"
#if defined(LINUX)
#include "jfr/periodic/sampling/jfrThreadSampling.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
@@ -67,7 +66,7 @@ static JavaThread* get_java_thread_if_valid() {
}
JfrCPUTimeTraceQueue::JfrCPUTimeTraceQueue(u4 capacity) :
_data(nullptr), _capacity(capacity), _head(0), _lost_samples(0) {
_data(nullptr), _capacity(capacity), _head(0), _lost_samples(0), _lost_samples_due_to_queue_full(0) {
if (capacity != 0) {
_data = JfrCHeapObj::new_array<JfrCPUTimeSampleRequest>(capacity);
}
@@ -110,10 +109,13 @@ void JfrCPUTimeTraceQueue::set_size(u4 size) {
}
u4 JfrCPUTimeTraceQueue::capacity() const {
return _capacity;
return Atomic::load_acquire(&_capacity);
}
void JfrCPUTimeTraceQueue::set_capacity(u4 capacity) {
if (capacity == Atomic::load(&_capacity)) {
return;
}
_head = 0;
if (_data != nullptr) {
assert(_capacity != 0, "invariant");
@@ -124,7 +126,7 @@ void JfrCPUTimeTraceQueue::set_capacity(u4 capacity) {
} else {
_data = nullptr;
}
_capacity = capacity;
Atomic::release_store(&_capacity, capacity);
}
bool JfrCPUTimeTraceQueue::is_empty() const {
@@ -140,28 +142,51 @@ void JfrCPUTimeTraceQueue::increment_lost_samples() {
Atomic::inc(&_lost_samples);
}
void JfrCPUTimeTraceQueue::increment_lost_samples_due_to_queue_full() {
Atomic::inc(&_lost_samples_due_to_queue_full);
}
u4 JfrCPUTimeTraceQueue::get_and_reset_lost_samples() {
return Atomic::xchg(&_lost_samples, (u4)0);
}
void JfrCPUTimeTraceQueue::resize(u4 capacity) {
if (capacity != _capacity) {
set_capacity(capacity);
}
u4 JfrCPUTimeTraceQueue::get_and_reset_lost_samples_due_to_queue_full() {
return Atomic::xchg(&_lost_samples_due_to_queue_full, (u4)0);
}
void JfrCPUTimeTraceQueue::resize_for_period(u4 period_millis) {
u4 capacity = CPU_TIME_QUEUE_CAPACITY;
if (period_millis > 0 && period_millis < 10) {
capacity = (u4) ((double) capacity * 10 / period_millis);
}
resize(capacity);
void JfrCPUTimeTraceQueue::init() {
set_capacity(JfrCPUTimeTraceQueue::CPU_TIME_QUEUE_INITIAL_CAPACITY);
}
void JfrCPUTimeTraceQueue::clear() {
Atomic::release_store(&_head, (u4)0);
}
void JfrCPUTimeTraceQueue::resize_if_needed() {
u4 lost_samples_due_to_queue_full = get_and_reset_lost_samples_due_to_queue_full();
if (lost_samples_due_to_queue_full == 0) {
return;
}
u4 capacity = Atomic::load(&_capacity);
if (capacity < CPU_TIME_QUEUE_MAX_CAPACITY) {
float ratio = (float)lost_samples_due_to_queue_full / (float)capacity;
int factor = 1;
if (ratio > 8) { // idea is to quickly scale the queue in the worst case
factor = ratio;
} else if (ratio > 2) {
factor = 8;
} else if (ratio > 0.5) {
factor = 4;
} else if (ratio > 0.01) {
factor = 2;
}
if (factor > 1) {
u4 new_capacity = MIN2(CPU_TIME_QUEUE_MAX_CAPACITY, capacity * factor);
set_capacity(new_capacity);
}
}
}
// A throttle is either a rate or a fixed period
class JfrCPUSamplerThrottle {
@@ -205,6 +230,8 @@ class JfrCPUSamplerThread : public NonJavaThread {
volatile bool _is_async_processing_of_cpu_time_jfr_requests_triggered;
volatile bool _warned_about_timer_creation_failure;
volatile bool _signal_handler_installed;
DEBUG_ONLY(volatile bool _out_of_stack_walking_enabled;)
DEBUG_ONLY(volatile u8 _out_of_stack_walking_iterations;)
static const u4 STOP_SIGNAL_BIT = 0x80000000;
@@ -250,6 +277,16 @@ public:
void stop_timer();
void trigger_async_processing_of_cpu_time_jfr_requests();
#ifdef ASSERT
void set_out_of_stack_walking_enabled(bool runnable) {
Atomic::release_store(&_out_of_stack_walking_enabled, runnable);
}
u8 out_of_stack_walking_iterations() const {
return Atomic::load(&_out_of_stack_walking_iterations);
}
#endif
};
JfrCPUSamplerThread::JfrCPUSamplerThread(JfrCPUSamplerThrottle& throttle) :
@@ -275,7 +312,7 @@ void JfrCPUSamplerThread::on_javathread_create(JavaThread* thread) {
}
JfrThreadLocal* tl = thread->jfr_thread_local();
assert(tl != nullptr, "invariant");
tl->cpu_time_jfr_queue().resize_for_period(_current_sampling_period_ns / 1000000);
tl->cpu_time_jfr_queue().init();
timer_t timerid;
if (create_timer_for_thread(thread, timerid)) {
tl->set_cpu_timer(&timerid);
@@ -294,12 +331,14 @@ void JfrCPUSamplerThread::on_javathread_terminate(JavaThread* thread) {
if (timer == nullptr) {
return; // no timer was created for this thread
}
tl->acquire_cpu_time_jfr_dequeue_lock();
tl->unset_cpu_timer();
tl->deallocate_cpu_time_jfr_queue();
s4 lost_samples = tl->cpu_time_jfr_queue().lost_samples();
if (lost_samples > 0) {
JfrCPUTimeThreadSampling::send_lost_event(JfrTicks::now(), JfrThreadLocal::thread_id(thread), lost_samples);
}
tl->release_cpu_time_jfr_queue_lock();
}
void JfrCPUSamplerThread::start_thread() {
@@ -352,10 +391,12 @@ void JfrCPUSamplerThread::run() {
recompute_period_if_needed();
last_recompute_check = os::javaTimeNanos();
}
if (Atomic::cmpxchg(&_is_async_processing_of_cpu_time_jfr_requests_triggered, true, false)) {
stackwalk_threads_in_native();
}
DEBUG_ONLY(if (Atomic::load_acquire(&_out_of_stack_walking_enabled)) {)
if (Atomic::cmpxchg(&_is_async_processing_of_cpu_time_jfr_requests_triggered, true, false)) {
DEBUG_ONLY(Atomic::inc(&_out_of_stack_walking_iterations);)
stackwalk_threads_in_native();
}
DEBUG_ONLY(})
os::naked_sleep(100);
}
}
@@ -545,6 +586,21 @@ void JfrCPUTimeThreadSampling::handle_timer_signal(siginfo_t* info, void* contex
_sampler->decrement_signal_handler_count();
}
#ifdef ASSERT
void JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(bool runnable) {
if (_instance != nullptr && _instance->_sampler != nullptr) {
_instance->_sampler->set_out_of_stack_walking_enabled(runnable);
}
}
u8 JfrCPUTimeThreadSampling::out_of_stack_walking_iterations() {
if (_instance != nullptr && _instance->_sampler != nullptr) {
return _instance->_sampler->out_of_stack_walking_iterations();
}
return 0;
}
#endif
void JfrCPUSamplerThread::sample_thread(JfrSampleRequest& request, void* ucontext, JavaThread* jt, JfrThreadLocal* tl, JfrTicks& now) {
JfrSampleRequestBuilder::build_cpu_time_sample_request(request, ucontext, jt, jt->jfr_thread_local(), now);
}
@@ -590,6 +646,7 @@ void JfrCPUSamplerThread::handle_timer_signal(siginfo_t* info, void* context) {
}
} else {
queue.increment_lost_samples();
queue.increment_lost_samples_due_to_queue_full();
}
if (jt->thread_state() == _thread_in_native) {
@@ -807,4 +864,10 @@ void JfrCPUTimeThreadSampling::on_javathread_create(JavaThread* thread) {
void JfrCPUTimeThreadSampling::on_javathread_terminate(JavaThread* thread) {
}
#ifdef ASSERT
static void set_out_of_stack_walking_enabled(bool runnable) {
warn();
}
#endif
#endif // defined(LINUX) && defined(INCLUDE_JFR)
@@ -50,12 +50,15 @@ class JfrCPUTimeTraceQueue {
static const u4 CPU_TIME_QUEUE_CAPACITY = 500;
JfrCPUTimeSampleRequest* _data;
u4 _capacity;
volatile u4 _capacity;
// next unfilled index
volatile u4 _head;
volatile u4 _lost_samples;
volatile u4 _lost_samples_due_to_queue_full;
static const u4 CPU_TIME_QUEUE_INITIAL_CAPACITY = 20;
static const u4 CPU_TIME_QUEUE_MAX_CAPACITY = 2000;
public:
JfrCPUTimeTraceQueue(u4 capacity);
@@ -81,12 +84,17 @@ public:
void increment_lost_samples();
void increment_lost_samples_due_to_queue_full();
// returns the previous lost samples count
u4 get_and_reset_lost_samples();
void resize(u4 capacity);
u4 get_and_reset_lost_samples_due_to_queue_full();
void resize_for_period(u4 period_millis);
void resize_if_needed();
// init the queue capacity
void init();
void clear();
@@ -130,6 +138,10 @@ class JfrCPUTimeThreadSampling : public JfrCHeapObj {
static void send_lost_event(const JfrTicks& time, traceid tid, s4 lost_samples);
static void trigger_async_processing_of_cpu_time_jfr_requests();
DEBUG_ONLY(static void set_out_of_stack_walking_enabled(bool runnable);)
DEBUG_ONLY(static u8 out_of_stack_walking_iterations();)
};
#else
@@ -150,6 +162,8 @@ private:
static void on_javathread_create(JavaThread* thread);
static void on_javathread_terminate(JavaThread* thread);
DEBUG_ONLY(static void set_out_of_stack_walking_enabled(bool runnable));
DEBUG_ONLY(static u8 out_of_stack_walking_iterations();)
};
#endif // defined(LINUX)
@@ -368,6 +368,7 @@ static void drain_enqueued_cpu_time_requests(const JfrTicks& now, JfrThreadLocal
tl->set_has_cpu_time_jfr_requests(false);
if (queue.lost_samples() > 0) {
JfrCPUTimeThreadSampling::send_lost_event( now, JfrThreadLocal::thread_id(jt), queue.get_and_reset_lost_samples());
queue.resize_if_needed();
}
if (lock) {
tl->release_cpu_time_jfr_queue_lock();
@@ -656,7 +656,7 @@ JfrCPUTimeTraceQueue& JfrThreadLocal::cpu_time_jfr_queue() {
}
void JfrThreadLocal::deallocate_cpu_time_jfr_queue() {
cpu_time_jfr_queue().resize(0);
cpu_time_jfr_queue().set_capacity(0);
}
void JfrThreadLocal::set_do_async_processing_of_cpu_time_jfr_requests(bool wants) {
+1 -6
View File
@@ -1399,10 +1399,6 @@ CodeBuffer* PhaseOutput::init_buffer() {
cb->initialize_stubs_size(stub_req);
cb->initialize_oop_recorder(C->env()->oop_recorder());
// fill in the nop array for bundling computations
MachNode *_nop_list[Bundle::_nop_count];
Bundle::initialize_nops(_nop_list);
return cb;
}
@@ -2062,8 +2058,7 @@ Scheduling::Scheduling(Arena *arena, Compile &compile)
// Create a MachNopNode
_nop = new MachNopNode();
// Now that the nops are in the array, save the count
// (but allow entries for the nops)
// Save the count
_node_bundling_limit = compile.unique();
uint node_max = _regalloc->node_regs_max_index();
+1 -1
View File
@@ -2502,7 +2502,7 @@ bool LibraryCallKit::inline_vector_extract() {
if (vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con() ||
idx == nullptr || !idx->is_con()) {
idx == nullptr) {
log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],
+36 -32
View File
@@ -418,6 +418,7 @@ JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) {
JvmtiThreadState*
JvmtiExport::get_jvmti_thread_state(JavaThread *thread, bool allow_suspend) {
assert(thread == JavaThread::current(), "must be current thread");
assert(thread->thread_state() == _thread_in_vm, "thread should be in vm");
if (thread->is_vthread_mounted() && thread->jvmti_thread_state() == nullptr) {
JvmtiEventController::thread_started(thread);
if (allow_suspend && thread->is_suspended()) {
@@ -1826,47 +1827,50 @@ void JvmtiExport::post_method_entry(JavaThread *thread, Method* method, frame cu
}
void JvmtiExport::post_method_exit(JavaThread* thread, Method* method, frame current_frame) {
// At this point we only have the address of a "raw result" and
// we just call into the interpreter to convert this into a jvalue.
// This method always makes transition to vm and back where GC can happen.
// So it is needed to preserve result and then restore it
// even if events are not actually posted.
// Saving oop_result into value.j is deferred until jvmti state is ready.
HandleMark hm(thread);
methodHandle mh(thread, method);
JvmtiThreadState *state = get_jvmti_thread_state(thread);
if (state == nullptr || !state->is_interp_only_mode()) {
// for any thread that actually wants method exit, interp_only_mode is set
return;
}
Handle result;
oop oop_result;
jvalue value;
value.j = 0L;
if (state->is_enabled(JVMTI_EVENT_METHOD_EXIT)) {
// At this point we only have the address of a "raw result" and
// we just call into the interpreter to convert this into a jvalue.
oop oop_result;
BasicType type = current_frame.interpreter_frame_result(&oop_result, &value);
assert(type == T_VOID || current_frame.interpreter_frame_expression_stack_size() > 0,
"Stack shouldn't be empty");
if (is_reference_type(type)) {
result = Handle(thread, oop_result);
value.l = JNIHandles::make_local(thread, result());
}
BasicType type = current_frame.interpreter_frame_result(&oop_result, &value);
assert(mh->is_native() || type == T_VOID || current_frame.interpreter_frame_expression_stack_size() > 0,
"Stack shouldn't be empty");
if (is_reference_type(type)) {
result = Handle(thread, oop_result);
}
// Do not allow NotifyFramePop to add new FramePop event request at
// depth 0 as it is already late in the method exiting dance.
state->set_top_frame_is_exiting();
// Deferred transition to VM, so we can stash away the return oop before GC.
JvmtiThreadState* state; // should be initialized in vm state only
JavaThread* current = thread; // for JRT_BLOCK
bool interp_only; // might be changed in JRT_BLOCK_END
JRT_BLOCK
post_method_exit_inner(thread, mh, state, false /* not exception exit */, current_frame, value);
state = get_jvmti_thread_state(thread);
interp_only = state != nullptr && state->is_interp_only_mode();
if (interp_only) {
if (state->is_enabled(JVMTI_EVENT_METHOD_EXIT)) {
// Deferred saving Object result into value.
if (is_reference_type(type)) {
value.l = JNIHandles::make_local(thread, result());
}
}
// Do not allow NotifyFramePop to add new FramePop event request at
// depth 0 as it is already late in the method exiting dance.
state->set_top_frame_is_exiting();
post_method_exit_inner(thread, mh, state, false /* not exception exit */, current_frame, value);
}
JRT_BLOCK_END
// The JRT_BLOCK_END can safepoint in ThreadInVMfromJava desctructor. Now it is safe to allow
// adding FramePop event requests as no safepoint can happen before removing activation.
state->clr_top_frame_is_exiting();
if (interp_only) {
// The JRT_BLOCK_END can safepoint in ThreadInVMfromJava destructor. Now it is safe to allow
// adding FramePop event requests as no safepoint can happen before removing activation.
state->clr_top_frame_is_exiting();
}
if (result.not_null() && !mh->is_native()) {
// We have to restore the oop on the stack for interpreter frames
*(oop*)current_frame.interpreter_frame_tos_address() = result();
+30
View File
@@ -46,6 +46,7 @@
#include "gc/shared/concurrentGCBreakpoints.hpp"
#include "gc/shared/gcConfig.hpp"
#include "gc/shared/genArguments.hpp"
#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp"
#include "jvm.h"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "logging/log.hpp"
@@ -2660,6 +2661,32 @@ WB_ENTRY(void, WB_WaitUnsafe(JNIEnv* env, jobject wb, jint time))
os::naked_short_sleep(time);
WB_END
WB_ENTRY(void, WB_BusyWait(JNIEnv* env, jobject wb, jint time))
ThreadToNativeFromVM ttn(thread);
u8 start = os::current_thread_cpu_time();
u8 target_duration = time * (u8)1000000;
while (os::current_thread_cpu_time() - start < target_duration) {
for (volatile int i = 0; i < 1000000; i++);
}
WB_END
WB_ENTRY(jboolean, WB_CPUSamplerSetOutOfStackWalking(JNIEnv* env, jobject wb, jboolean enable))
#if defined(ASSERT) && INCLUDE_JFR && defined(LINUX)
JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(enable == JNI_TRUE);
return JNI_TRUE;
#else
return JNI_FALSE;
#endif
WB_END
WB_ENTRY(jlong, WB_CPUSamplerOutOfStackWalkingIterations(JNIEnv* env, jobject wb))
#if defined(ASSERT) && INCLUDE_JFR && defined(LINUX)
return (jlong)JfrCPUTimeThreadSampling::out_of_stack_walking_iterations();
#else
return 0;
#endif
WB_END
WB_ENTRY(jstring, WB_GetLibcName(JNIEnv* env, jobject o))
ThreadToNativeFromVM ttn(thread);
jstring info_string = env->NewStringUTF(XSTR(LIBC));
@@ -3013,6 +3040,9 @@ static JNINativeMethod methods[] = {
{CC"isJVMTIIncluded", CC"()Z", (void*)&WB_IsJVMTIIncluded},
{CC"waitUnsafe", CC"(I)V", (void*)&WB_WaitUnsafe},
{CC"busyWait", CC"(I)V", (void*)&WB_BusyWait},
{CC"cpuSamplerSetOutOfStackWalking", CC"(Z)Z", (void*)&WB_CPUSamplerSetOutOfStackWalking},
{CC"cpuSamplerOutOfStackWalkingIterations", CC"()J",(void*)&WB_CPUSamplerOutOfStackWalkingIterations},
{CC"getLibcName", CC"()Ljava/lang/String;", (void*)&WB_GetLibcName},
{CC"pinObject", CC"(Ljava/lang/Object;)V", (void*)&WB_PinObject},
@@ -36,7 +36,6 @@
// Mutexes used in the VM (see comment in mutexLocker.hpp):
Mutex* NMethodState_lock = nullptr;
Mutex* NMethodEntryBarrier_lock = nullptr;
Monitor* SystemDictionary_lock = nullptr;
Mutex* InvokeMethodTypeTable_lock = nullptr;
Monitor* InvokeMethodIntrinsicTable_lock = nullptr;
@@ -207,8 +206,6 @@ void assert_lock_strong(const Mutex* lock) {
void mutex_init() {
MUTEX_DEFN(tty_lock , PaddedMutex , tty); // allow to lock in VM
MUTEX_DEFN(NMethodEntryBarrier_lock , PaddedMutex , service-1);
MUTEX_DEFN(STS_lock , PaddedMonitor, nosafepoint);
#if INCLUDE_G1GC
@@ -34,7 +34,6 @@ class Thread;
// Mutexes used in the VM.
extern Mutex* NMethodState_lock; // a lock used to guard a compiled method state
extern Mutex* NMethodEntryBarrier_lock; // protects nmethod entry barrier
extern Monitor* SystemDictionary_lock; // a lock on the system dictionary
extern Mutex* InvokeMethodTypeTable_lock;
extern Monitor* InvokeMethodIntrinsicTable_lock;
@@ -38,6 +38,15 @@
#include <stdlib.h>
#endif
// Workaround for noexcept functions in glibc when using clang.
// clang errors if declaration without exception specification preceeds
// noexcept declaration, but not the other way around.
#ifdef __clang__
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#endif
#ifdef _WINDOWS
#include "forbiddenFunctions_windows.hpp"
#else
@@ -25,6 +25,7 @@
package java.io;
import java.lang.annotation.Native;
import java.util.*;
import java.nio.charset.Charset;
import jdk.internal.access.JavaIOAccess;
@@ -550,7 +551,12 @@ public sealed class Console implements Flushable permits ProxyingConsole {
"Console class itself does not provide implementation");
}
private static final boolean istty = istty();
@Native static final int TTY_STDIN_MASK = 0x00000001;
@Native static final int TTY_STDOUT_MASK = 0x00000002;
@Native static final int TTY_STDERR_MASK = 0x00000004;
// ttyStatus() returns bit patterns above, a bit is set if the corresponding file
// descriptor is a character device
private static final int ttyStatus = ttyStatus();
private static final Charset STDIN_CHARSET =
Charset.forName(StaticProperty.stdinEncoding(), UTF_8.INSTANCE);
private static final Charset STDOUT_CHARSET =
@@ -562,6 +568,9 @@ public sealed class Console implements Flushable permits ProxyingConsole {
public Console console() {
return cons;
}
public boolean isStdinTty() {
return Console.isStdinTty();
}
});
}
@@ -583,7 +592,7 @@ public sealed class Console implements Flushable permits ProxyingConsole {
for (var jcp : ServiceLoader.load(ModuleLayer.boot(), JdkConsoleProvider.class)) {
if (consModName.equals(jcp.getClass().getModule().getName())) {
var jc = jcp.console(istty, STDIN_CHARSET, STDOUT_CHARSET);
var jc = jcp.console(isStdinTty() && isStdoutTty(), STDIN_CHARSET, STDOUT_CHARSET);
if (jc != null) {
c = new ProxyingConsole(jc);
}
@@ -594,12 +603,21 @@ public sealed class Console implements Flushable permits ProxyingConsole {
}
// If not found, default to built-in Console
if (istty && c == null) {
if (isStdinTty() && isStdoutTty() && c == null) {
c = new ProxyingConsole(new JdkConsoleImpl(STDIN_CHARSET, STDOUT_CHARSET));
}
return c;
}
private static native boolean istty();
private static boolean isStdinTty() {
return (ttyStatus & TTY_STDIN_MASK) != 0;
}
private static boolean isStdoutTty() {
return (ttyStatus & TTY_STDOUT_MASK) != 0;
}
private static boolean isStderrTty() {
return (ttyStatus & TTY_STDERR_MASK) != 0;
}
private static native int ttyStatus();
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,4 +29,5 @@ import java.io.Console;
public interface JavaIOAccess {
Console console();
boolean isStdinTty();
}
@@ -38,10 +38,13 @@ import java.util.Arrays;
import java.util.Formatter;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.StaticProperty;
import sun.nio.cs.StreamDecoder;
import sun.nio.cs.StreamEncoder;
import sun.nio.cs.UTF_8;
/**
* JdkConsole implementation based on the platform's TTY.
@@ -103,6 +106,42 @@ public final class JdkConsoleImpl implements JdkConsole {
@Override
public char[] readPassword(Locale locale, String format, Object ... args) {
return readPassword0(false, locale, format, args);
}
// These two methods are intended for sun.security.util.Password, so tools like keytool can
// use JdkConsoleImpl even when standard output is redirected. The Password class should first
// check if `System.console()` returns a Console instance and use it if available. Otherwise,
// it should call this method to obtain a JdkConsoleImpl. This ensures only one Console
// instance exists in the Java runtime.
private static final StableValue<Optional<JdkConsoleImpl>> INSTANCE = StableValue.of();
public static Optional<JdkConsoleImpl> passwordConsole() {
return INSTANCE.orElseSet(() -> {
// If there's already a proper console, throw an exception
if (System.console() != null) {
throw new IllegalStateException("Cant create a dedicated password " +
"console since a real console already exists");
}
// If stdin is NOT redirected, return an Optional containing a JdkConsoleImpl
// instance, otherwise an empty Optional.
return SharedSecrets.getJavaIOAccess().isStdinTty() ?
Optional.of(
new JdkConsoleImpl(
Charset.forName(StaticProperty.stdinEncoding(), UTF_8.INSTANCE),
Charset.forName(StaticProperty.stdoutEncoding(), UTF_8.INSTANCE))) :
Optional.empty();
});
}
// Dedicated entry for sun.security.util.Password when stdout is redirected.
// This method strictly avoids producing any output by using noNewLine = true
// and an empty format string.
public char[] readPasswordNoNewLine() {
return readPassword0(true, Locale.getDefault(Locale.Category.FORMAT), "");
}
private char[] readPassword0(boolean noNewLine, Locale locale, String format, Object ... args) {
char[] passwd = null;
synchronized (writeLock) {
synchronized(readLock) {
@@ -146,7 +185,9 @@ public final class JdkConsoleImpl implements JdkConsole {
throw ioe;
}
}
pw.println();
if (!noNewLine) {
pw.println();
}
}
}
return passwd;
+15 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,8 +31,19 @@
#include <stdlib.h>
#include <unistd.h>
JNIEXPORT jboolean JNICALL
Java_java_io_Console_istty(JNIEnv *env, jclass cls)
JNIEXPORT jint JNICALL
Java_java_io_Console_ttyStatus(JNIEnv *env, jclass cls)
{
return isatty(fileno(stdin)) && isatty(fileno(stdout));
jint ret = 0;
if (isatty(fileno(stdin))) {
ret |= java_io_Console_TTY_STDIN_MASK;
}
if (isatty(fileno(stdout))) {
ret |= java_io_Console_TTY_STDOUT_MASK;
}
if (isatty(fileno(stderr))) {
ret |= java_io_Console_TTY_STDERR_MASK;
}
return ret;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,21 +31,28 @@
#include <stdlib.h>
#include <Wincon.h>
JNIEXPORT jboolean JNICALL
Java_java_io_Console_istty(JNIEnv *env, jclass cls)
JNIEXPORT jint JNICALL
Java_java_io_Console_ttyStatus(JNIEnv *env, jclass cls)
{
jint ret = 0;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE);
if (hStdIn == INVALID_HANDLE_VALUE ||
hStdOut == INVALID_HANDLE_VALUE) {
return JNI_FALSE;
if (hStdIn != INVALID_HANDLE_VALUE &&
GetFileType(hStdIn) == FILE_TYPE_CHAR) {
ret |= java_io_Console_TTY_STDIN_MASK;
}
if (GetFileType(hStdIn) != FILE_TYPE_CHAR ||
GetFileType(hStdOut) != FILE_TYPE_CHAR) {
return JNI_FALSE;
if (hStdOut != INVALID_HANDLE_VALUE &&
GetFileType(hStdOut) == FILE_TYPE_CHAR) {
ret |= java_io_Console_TTY_STDOUT_MASK;
}
return JNI_TRUE;
if (hStdErr != INVALID_HANDLE_VALUE &&
GetFileType(hStdErr) == FILE_TYPE_CHAR) {
ret |= java_io_Console_TTY_STDERR_MASK;
}
return ret;
}
@@ -78,6 +78,8 @@ environment=\
process.top process.ps \
memory.free memory.vmstat.default memory.vmstat.statistics \
memory.vmstat.slabinfo memory.vmstat.disk \
memory.proc_meminfo memory.proc_vmstat \
memory.thp \
files \
locks \
net.sockets net.statistics net.ifconfig net.hostsfile \
@@ -115,6 +117,15 @@ memory.vmstat.default.args=3 3
memory.vmstat.statistics.args=-s
memory.vmstat.slabinfo.args=-m
memory.vmstat.disk.args=-d
memory.proc_meminfo.app=bash
memory.proc_meminfo.args=-c\0cat /proc/meminfo
memory.proc_meminfo.delimiter=\0
memory.proc_vmstat.app=bash
memory.proc_vmstat.args=-c\0cat /proc/vmstat
memory.proc_vmstat.delimiter=\0
memory.thp.app=bash
memory.thp.args=-c\0cat /sys/kernel/mm/transparent_hugepage/{enabled,defrag,shmem_enabled}
memory.thp.delimiter=\0
files.app=lsof
locks.app=lslocks
@@ -1958,6 +1958,8 @@ generate(SpecialCases, [["ccmn", "__ ccmn(zr, zr, 3u, Assembler::LE);",
["cpy", "__ sve_cpy(z5, __ D, p0, -32768, false);", "mov\tz5.d, p0/z, -32768"],
["cpy", "__ sve_cpy(z10, __ B, p0, -1, false);", "mov\tz10.b, p0/z, -1"],
["cpy", "__ sve_cpy(z11, __ S, p0, -1, false);", "mov\tz11.s, p0/z, -1"],
["fcpy", "__ sve_cpy(z11, __ S, p0, 0.5);", "fcpy\tz11.s, p0/m, #0.5"],
["fcpy", "__ sve_cpy(z11, __ S, p0, -1.0);", "fcpy\tz11.s, p0/m, #-1.0"],
["inc", "__ sve_inc(r0, __ S);", "incw\tx0"],
["dec", "__ sve_dec(r1, __ H);", "dech\tx1"],
["lsl", "__ sve_lsl(z0, __ B, z1, 7);", "lsl\tz0.b, z1.b, #7"],
+127 -124
View File
@@ -971,6 +971,8 @@
__ sve_cpy(z5, __ D, p0, -32768, false); // mov z5.d, p0/z, -32768
__ sve_cpy(z10, __ B, p0, -1, false); // mov z10.b, p0/z, -1
__ sve_cpy(z11, __ S, p0, -1, false); // mov z11.s, p0/z, -1
__ sve_cpy(z11, __ S, p0, 0.5); // fcpy z11.s, p0/m, #0.5
__ sve_cpy(z11, __ S, p0, -1.0); // fcpy z11.s, p0/m, #-1.0
__ sve_inc(r0, __ S); // incw x0
__ sve_dec(r1, __ H); // dech x1
__ sve_lsl(z0, __ B, z1, 7); // lsl z0.b, z1.b, #7
@@ -1442,30 +1444,30 @@
0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061,
0x120cb166, 0x321764bc, 0x52174681, 0x720c0227,
0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01,
0x14000000, 0x17ffffd7, 0x140004b4, 0x94000000,
0x97ffffd4, 0x940004b1, 0x3400000a, 0x34fffa2a,
0x340095ca, 0x35000008, 0x35fff9c8, 0x35009568,
0xb400000b, 0xb4fff96b, 0xb400950b, 0xb500001d,
0xb5fff91d, 0xb50094bd, 0x10000013, 0x10fff8b3,
0x10009453, 0x90000013, 0x36300016, 0x3637f836,
0x363093d6, 0x3758000c, 0x375ff7cc, 0x3758936c,
0x14000000, 0x17ffffd7, 0x140004b6, 0x94000000,
0x97ffffd4, 0x940004b3, 0x3400000a, 0x34fffa2a,
0x3400960a, 0x35000008, 0x35fff9c8, 0x350095a8,
0xb400000b, 0xb4fff96b, 0xb400954b, 0xb500001d,
0xb5fff91d, 0xb50094fd, 0x10000013, 0x10fff8b3,
0x10009493, 0x90000013, 0x36300016, 0x3637f836,
0x36309416, 0x3758000c, 0x375ff7cc, 0x375893ac,
0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc,
0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f,
0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016,
0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0,
0x54009140, 0x54000001, 0x54fff541, 0x540090e1,
0x54000002, 0x54fff4e2, 0x54009082, 0x54000002,
0x54fff482, 0x54009022, 0x54000003, 0x54fff423,
0x54008fc3, 0x54000003, 0x54fff3c3, 0x54008f63,
0x54000004, 0x54fff364, 0x54008f04, 0x54000005,
0x54fff305, 0x54008ea5, 0x54000006, 0x54fff2a6,
0x54008e46, 0x54000007, 0x54fff247, 0x54008de7,
0x54000008, 0x54fff1e8, 0x54008d88, 0x54000009,
0x54fff189, 0x54008d29, 0x5400000a, 0x54fff12a,
0x54008cca, 0x5400000b, 0x54fff0cb, 0x54008c6b,
0x5400000c, 0x54fff06c, 0x54008c0c, 0x5400000d,
0x54fff00d, 0x54008bad, 0x5400000e, 0x54ffefae,
0x54008b4e, 0x5400000f, 0x54ffef4f, 0x54008aef,
0x54009180, 0x54000001, 0x54fff541, 0x54009121,
0x54000002, 0x54fff4e2, 0x540090c2, 0x54000002,
0x54fff482, 0x54009062, 0x54000003, 0x54fff423,
0x54009003, 0x54000003, 0x54fff3c3, 0x54008fa3,
0x54000004, 0x54fff364, 0x54008f44, 0x54000005,
0x54fff305, 0x54008ee5, 0x54000006, 0x54fff2a6,
0x54008e86, 0x54000007, 0x54fff247, 0x54008e27,
0x54000008, 0x54fff1e8, 0x54008dc8, 0x54000009,
0x54fff189, 0x54008d69, 0x5400000a, 0x54fff12a,
0x54008d0a, 0x5400000b, 0x54fff0cb, 0x54008cab,
0x5400000c, 0x54fff06c, 0x54008c4c, 0x5400000d,
0x54fff00d, 0x54008bed, 0x5400000e, 0x54ffefae,
0x54008b8e, 0x5400000f, 0x54ffef4f, 0x54008b2f,
0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60,
0xd44cad80, 0xd503201f, 0xd503203f, 0xd503205f,
0xd503209f, 0xd50320bf, 0xd503219f, 0xd50323bf,
@@ -1640,109 +1642,110 @@
0x4e21c862, 0x0e79c862, 0x4e79c862, 0x4e61b8a4,
0x0e79b8a4, 0x4e79b8a4, 0x05a08020, 0x05104fe0,
0x05505001, 0x05906fe2, 0x05d03005, 0x05101fea,
0x05901feb, 0x04b0e3e0, 0x0470e7e1, 0x042f9c20,
0x043f9c35, 0x047f9c20, 0x04ff9c20, 0x04299420,
0x04319160, 0x0461943e, 0x04a19020, 0x04038100,
0x040381a0, 0x040387e1, 0x04438be2, 0x04c38fe3,
0x040181e0, 0x04018100, 0x04018621, 0x04418b22,
0x04418822, 0x04818c23, 0x040081e0, 0x04008120,
0x04008761, 0x04008621, 0x04408822, 0x04808c23,
0x042053ff, 0x047f5401, 0x25208028, 0x2538cfe0,
0x2578d001, 0x25b8efe2, 0x25f8f007, 0x2538dfea,
0x25b8dfeb, 0xa400a3e0, 0xa420a7e0, 0xa4484be0,
0xa467afe0, 0xa4a8a7ea, 0xa547a814, 0xa4084ffe,
0xa55c53e0, 0xa5e1540b, 0xe400fbf6, 0xe408ffff,
0xe420e7e0, 0xe4484be0, 0xe460efe0, 0xe547e400,
0xe4014be0, 0xe4a84fe0, 0xe5f15000, 0x858043e0,
0x85a043ff, 0xe59f5d08, 0x0420e3e9, 0x0460e3ea,
0x04a0e3eb, 0x04e0e3ec, 0x25104042, 0x25104871,
0x25904861, 0x25904c92, 0x05344020, 0x05744041,
0x05b44062, 0x05f44083, 0x252c8840, 0x253c1420,
0x25681572, 0x25a21ce3, 0x25ea1e34, 0x253c0421,
0x25680572, 0x25a20ce3, 0x25ea0e34, 0x0522c020,
0x05e6c0a4, 0x2401a001, 0x2443a051, 0x24858881,
0x24c78cd1, 0x24850891, 0x24c70cc1, 0x250f9001,
0x25508051, 0x25802491, 0x25df28c1, 0x25850c81,
0x251e10d1, 0x65816001, 0x65c36051, 0x65854891,
0x65c74cc1, 0x05733820, 0x05b238a4, 0x05f138e6,
0x0570396a, 0x65d0a001, 0x65d6a443, 0x65d4a826,
0x6594ac26, 0x6554ac26, 0x6556ac26, 0x6552ac26,
0x65cbac85, 0x65caac01, 0x6589ac85, 0x6588ac01,
0x65c9ac85, 0x65c8ac01, 0x65dea833, 0x659ca509,
0x65d8a801, 0x65dcac01, 0x655cb241, 0x0520a1e0,
0x0521a601, 0x052281e0, 0x05238601, 0x04a14026,
0x042244a6, 0x046344a6, 0x04a444a6, 0x04e544a7,
0x0568aca7, 0x05b23230, 0x05302a30, 0x05702a30,
0x05b02a30, 0x05f02a30, 0x853040af, 0xc5b040af,
0xe57080af, 0xe5b080af, 0x25034440, 0x254054c4,
0x25034640, 0x25415a05, 0x25834440, 0x25c54489,
0x250b5d3a, 0x2550dc20, 0x2518e3e1, 0x2518e021,
0x2518e0a1, 0x2518e121, 0x2518e1a1, 0x2558e3e2,
0x2558e042, 0x2558e0c2, 0x2558e142, 0x2598e3e3,
0x2598e063, 0x2598e0e3, 0x2598e163, 0x25d8e3e4,
0x25d8e084, 0x25d8e104, 0x25d8e184, 0x2518e407,
0x05214800, 0x05614800, 0x05a14800, 0x05e14800,
0x05214c00, 0x05614c00, 0x05a14c00, 0x05e14c00,
0x05304001, 0x05314001, 0x05a18610, 0x05e18610,
0x05271e11, 0x6545e891, 0x6585e891, 0x65c5e891,
0x6545c891, 0x6585c891, 0x65c5c891, 0x45b0c210,
0x45f1c231, 0x1e601000, 0x1e603000, 0x1e621000,
0x1e623000, 0x1e641000, 0x1e643000, 0x1e661000,
0x1e663000, 0x1e681000, 0x1e683000, 0x1e6a1000,
0x1e6a3000, 0x1e6c1000, 0x1e6c3000, 0x1e6e1000,
0x1e6e3000, 0x1e701000, 0x1e703000, 0x1e721000,
0x1e723000, 0x1e741000, 0x1e743000, 0x1e761000,
0x1e763000, 0x1e781000, 0x1e783000, 0x1e7a1000,
0x1e7a3000, 0x1e7c1000, 0x1e7c3000, 0x1e7e1000,
0x1e7e3000, 0xf8268267, 0xf82d023c, 0xf8301046,
0xf83d2083, 0xf8263290, 0xf82d528c, 0xf8284299,
0xf8337160, 0xf8386286, 0xf8bf820e, 0xf8a600e0,
0xf8af1353, 0xf8a922ea, 0xf8b53396, 0xf8a251e3,
0xf8b340f4, 0xf8a470fd, 0xf8a06209, 0xf8f48097,
0xf8f002ea, 0xf8eb10d9, 0xf8ff21b0, 0xf8f7302c,
0xf8ee52a9, 0xf8f041fa, 0xf8e471e4, 0xf8e863c6,
0xf864823d, 0xf87d013a, 0xf86f1162, 0xf87d20e3,
0xf86132bb, 0xf870510e, 0xf8704336, 0xf86572b4,
0xf8706217, 0xb83e8294, 0xb8200264, 0xb8381284,
0xb8242358, 0xb8333102, 0xb828530e, 0xb83042df,
0xb824703f, 0xb82a6194, 0xb8a080e9, 0xb8b80090,
0xb8bb1146, 0xb8bb21b8, 0xb8b032df, 0xb8b653f4,
0xb8bd41c9, 0xb8b47287, 0xb8bc6169, 0xb8ee828c,
0xb8e10138, 0xb8f3126d, 0xb8f020b0, 0xb8e03183,
0xb8e851ef, 0xb8f041e4, 0xb8fe7005, 0xb8ea6376,
0xb8638120, 0xb873015d, 0xb8781284, 0xb86723b8,
0xb86e3175, 0xb87b51ed, 0xb87f41d1, 0xb863721e,
0xb87660f4, 0xce216874, 0xce104533, 0xce648c15,
0xce8e3302, 0xce6e82ab, 0xce6c87d1, 0xcec08063,
0xce638937, 0x25e0c358, 0x25a1c7d3, 0x0580785a,
0x05426328, 0x05009892, 0x25a0cc29, 0x2561cec8,
0x058044b3, 0x05401c99, 0x05006b49, 0x25e0d6f7,
0x2561c528, 0x0583c8bc, 0x0542522f, 0x05001ec0,
0x25e0de65, 0x25a1c113, 0x05803cad, 0x0540f3c0,
0x0500ab15, 0x2560c28c, 0x2561d7c0, 0x05801ed7,
0x0542633b, 0x05003696, 0x2560d4b4, 0x25e1c918,
0x058021ff, 0x05400e15, 0x0500f3de, 0x0473025a,
0x04bd05ab, 0x658e0025, 0x658a08e2, 0x659a0493,
0x043e1062, 0x04f418b4, 0x046d15bd, 0x04611fce,
0x04d6a07c, 0x04001929, 0x041a09da, 0x04d098f4,
0x04db10d4, 0x0459a3ad, 0x041aa029, 0x041919fb,
0x04d39e24, 0x04118302, 0x04101dba, 0x04d7ae16,
0x04dea571, 0x04180210, 0x05e786fc, 0x05e4915c,
0x04881cf1, 0x044a0f04, 0x04090969, 0x048b16c4,
0x044101e4, 0x04dcbf44, 0x65809745, 0x658d833f,
0x65c68468, 0x65c79b07, 0x65829e38, 0x049dafca,
0x6582bba8, 0x65c0b7ff, 0x65c1b4e0, 0x658dbadd,
0x65819a9d, 0x65ed9246, 0x65b30815, 0x65e6263c,
0x65eebb94, 0x65bad14e, 0x65efe178, 0x65fc5697,
0x65e07f14, 0x040c55a6, 0x04977f4d, 0x043d3046,
0x04b733a0, 0x046830a4, 0x04ed322d, 0x05686948,
0x05bd6c13, 0x65c88ef0, 0x450db3d7, 0x4540b6d9,
0x043e3979, 0x445896ce, 0x445a9005, 0x44d98069,
0x445b87ae, 0x04da348e, 0x04982edb, 0x0499397f,
0x0408338c, 0x04ca309c, 0x65c721e6, 0x65c63641,
0x65982882, 0x04812b8b, 0x0e251083, 0x4e3712d5,
0x0e61101f, 0x4e6d118b, 0x0eba1338, 0x4eb712d5,
0x2e31120f, 0x6e2e11ac, 0x2e6810e6, 0x6e6f11cd,
0x2eaa1128, 0x6eb1120f,
0x05901feb, 0x0590cc0b, 0x0590de0b, 0x04b0e3e0,
0x0470e7e1, 0x042f9c20, 0x043f9c35, 0x047f9c20,
0x04ff9c20, 0x04299420, 0x04319160, 0x0461943e,
0x04a19020, 0x04038100, 0x040381a0, 0x040387e1,
0x04438be2, 0x04c38fe3, 0x040181e0, 0x04018100,
0x04018621, 0x04418b22, 0x04418822, 0x04818c23,
0x040081e0, 0x04008120, 0x04008761, 0x04008621,
0x04408822, 0x04808c23, 0x042053ff, 0x047f5401,
0x25208028, 0x2538cfe0, 0x2578d001, 0x25b8efe2,
0x25f8f007, 0x2538dfea, 0x25b8dfeb, 0xa400a3e0,
0xa420a7e0, 0xa4484be0, 0xa467afe0, 0xa4a8a7ea,
0xa547a814, 0xa4084ffe, 0xa55c53e0, 0xa5e1540b,
0xe400fbf6, 0xe408ffff, 0xe420e7e0, 0xe4484be0,
0xe460efe0, 0xe547e400, 0xe4014be0, 0xe4a84fe0,
0xe5f15000, 0x858043e0, 0x85a043ff, 0xe59f5d08,
0x0420e3e9, 0x0460e3ea, 0x04a0e3eb, 0x04e0e3ec,
0x25104042, 0x25104871, 0x25904861, 0x25904c92,
0x05344020, 0x05744041, 0x05b44062, 0x05f44083,
0x252c8840, 0x253c1420, 0x25681572, 0x25a21ce3,
0x25ea1e34, 0x253c0421, 0x25680572, 0x25a20ce3,
0x25ea0e34, 0x0522c020, 0x05e6c0a4, 0x2401a001,
0x2443a051, 0x24858881, 0x24c78cd1, 0x24850891,
0x24c70cc1, 0x250f9001, 0x25508051, 0x25802491,
0x25df28c1, 0x25850c81, 0x251e10d1, 0x65816001,
0x65c36051, 0x65854891, 0x65c74cc1, 0x05733820,
0x05b238a4, 0x05f138e6, 0x0570396a, 0x65d0a001,
0x65d6a443, 0x65d4a826, 0x6594ac26, 0x6554ac26,
0x6556ac26, 0x6552ac26, 0x65cbac85, 0x65caac01,
0x6589ac85, 0x6588ac01, 0x65c9ac85, 0x65c8ac01,
0x65dea833, 0x659ca509, 0x65d8a801, 0x65dcac01,
0x655cb241, 0x0520a1e0, 0x0521a601, 0x052281e0,
0x05238601, 0x04a14026, 0x042244a6, 0x046344a6,
0x04a444a6, 0x04e544a7, 0x0568aca7, 0x05b23230,
0x05302a30, 0x05702a30, 0x05b02a30, 0x05f02a30,
0x853040af, 0xc5b040af, 0xe57080af, 0xe5b080af,
0x25034440, 0x254054c4, 0x25034640, 0x25415a05,
0x25834440, 0x25c54489, 0x250b5d3a, 0x2550dc20,
0x2518e3e1, 0x2518e021, 0x2518e0a1, 0x2518e121,
0x2518e1a1, 0x2558e3e2, 0x2558e042, 0x2558e0c2,
0x2558e142, 0x2598e3e3, 0x2598e063, 0x2598e0e3,
0x2598e163, 0x25d8e3e4, 0x25d8e084, 0x25d8e104,
0x25d8e184, 0x2518e407, 0x05214800, 0x05614800,
0x05a14800, 0x05e14800, 0x05214c00, 0x05614c00,
0x05a14c00, 0x05e14c00, 0x05304001, 0x05314001,
0x05a18610, 0x05e18610, 0x05271e11, 0x6545e891,
0x6585e891, 0x65c5e891, 0x6545c891, 0x6585c891,
0x65c5c891, 0x45b0c210, 0x45f1c231, 0x1e601000,
0x1e603000, 0x1e621000, 0x1e623000, 0x1e641000,
0x1e643000, 0x1e661000, 0x1e663000, 0x1e681000,
0x1e683000, 0x1e6a1000, 0x1e6a3000, 0x1e6c1000,
0x1e6c3000, 0x1e6e1000, 0x1e6e3000, 0x1e701000,
0x1e703000, 0x1e721000, 0x1e723000, 0x1e741000,
0x1e743000, 0x1e761000, 0x1e763000, 0x1e781000,
0x1e783000, 0x1e7a1000, 0x1e7a3000, 0x1e7c1000,
0x1e7c3000, 0x1e7e1000, 0x1e7e3000, 0xf8268267,
0xf82d023c, 0xf8301046, 0xf83d2083, 0xf8263290,
0xf82d528c, 0xf8284299, 0xf8337160, 0xf8386286,
0xf8bf820e, 0xf8a600e0, 0xf8af1353, 0xf8a922ea,
0xf8b53396, 0xf8a251e3, 0xf8b340f4, 0xf8a470fd,
0xf8a06209, 0xf8f48097, 0xf8f002ea, 0xf8eb10d9,
0xf8ff21b0, 0xf8f7302c, 0xf8ee52a9, 0xf8f041fa,
0xf8e471e4, 0xf8e863c6, 0xf864823d, 0xf87d013a,
0xf86f1162, 0xf87d20e3, 0xf86132bb, 0xf870510e,
0xf8704336, 0xf86572b4, 0xf8706217, 0xb83e8294,
0xb8200264, 0xb8381284, 0xb8242358, 0xb8333102,
0xb828530e, 0xb83042df, 0xb824703f, 0xb82a6194,
0xb8a080e9, 0xb8b80090, 0xb8bb1146, 0xb8bb21b8,
0xb8b032df, 0xb8b653f4, 0xb8bd41c9, 0xb8b47287,
0xb8bc6169, 0xb8ee828c, 0xb8e10138, 0xb8f3126d,
0xb8f020b0, 0xb8e03183, 0xb8e851ef, 0xb8f041e4,
0xb8fe7005, 0xb8ea6376, 0xb8638120, 0xb873015d,
0xb8781284, 0xb86723b8, 0xb86e3175, 0xb87b51ed,
0xb87f41d1, 0xb863721e, 0xb87660f4, 0xce216874,
0xce104533, 0xce648c15, 0xce8e3302, 0xce6e82ab,
0xce6c87d1, 0xcec08063, 0xce638937, 0x25e0c358,
0x25a1c7d3, 0x0580785a, 0x05426328, 0x05009892,
0x25a0cc29, 0x2561cec8, 0x058044b3, 0x05401c99,
0x05006b49, 0x25e0d6f7, 0x2561c528, 0x0583c8bc,
0x0542522f, 0x05001ec0, 0x25e0de65, 0x25a1c113,
0x05803cad, 0x0540f3c0, 0x0500ab15, 0x2560c28c,
0x2561d7c0, 0x05801ed7, 0x0542633b, 0x05003696,
0x2560d4b4, 0x25e1c918, 0x058021ff, 0x05400e15,
0x0500f3de, 0x0473025a, 0x04bd05ab, 0x658e0025,
0x658a08e2, 0x659a0493, 0x043e1062, 0x04f418b4,
0x046d15bd, 0x04611fce, 0x04d6a07c, 0x04001929,
0x041a09da, 0x04d098f4, 0x04db10d4, 0x0459a3ad,
0x041aa029, 0x041919fb, 0x04d39e24, 0x04118302,
0x04101dba, 0x04d7ae16, 0x04dea571, 0x04180210,
0x05e786fc, 0x05e4915c, 0x04881cf1, 0x044a0f04,
0x04090969, 0x048b16c4, 0x044101e4, 0x04dcbf44,
0x65809745, 0x658d833f, 0x65c68468, 0x65c79b07,
0x65829e38, 0x049dafca, 0x6582bba8, 0x65c0b7ff,
0x65c1b4e0, 0x658dbadd, 0x65819a9d, 0x65ed9246,
0x65b30815, 0x65e6263c, 0x65eebb94, 0x65bad14e,
0x65efe178, 0x65fc5697, 0x65e07f14, 0x040c55a6,
0x04977f4d, 0x043d3046, 0x04b733a0, 0x046830a4,
0x04ed322d, 0x05686948, 0x05bd6c13, 0x65c88ef0,
0x450db3d7, 0x4540b6d9, 0x043e3979, 0x445896ce,
0x445a9005, 0x44d98069, 0x445b87ae, 0x04da348e,
0x04982edb, 0x0499397f, 0x0408338c, 0x04ca309c,
0x65c721e6, 0x65c63641, 0x65982882, 0x04812b8b,
0x0e251083, 0x4e3712d5, 0x0e61101f, 0x4e6d118b,
0x0eba1338, 0x4eb712d5, 0x2e31120f, 0x6e2e11ac,
0x2e6810e6, 0x6e6f11cd, 0x2eaa1128, 0x6eb1120f,
};
// END Generated code -- do not edit
@@ -1417,6 +1417,11 @@ public class IRNode {
beforeMatchingNameRegex(VECTOR_MASK_TO_LONG, "VectorMaskToLong");
}
public static final String VECTOR_MASK_LANE_IS_SET = PREFIX + "VECTOR_MASK_LANE_IS_SET" + POSTFIX;
static {
beforeMatchingNameRegex(VECTOR_MASK_LANE_IS_SET, "ExtractUB");
}
// Can only be used if avx512_vnni is available.
public static final String MUL_ADD_VS2VI_VNNI = PREFIX + "MUL_ADD_VS2VI_VNNI" + POSTFIX;
static {
@@ -42,8 +42,8 @@ public class CheckLoopStripMining {
"-XX:+SafepointTimeout",
"-XX:+SafepointALot",
"-XX:+AbortVMOnSafepointTimeout",
"-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(300),
"-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(300),
"-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(1200),
"-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(1200),
"-XX:-TieredCompilation",
"-XX:+UseCountedLoopSafepoints",
"-XX:LoopStripMiningIter=1000",
@@ -58,8 +58,8 @@ public class CheckLoopStripMining {
"-XX:+SafepointTimeout",
"-XX:+SafepointALot",
"-XX:+AbortVMOnSafepointTimeout",
"-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(300),
"-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(300),
"-XX:SafepointTimeoutDelay=" + Utils.adjustTimeout(1200),
"-XX:GuaranteedSafepointInterval=" + Utils.adjustTimeout(1200),
"-XX:-TieredCompilation",
"-XX:+UseCountedLoopSafepoints",
"-XX:LoopStripMiningIter=1000",
@@ -0,0 +1,160 @@
/*
* Copyright (c) 2025, NVIDIA CORPORATION & 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.vectorapi;
import compiler.lib.ir_framework.*;
import jdk.incubator.vector.*;
import jdk.test.lib.Asserts;
/**
* @test
* @bug 8366588
* @key randomness
* @library /test/lib /
* @summary VectorAPI: Re-intrinsify VectorMask.laneIsSet where the input index is a variable
* @modules jdk.incubator.vector
*
* @run driver compiler.vectorapi.VectorMaskLaneIsSetTest
*/
public class VectorMaskLaneIsSetTest {
static final VectorSpecies<Byte> B_SPECIES = ByteVector.SPECIES_MAX;
static final VectorSpecies<Short> S_SPECIES = ShortVector.SPECIES_MAX;
static final VectorSpecies<Integer> I_SPECIES = IntVector.SPECIES_MAX;
static final VectorSpecies<Float> F_SPECIES = FloatVector.SPECIES_MAX;
static final VectorSpecies<Long> L_SPECIES = LongVector.SPECIES_MAX;
static final VectorSpecies<Double> D_SPECIES = DoubleVector.SPECIES_MAX;
static final int LENGTH = 512;
static boolean[] ma;
static VectorMask<Byte> mask_b;
static VectorMask<Short> mask_s;
static VectorMask<Integer> mask_i;
static VectorMask<Long> mask_l;
static VectorMask<Float> mask_f;
static VectorMask<Double> mask_d;
static {
ma = new boolean[LENGTH];
for (int i = 0; i < LENGTH; i++) {
ma[i] = i % 2 == 0;
}
mask_b = VectorMask.fromArray(B_SPECIES, ma, 0);
mask_s = VectorMask.fromArray(S_SPECIES, ma, 0);
mask_i = VectorMask.fromArray(I_SPECIES, ma, 0);
mask_l = VectorMask.fromArray(L_SPECIES, ma, 0);
mask_f = VectorMask.fromArray(F_SPECIES, ma, 0);
mask_d = VectorMask.fromArray(D_SPECIES, ma, 0);
}
@Test
@IR(counts = { IRNode.VECTOR_MASK_LANE_IS_SET, "= 6" }, applyIfCPUFeature = { "asimd", "true" })
@IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 6" }, applyIfCPUFeatureOr = { "avx2", "true", "rvv", "true" })
public static void testVectorMaskLaneIsSetByte_const() {
Asserts.assertEquals(ma[0], mask_b.laneIsSet(0));
Asserts.assertEquals(ma[0], mask_s.laneIsSet(0));
Asserts.assertEquals(ma[0], mask_i.laneIsSet(0));
Asserts.assertEquals(ma[0], mask_l.laneIsSet(0));
Asserts.assertEquals(ma[0], mask_f.laneIsSet(0));
Asserts.assertEquals(ma[0], mask_d.laneIsSet(0));
}
@Test
@IR(counts = { IRNode.VECTOR_MASK_LANE_IS_SET, "= 1" }, applyIfCPUFeature = { "asimd", "true" })
@IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 1" }, applyIfCPUFeatureOr = { "avx", "true", "rvv", "true" })
public static boolean testVectorMaskLaneIsSet_Byte_variable(int i) {
return mask_b.laneIsSet(i);
}
@Run(test = "testVectorMaskLaneIsSet_Byte_variable")
public static void testVectorMaskLaneIsSet_Byte_variable_runner() {
Asserts.assertEquals(ma[0], testVectorMaskLaneIsSet_Byte_variable(0));
}
@Test
@IR(counts = { IRNode.VECTOR_MASK_LANE_IS_SET, "= 1" }, applyIfCPUFeature = { "asimd", "true" })
@IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 1" }, applyIfCPUFeatureOr = { "avx", "true", "rvv", "true" })
public static boolean testVectorMaskLaneIsSet_Short_variable(int i) {
return mask_s.laneIsSet(i);
}
@Run(test = "testVectorMaskLaneIsSet_Short_variable")
public static void testVectorMaskLaneIsSet_Short_variable_runner() {
Asserts.assertEquals(ma[0], testVectorMaskLaneIsSet_Short_variable(0));
}
@Test
@IR(counts = { IRNode.VECTOR_MASK_LANE_IS_SET, "= 1" }, applyIfCPUFeature = { "asimd", "true" })
@IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 1" }, applyIfCPUFeatureOr = { "avx", "true", "rvv", "true" })
public static boolean testVectorMaskLaneIsSet_Int_variable(int i) {
return mask_i.laneIsSet(i);
}
@Run(test = "testVectorMaskLaneIsSet_Int_variable")
public static void testVectorMaskLaneIsSet_Int_variable_runner() {
Asserts.assertEquals(ma[0], testVectorMaskLaneIsSet_Int_variable(0));
}
@Test
@IR(counts = { IRNode.VECTOR_MASK_LANE_IS_SET, "= 1" }, applyIfCPUFeature = { "asimd", "true" })
@IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 1" }, applyIfCPUFeatureOr = { "avx2", "true", "rvv", "true" })
public static boolean testVectorMaskLaneIsSet_Long_variable(int i) {
return mask_l.laneIsSet(i);
}
@Run(test = "testVectorMaskLaneIsSet_Long_variable")
public static void testVectorMaskLaneIsSet_Long_variable_runner() {
Asserts.assertEquals(ma[0], testVectorMaskLaneIsSet_Long_variable(0));
}
@Test
@IR(counts = { IRNode.VECTOR_MASK_LANE_IS_SET, "= 1" }, applyIfCPUFeature = { "asimd", "true" })
@IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 1" }, applyIfCPUFeatureOr = { "avx", "true", "rvv", "true" })
public static boolean testVectorMaskLaneIsSet_Float_variable(int i) {
return mask_f.laneIsSet(i);
}
@Run(test = "testVectorMaskLaneIsSet_Float_variable")
public static void testVectorMaskLaneIsSet_Float_variable_runner() {
Asserts.assertEquals(ma[0], testVectorMaskLaneIsSet_Float_variable(0));
}
@Test
@IR(counts = { IRNode.VECTOR_MASK_LANE_IS_SET, "= 1" }, applyIfCPUFeature = { "asimd", "true" })
@IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 1" }, applyIfCPUFeatureOr = { "avx2", "true", "rvv", "true" })
public static boolean testVectorMaskLaneIsSet_Double_variable(int i) {
return mask_d.laneIsSet(i);
}
@Run(test = "testVectorMaskLaneIsSet_Double_variable")
public static void testVectorMaskLaneIsSet_Double_variable_runner() {
Asserts.assertEquals(ma[0], testVectorMaskLaneIsSet_Double_variable(0));
}
public static void main(String[] args) {
TestFramework testFramework = new TestFramework();
testFramework.setDefaultWarmup(10000)
.addFlags("--add-modules=jdk.incubator.vector")
.start();
}
}
@@ -44,6 +44,7 @@ public class TestIncludesAreSorted {
*/
private static final String[] HOTSPOT_SOURCES_TO_CHECK = {
"os/linux",
"os/posix",
"share"
};
@@ -21,9 +21,9 @@
* questions.
*/
/**
/*
* @test
* @bug 8295803 8299689 8351435 8361613
* @bug 8295803 8299689 8351435 8361613 8366261
* @summary Tests System.console() returns correct Console (or null) from the expected
* module.
* @library /test/lib
@@ -92,9 +92,12 @@ public class ModuleSelectionTest {
var con = System.console();
var pc = Class.forName("java.io.ProxyingConsole");
var jdkc = Class.forName("jdk.internal.io.JdkConsole");
var istty = (boolean)MethodHandles.privateLookupIn(Console.class, MethodHandles.lookup())
.findStatic(Console.class, "istty", MethodType.methodType(boolean.class))
.invoke();
var lookup = MethodHandles.privateLookupIn(Console.class, MethodHandles.lookup());
var istty = (boolean)lookup.findStatic(Console.class, "isStdinTty", MethodType.methodType(boolean.class))
.invoke() &&
(boolean)lookup.findStatic(Console.class, "isStdoutTty", MethodType.methodType(boolean.class))
.invoke();
var impl = con != null ? MethodHandles.privateLookupIn(pc, MethodHandles.lookup())
.findGetter(pc, "delegate", jdkc)
.invoke(con) : null;
+23 -2
View File
@@ -212,7 +212,7 @@ public class Basic {
private static String winEnvFilter(String env) {
return env.replaceAll("\r", "")
.replaceAll("(?m)^(?:COMSPEC|PROMPT|PATHEXT)=.*\n","");
.replaceAll("(?m)^(?:COMSPEC|PROMPT|PATHEXT|PROCESSOR_ARCHITECTURE)=.*\n","");
}
private static String unixEnvProg() {
@@ -811,6 +811,14 @@ public class Basic {
return vars.replace("AIXTHREAD_GUARDPAGES=0,", "");
}
/* Only used for Windows AArch64 --
* Windows AArch64 adds the variable PROCESSOR_ARCHITECTURE=ARM64 to the environment.
* Remove it from the list of env variables
*/
private static String removeWindowsAArch64ExpectedVars(String vars) {
return vars.replace("PROCESSOR_ARCHITECTURE=ARM64,", "");
}
private static String sortByLinesWindowsly(String text) {
String[] lines = text.split("\n");
Arrays.sort(lines, new WindowsComparator());
@@ -1321,6 +1329,9 @@ public class Basic {
if (AIX.is()) {
result = removeAixExpectedVars(result);
}
if (Windows.is() && Platform.isAArch64()) {
result = removeWindowsAArch64ExpectedVars(result);
}
equal(result, expected);
} catch (Throwable t) { unexpected(t); }
@@ -1833,6 +1844,9 @@ public class Basic {
if (AIX.is()) {
commandOutput = removeAixExpectedVars(commandOutput);
}
if (Windows.is() && Platform.isAArch64()) {
commandOutput = removeWindowsAArch64ExpectedVars(commandOutput);
}
equal(commandOutput, expected);
if (Windows.is()) {
ProcessBuilder pb = new ProcessBuilder(childArgs);
@@ -1840,7 +1854,11 @@ public class Basic {
pb.environment().put("SystemRoot", systemRoot);
pb.environment().put("=ExitValue", "3");
pb.environment().put("=C:", "\\");
equal(commandOutput(pb), expected);
commandOutput = commandOutput(pb);
if (Platform.isAArch64()) {
commandOutput = removeWindowsAArch64ExpectedVars(commandOutput);
}
equal(commandOutput, expected);
}
} catch (Throwable t) { unexpected(t); }
@@ -1892,6 +1910,9 @@ public class Basic {
if (AIX.is()) {
commandOutput = removeAixExpectedVars(commandOutput);
}
if (Windows.is() && Platform.isAArch64()) {
commandOutput = removeWindowsAArch64ExpectedVars(commandOutput);
}
check(commandOutput.equals(Windows.is()
? "LC_ALL=C,SystemRoot="+systemRoot+","
: AIX.is()
@@ -23,7 +23,9 @@
/*
* @test
* @bug 8366401
* @bug 4068067 4101150 8366401
* @library /java/text/testlib
* @build HexDumpReader
* @summary Check serialization of DecimalFormatSymbols. That is, ensure the
* behavior for each stream version is correct during de-serialization.
* @run junit/othervm --add-opens java.base/java.text=ALL-UNNAMED DFSSerializationTest
@@ -35,9 +37,11 @@ import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.text.DecimalFormatSymbols;
import java.util.Currency;
@@ -51,13 +55,36 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
public class DFSSerializationTest {
// Test that rely on hex dump files that were written from older JDK versions
@Nested
class VersionTests {
class HexDumpTests {
@Test // See 4068067 and CDFS which is the class in the serialized hex dump
void JDK1_1_4Test() {
// Reconstruct a class serialized during 1.1.4 which has a DFS holder
var cdfs = (CheckDecimalFormatSymbols) assertDoesNotThrow(
() -> deSer("DecimalFormatSymbols.114.txt"));
assertDoesNotThrow(cdfs::Update); // Checks getDigit call succeeds
}
@Test // See 4068067
void JDK1_4_2Test() {
// Reconstruct a 1.4.2 DFS
var dfs = (DecimalFormatSymbols) assertDoesNotThrow(
() -> deSer("DecimalFormatSymbols.142.txt"));
// Checks curr symbol is saved, and exponent separator default set
assertEquals("E", dfs.getExponentSeparator());
assertEquals("*SpecialCurrencySymbol*", dfs.getCurrencySymbol());
}
}
@Nested
class StreamVersionTests {
// Ensure correct monetarySeparator and exponential field defaults
// Reads monetary from decimal, and sets exponential to 'E'
@Test
public void version0Test() {
void version0Test() {
var crafted = new DFSBuilder()
.setVer(0)
.set("monetarySeparator", '~')
@@ -76,7 +103,7 @@ public class DFSSerializationTest {
// Note that other versions did allow a locale field, which was nullable.
// E.g. see nullableLocaleTest which does not set locale when it is `null`
@Test
public void version1Test() {
void version1Test() {
var crafted = new DFSBuilder()
.setVer(1)
.set("locale", null)
@@ -89,7 +116,7 @@ public class DFSSerializationTest {
// Version 2 did not have an exponential separator, and created it via exponent
// char field.
@Test
public void version2Test() {
void version2Test() {
var crafted = new DFSBuilder()
.setVer(2)
.set("exponentialSeparator", null)
@@ -103,7 +130,7 @@ public class DFSSerializationTest {
// Version 3 didn't have perMillText, percentText, and minusSignText.
// These were created from the corresponding char equivalents.
@Test
public void version3Test() {
void version3Test() {
var crafted = new DFSBuilder()
.setVer(3)
.set("perMillText", null)
@@ -125,7 +152,7 @@ public class DFSSerializationTest {
// Version 4 did not have monetaryGroupingSeparator. It should be based
// off of groupingSeparator.
@Test
public void version4Test() {
void version4Test() {
var crafted = new DFSBuilder()
.setVer(4)
.set("monetaryGroupingSeparator", 'Z')
@@ -142,7 +169,7 @@ public class DFSSerializationTest {
// the case and previous stream versions can contain a null locale. Thus,
// ensure that a null locale does not cause number data loading to fail.
@Test
public void nullableLocaleTest() {
void nullableLocaleTest() {
var bytes = ser(new DFSBuilder()
.set("locale", null)
.set("minusSignText", "zFoo")
@@ -157,7 +184,7 @@ public class DFSSerializationTest {
// readObject fails when the {@code char} and {@code String} representations
// of percent, per mille, and/or minus sign disagree.
@Test
public void disagreeingTextTest() {
void disagreeingTextTest() {
var expected = "'char' and 'String' representations of either percent, " +
"per mille, and/or minus sign disagree.";
assertEquals(expected, assertThrows(InvalidObjectException.class, () ->
@@ -179,7 +206,7 @@ public class DFSSerializationTest {
// Ensure the serial version is updated to the current after de-serialization.
@Test
public void updatedVersionTest() {
void updatedVersionTest() {
var bytes = ser(new DFSBuilder().setVer(-25).build());
var dfs = assertDoesNotThrow(() -> deSer(bytes));
assertEquals(5, readField(dfs, "serialVersionOnStream"));
@@ -187,7 +214,7 @@ public class DFSSerializationTest {
// Should set currency from 4217 code when it is valid.
@Test
public void validIntlCurrencyTest() {
void validIntlCurrencyTest() {
var bytes = ser(new DFSBuilder().set("intlCurrencySymbol", "JPY").build());
var dfs = assertDoesNotThrow(() -> deSer(bytes));
assertEquals(Currency.getInstance("JPY"), dfs.getCurrency());
@@ -195,7 +222,7 @@ public class DFSSerializationTest {
// Should not set currency when 4217 code is invalid, it remains null.
@Test
public void invalidIntlCurrencyTest() {
void invalidIntlCurrencyTest() {
var bytes = ser(new DFSBuilder()
.set("intlCurrencySymbol", ">.,")
.set("locale", Locale.JAPAN)
@@ -205,6 +232,26 @@ public class DFSSerializationTest {
assertNull(dfs.getCurrency());
}
// Ensure the currency symbol is read properly
@Test
void currencySymbolTest() {
var crafted = new DecimalFormatSymbols();
crafted.setCurrencySymbol("*SpecialCurrencySymbol*");
var bytes = ser(crafted);
var dfs = assertDoesNotThrow(() -> deSer(bytes));
assertEquals("*SpecialCurrencySymbol*", dfs.getCurrencySymbol());
}
// Ensure the exponent separator is read properly
@Test
void exponentSeparatorTest() {
var crafted = new DecimalFormatSymbols();
crafted.setExponentSeparator("*SpecialExponentSeparator*");
var bytes = ser(crafted);
var dfs = assertDoesNotThrow(() -> deSer(bytes));
assertEquals("*SpecialExponentSeparator*", dfs.getExponentSeparator());
}
// Utilities ----
// Utility to serialize
@@ -218,7 +265,7 @@ public class DFSSerializationTest {
}, "Unexpected error during serialization");
}
// Utility to deserialize
// Utility to deserialize from byte array
private static DecimalFormatSymbols deSer(byte[] bytes) throws IOException, ClassNotFoundException {
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream)) {
@@ -226,6 +273,14 @@ public class DFSSerializationTest {
}
}
// Utility to deserialize from file in hex format
private static Object deSer(String file) throws IOException, ClassNotFoundException {
try (InputStream stream = HexDumpReader.getStreamFromHexDump(file);
ObjectInputStream ois = new ObjectInputStream(stream)) {
return ois.readObject();
}
}
// Utility to read a private field
private static Object readField(DecimalFormatSymbols dfs, String name) {
return assertDoesNotThrow(() -> {
@@ -262,3 +317,12 @@ public class DFSSerializationTest {
}
}
}
// Not nested, so that it can be cast correctly for the 1.1.4 test
class CheckDecimalFormatSymbols implements Serializable {
DecimalFormatSymbols _decFormatSymbols = new DecimalFormatSymbols();
public char Update()
{
return _decFormatSymbols.getDigit();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,65 +22,344 @@
*/
/*
* @test
* @bug 8327640
* @summary Check parseStrict correctness for DecimalFormat serialization
* @run junit/othervm SerializationTest
* @bug 4069754 4067878 4101150 4185761 8327640
* @library /java/text/testlib
* @build HexDumpReader
* @summary Check de-serialization correctness for DecimalFormat. That is, ensure the
* behavior for each stream version is correct during de-serialization.
* @run junit/othervm --add-opens java.base/java.text=ALL-UNNAMED SerializationTest
*/
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class SerializationTest {
private static final NumberFormat FORMAT = NumberFormat.getInstance();
@Nested // Test that rely on hex dump files that were written from older JDK versions
class HexDumpTests {
@BeforeAll
public static void mutateFormat() {
FORMAT.setStrict(true);
}
@Test // See 4101150 and CDF which is the serialized hex dump
void JDK1_1_4Test() {
// Reconstruct a 1.1.4 serializable class which has a DF holder
var cdf = (CheckDecimalFormat) assertDoesNotThrow(
() -> deSer("DecimalFormat.114.txt"));
assertDoesNotThrow(cdf::Update); // Checks format call succeeds
}
@Test
public void testSerialization() throws IOException, ClassNotFoundException {
// Serialize
serialize("fmt.ser", FORMAT);
// Deserialize
deserialize("fmt.ser", FORMAT);
}
@Test // See 4185761
void minMaxDigitsTest() {
// Reconstructing a DFS stream from an older JDK version
// The min digits are smaller than the max digits and should fail
// minint maxint minfrac maxfrac
// 0x122 0x121 0x124 0x123
assertEquals("Digit count range invalid",
assertThrows(InvalidObjectException.class,
() -> deSer("NumberFormat4185761a.ser.txt")).getMessage());
}
private void serialize(String fileName, NumberFormat... formats)
throws IOException {
try (ObjectOutputStream os = new ObjectOutputStream(
new FileOutputStream(fileName))) {
for (NumberFormat fmt : formats) {
os.writeObject(fmt);
}
@Test // See 4185761
void digitLimitTest() {
// Reconstructing a DFS stream from an older JDK version
// The digit values exceed the class invariant limits
// minint maxint minfrac maxfrac
// 0x311 0x312 0x313 0x314
assertEquals("Digit count out of range",
assertThrows(InvalidObjectException.class,
() -> deSer("NumberFormat4185761b.ser.txt")).getMessage());
}
}
private static void deserialize(String fileName, NumberFormat... formats)
throws IOException, ClassNotFoundException {
try (ObjectInputStream os = new ObjectInputStream(
new FileInputStream(fileName))) {
for (NumberFormat fmt : formats) {
NumberFormat obj = (NumberFormat) os.readObject();
assertEquals(fmt, obj, "Serialized and deserialized"
+ " objects do not match");
@Nested
class VersionTests {
String badNumber = "fooofooo23foo";
assertThrows(ParseException.class, () -> fmt.parse(badNumber));
assertThrows(ParseException.class, () -> obj.parse(badNumber));
// Version 0 did not have exponential fields and defaulted the value to false
@Test
void version0Test() {
var crafted = new DFBuilder()
.setVer(0)
.set("useExponentialNotation", true)
.build();
var bytes = ser(crafted);
var df = assertDoesNotThrow(() -> deSer(bytes));
// Ensure we do not observe exponential notation form
assertFalse(df.format(0).contains("E"));
}
// Version 1 did not support the affix pattern Strings. Ensure when they
// are read in from the stream they are not defaulted and remain null.
@Test
void version1Test() {
var crafted = new DFBuilder()
.setVer(1)
.set("posPrefixPattern", null)
.set("posSuffixPattern", null)
.set("negPrefixPattern", null)
.set("negSuffixPattern", null)
.build();
var bytes = ser(crafted);
var df = assertDoesNotThrow(() -> deSer(bytes));
assertNull(readField(df, "posPrefixPattern"));
assertNull(readField(df, "posSuffixPattern"));
assertNull(readField(df, "negPrefixPattern"));
assertNull(readField(df, "negSuffixPattern"));
}
// Version 2 did not support the min/max int and frac digits.
// Ensure the proper defaults are set.
@Test
void version2Test() {
var crafted = new DFBuilder()
.setVer(2)
.set("maximumIntegerDigits", -1)
.set("maximumFractionDigits", -1)
.set("minimumIntegerDigits", -1)
.set("minimumFractionDigits", -1)
.build();
var bytes = ser(crafted);
var df = assertDoesNotThrow(() -> deSer(bytes));
assertEquals(1, df.getMinimumIntegerDigits());
assertEquals(3, df.getMaximumFractionDigits());
assertEquals(309, df.getMaximumIntegerDigits());
assertEquals(0, df.getMinimumFractionDigits());
}
// Version 3 did not support rounding mode. Should default to HALF_EVEN
@Test
void version3Test() {
var crafted = new DFBuilder()
.setVer(3)
.set("roundingMode", RoundingMode.UNNECESSARY)
.build();
var bytes = ser(crafted);
var df = assertDoesNotThrow(() -> deSer(bytes));
assertEquals(RoundingMode.HALF_EVEN, df.getRoundingMode());
}
}
// Some invariant checking in DF relies on checking NF fields.
// Either via NF.readObject() or through super calls in DF.readObject
@Nested // For all these nested tests, see 4185761
class NumberFormatTests {
// Ensure the max integer value invariant is not exceeded
@Test
void integerTest() {
var crafted = new DFBuilder()
.setSuper("maximumIntegerDigits", 786)
.setSuper("minimumIntegerDigits", 785)
.build();
var bytes = ser(crafted);
assertEquals("Digit count out of range",
assertThrows(InvalidObjectException.class, () -> deSer(bytes)).getMessage());
}
// Ensure the max fraction value invariant is not exceeded
@Test
void fractionTest() {
var crafted = new DFBuilder()
.setSuper("maximumFractionDigits", 788)
.setSuper("minimumFractionDigits", 787)
.build();
var bytes = ser(crafted);
assertEquals("Digit count out of range",
assertThrows(InvalidObjectException.class, () -> deSer(bytes)).getMessage());
}
// Ensure the minimum integer digits cannot be greater than the max
@Test
void maxMinIntegerTest() {
var crafted = new DFBuilder()
.setSuper("maximumIntegerDigits", 5)
.setSuper("minimumIntegerDigits", 6)
.build();
var bytes = ser(crafted);
assertEquals("Digit count range invalid",
assertThrows(InvalidObjectException.class, () -> deSer(bytes)).getMessage());
}
// Ensure the minimum fraction digits cannot be greater than the max
@Test
void maxMinFractionTest() {
var crafted = new DFBuilder()
.setSuper("maximumFractionDigits", 5)
.setSuper("minimumFractionDigits", 6)
.build();
var bytes = ser(crafted);
assertEquals("Digit count range invalid",
assertThrows(InvalidObjectException.class, () -> deSer(bytes)).getMessage());
}
}
// Ensure the serial version is updated to the current after de-serialization.
@Test
void versionTest() {
var bytes = ser(new DFBuilder().setVer(-25).build());
var df = assertDoesNotThrow(() -> deSer(bytes));
assertEquals(4, readField(df, "serialVersionOnStream"));
}
// Ensure strictness value is read properly when it is set.
@Test
void strictnessTest() {
var crafted = new DecimalFormat();
crafted.setStrict(true);
var bytes = ser(crafted);
var df = assertDoesNotThrow(() -> deSer(bytes));
assertTrue(df.isStrict());
}
// Ensure invalid grouping sizes are corrected to the default invariant.
@Test
void groupingSizeTest() {
var crafted = new DFBuilder()
.set("groupingSize", (byte) -5)
.build();
var bytes = ser(crafted);
var df = assertDoesNotThrow(() -> deSer(bytes));
assertEquals(3, df.getGroupingSize());
}
// Ensure a de-serialized dFmt does not throw NPE from missing digitList
// later when formatting. i.e. re-construct the transient digitList field
@Test // See 4069754, 4067878
void digitListTest() {
var crafted = new DecimalFormat();
var bytes = ser(crafted);
var df = assertDoesNotThrow(() -> deSer(bytes));
assertDoesNotThrow(() -> df.format(1));
assertNotNull(readField(df, "digitList"));
}
// Similar to the previous test, but the original regression test
// which was a failure in DateFormat due to DecimalFormat NPE
@Test // See 4069754 and 4067878
void digitListDateFormatTest() {
var fmt = new FooFormat();
fmt.now();
var bytes = ser(fmt);
var ff = (FooFormat) assertDoesNotThrow(() -> deSer0(bytes));
assertDoesNotThrow(ff::now);
}
static class FooFormat implements Serializable {
DateFormat dateFormat = DateFormat.getDateInstance();
public String now() {
GregorianCalendar calendar = new GregorianCalendar();
Date t = calendar.getTime();
return dateFormat.format(t);
}
}
// Utilities ----
// Utility to serialize
private static byte[] ser(Object obj) {
return assertDoesNotThrow(() -> {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream)) {
oos.writeObject(obj);
return byteArrayOutputStream.toByteArray();
}
}, "Unexpected error during serialization");
}
// Utility to deserialize
private static Object deSer0(byte[] bytes) throws IOException, ClassNotFoundException {
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream)) {
return ois.readObject();
}
}
// Convenience cast to DF
private static DecimalFormat deSer(byte[] bytes) throws IOException, ClassNotFoundException {
return (DecimalFormat) deSer0(bytes);
}
// Utility to deserialize from file in hex format
private static Object deSer(String file) throws IOException, ClassNotFoundException {
try (InputStream stream = HexDumpReader.getStreamFromHexDump(file);
ObjectInputStream ois = new ObjectInputStream(stream)) {
return ois.readObject();
}
}
// Utility to read a private field
private static Object readField(DecimalFormat df, String name) {
return assertDoesNotThrow(() -> {
var field = DecimalFormat.class.getDeclaredField(name);
field.setAccessible(true);
return field.get(df);
}, "Unexpected error during field reading");
}
// Utility class to build instances of DF via reflection
private static class DFBuilder {
private final DecimalFormat df;
private DFBuilder() {
df = new DecimalFormat();
}
private DFBuilder setVer(Object value) {
return set("serialVersionOnStream", value);
}
private DFBuilder setSuper(String field, Object value) {
return set(df.getClass().getSuperclass(), field, value);
}
private DFBuilder set(String field, Object value) {
return set(df.getClass(), field, value);
}
private DFBuilder set(Class<?> clzz, String field, Object value) {
return assertDoesNotThrow(() -> {
Field f = clzz.getDeclaredField(field);
f.setAccessible(true);
f.set(df, value);
return this;
}, "Unexpected error during reflection setting");
}
private DecimalFormat build() {
return df;
}
}
}
// Not nested, so that it can be recognized and cast correctly for the 1.1.4 test
class CheckDecimalFormat implements Serializable {
DecimalFormat _decFormat = (DecimalFormat) NumberFormat.getInstance();
public String Update() {
Random r = new Random();
return _decFormat.format(r.nextDouble());
}
}
@@ -1,56 +0,0 @@
/*
* Copyright (c) 2005, 2016, 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.
*/
/*
* No at-test for this test, because it needs to be run on older version JDK than 1.6 to test.
* It was tested using 1.4.2. The file object was created using JDK1.6.
*/
import java.awt.*;
import java.text.*;
import java.util.*;
import java.io.*;
public class DFSDeserialization142{
public static void main(String[] args)
{
try {
File file = new File("DecimalFormatSymbols.current");
FileInputStream istream = new FileInputStream(file);
ObjectInputStream p = new ObjectInputStream(istream);
DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject();
if (dfs.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){
System.out.println("Serialization/Deserialization Test Passed.");
}else{
throw new Exception("Serialization/Deserialization Test Failed:"+dfs.getCurrencySymbol());
}
istream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,162 +0,0 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 4068067
* @library /java/text/testlib
* @build DFSSerialization HexDumpReader
* @run junit DFSSerialization
* @summary Three different tests are done.
* 1. read from the object created using jdk1.4.2
* 2. create a valid DecimalFormatSymbols object with current JDK, then read the object
* 3. Try to create an valid DecimalFormatSymbols object by passing null to set null
* for the exponent separator symbol. Expect the NullPointerException.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.fail;
public class DFSSerialization{
@Test
public void TestDFSSerialization(){
/*
* 1. read from the object created using jdk1.4.2
*/
File oldFile = new File(System.getProperty("test.src", "."), "DecimalFormatSymbols.142.txt");
DecimalFormatSymbols dfs142 = readTestObject(oldFile);
if (dfs142 != null){
if (dfs142.getExponentSeparator().equals("E") && dfs142.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){
System.out.println("\n Deserialization of JDK1.4.2 Object from the current JDK: Passed.");
System.out.println(" Deserialization of JDK1.4.2 Object from the current JDK: Passed.");
} else {
fail(" Deserialization of JDK1.4.2 Object from the current JDK was Failed:"
+dfs142.getCurrencySymbol()+" "+dfs142.getExponentSeparator());
/*
* logically should not throw this exception as errln throws exception
* if not thrown yet - but in case errln got changed
*/
throw new RuntimeException(" Deserialization of JDK1.4.2 Object from the current JDK was Failed:"
+dfs142.getCurrencySymbol()+" "+dfs142.getExponentSeparator());
}
}
/*
* 2. create a valid DecimalFormatSymbols object with current JDK, then read the object
*/
String validObject = "DecimalFormatSymbols.current";
File currentFile = createTestObject(validObject, "*SpecialExponentSeparator*");
DecimalFormatSymbols dfsValid = readTestObject(currentFile);
if (dfsValid != null){
if (dfsValid.getExponentSeparator().equals("*SpecialExponentSeparator*") &&
dfsValid.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){
System.out.println(" Deserialization of current JDK Object from the current JDK: Passed.");
System.out.println(" Deserialization of current JDK Object from the current JDK: Passed.");
} else {
fail(" Deserialization of current JDK Object from the current JDK was Failed:"
+dfsValid.getCurrencySymbol()+" "+dfsValid.getExponentSeparator());
/*
* logically should not throw this exception as errln throws exception
* if not thrown yet - but in case errln got changed
*/
throw new RuntimeException(" Deserialization of current Object from the current JDK was Failed:"
+dfsValid.getCurrencySymbol()+" "+dfsValid.getExponentSeparator());
}
}
/*
* 3. Try to create an valid DecimalFormatSymbols object by passing null
* to set null for the exponent separator symbol. Expect the NullPointerException.
*/
DecimalFormatSymbols symNPE = new DecimalFormatSymbols(Locale.US);
boolean npePassed = false;
try {
symNPE.setExponentSeparator(null);
} catch (NullPointerException npe){
npePassed = true;
System.out.println(" Trying to set exponent separator with null: Passed.");
System.out.println(" Trying to set exponent separator with null: Passed.");
}
if (!npePassed){
System.out.println(" Trying to set exponent separator with null:Failed.");
fail(" Trying to set exponent separator with null:Failed.");
/*
* logically should not throw this exception as errln throws exception
* if not thrown yet - but in case errln got changed
*/
throw new RuntimeException(" Trying to set exponent separator with null:Failed.");
}
}
private DecimalFormatSymbols readTestObject(File inputFile){
try (InputStream istream = inputFile.getName().endsWith(".txt") ?
HexDumpReader.getStreamFromHexDump(inputFile) :
new FileInputStream(inputFile)) {
ObjectInputStream p = new ObjectInputStream(istream);
DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject();
return dfs;
} catch (Exception e) {
fail("Test Malfunction in DFSSerialization: Exception while reading the object");
/*
* logically should not throw this exception as errln throws exception
* if not thrown yet - but in case errln got changed
*/
throw new RuntimeException("Test Malfunction: re-throwing the exception", e);
}
}
private File createTestObject(String objectName, String expString){
DecimalFormatSymbols dfs= new DecimalFormatSymbols();
dfs.setExponentSeparator(expString);
dfs.setCurrencySymbol("*SpecialCurrencySymbol*");
System.out.println(" The special exponent separator is set : " + dfs.getExponentSeparator());
System.out.println(" The special currency symbol is set : " + dfs.getCurrencySymbol());
// 6345659: create a test object in the test.class dir where test user has a write permission.
File file = new File(System.getProperty("test.class", "."), objectName);
try (FileOutputStream ostream = new FileOutputStream(file)) {
ObjectOutputStream p = new ObjectOutputStream(ostream);
p.writeObject(dfs);
//System.out.println(" The special currency symbol is set : " + dfs.getCurrencySymbol());
return file;
} catch (Exception e){
fail("Test Malfunction in DFSSerialization: Exception while creating an object");
/*
* logically should not throw this exception as errln throws exception
* if not thrown yet - but in case errln got changed
*/
throw new RuntimeException("Test Malfunction: re-throwing the exception", e);
}
}
}
@@ -1,54 +0,0 @@
/*
* Copyright (c) 2005, 2016, 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.
*/
/*
* No at-test for this test, because it needs to be run on JDK 1.4.2
* Instead, the resulting serialized file
* DecimalFormatSymbols.142 is archived.
*/
import java.awt.*;
import java.text.*;
import java.util.*;
import java.io.*;
public class DFSSerialization142 {
public static void main(String[] args)
{
try {
DecimalFormatSymbols dfs= new DecimalFormatSymbols();
System.out.println("Default currency symbol in the default locale : " + dfs.getCurrencySymbol());
dfs.setCurrencySymbol("*SpecialCurrencySymbol*");
System.out.println("The special currency symbol is set : " + dfs.getCurrencySymbol());
FileOutputStream ostream = new FileOutputStream("DecimalFormatSymbols.142");
ObjectOutputStream p = new ObjectOutputStream(ostream);
p.writeObject(dfs);
ostream.close();
System.out.println("DecimalFormatSymbols saved ok.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,9 +28,8 @@
* 4087251 4087535 4088161 4088503 4090489 4090504 4092480 4092561 4095713
* 4098741 4099404 4101481 4106658 4106662 4106664 4108738 4110936 4122840
* 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198
* 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742
* 4217661 4243011 4243108 4330377 4233840 4241880 4833877 8008577 8227313
* 8174269
* 4162852 4167494 4170798 4176114 4179818 4212072 4212073 4216742 4217661
* 4243011 4243108 4330377 4233840 4241880 4833877 8008577 8227313 8174269
* @summary Regression tests for NumberFormat and associated classes
* @library /java/text/testlib
* @build HexDumpReader TestUtils
@@ -307,33 +306,6 @@ public class NumberRegression {
Locale.setDefault(savedLocale);
}
/* bugs 4069754, 4067878
* null pointer thrown when accessing a deserialized DecimalFormat
* object.
*/
@Test
public void Test4069754()
{
try {
myformat it = new myformat();
System.out.println(it.Now());
FileOutputStream ostream = new FileOutputStream("t.tmp");
ObjectOutputStream p = new ObjectOutputStream(ostream);
p.writeObject(it);
ostream.close();
System.out.println("Saved ok.");
FileInputStream istream = new FileInputStream("t.tmp");
ObjectInputStream p2 = new ObjectInputStream(istream);
myformat it2 = (myformat)p2.readObject();
System.out.println(it2.Now());
istream.close();
System.out.println("Loaded ok.");
} catch (Exception foo) {
fail("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
}
}
/**
* DecimalFormat.applyPattern(String) allows illegal patterns
*/
@@ -1485,59 +1457,6 @@ public class NumberRegression {
}
}
@Test
public void Test4185761() throws IOException, ClassNotFoundException {
/* Code used to write out the initial files, which are
* then edited manually:
NumberFormat nf = NumberFormat.getInstance(Locale.US);
nf.setMinimumIntegerDigits(0x111); // Keep under 309
nf.setMaximumIntegerDigits(0x112); // Keep under 309
nf.setMinimumFractionDigits(0x113); // Keep under 340
nf.setMaximumFractionDigits(0x114); // Keep under 340
FileOutputStream ostream =
new FileOutputStream("NumberFormat4185761");
ObjectOutputStream p = new ObjectOutputStream(ostream);
p.writeObject(nf);
ostream.close();
*/
// File minint maxint minfrac maxfrac
// NumberFormat4185761a 0x122 0x121 0x124 0x123
// NumberFormat4185761b 0x311 0x312 0x313 0x314
// File a is bad because the mins are smaller than the maxes.
// File b is bad because the values are too big for a DecimalFormat.
// These files have a sufix ".ser.txt".
InputStream istream = HexDumpReader.getStreamFromHexDump("NumberFormat4185761a.ser.txt");
ObjectInputStream p = new ObjectInputStream(istream);
try {
NumberFormat nf = (NumberFormat) p.readObject();
fail("FAIL: Deserialized bogus NumberFormat int:" +
nf.getMinimumIntegerDigits() + ".." +
nf.getMaximumIntegerDigits() + " frac:" +
nf.getMinimumFractionDigits() + ".." +
nf.getMaximumFractionDigits());
} catch (InvalidObjectException e) {
System.out.println("Ok: " + e.getMessage());
}
istream.close();
istream = HexDumpReader.getStreamFromHexDump("NumberFormat4185761b.ser.txt");
p = new ObjectInputStream(istream);
try {
NumberFormat nf = (NumberFormat) p.readObject();
fail("FAIL: Deserialized bogus DecimalFormat int:" +
nf.getMinimumIntegerDigits() + ".." +
nf.getMaximumIntegerDigits() + " frac:" +
nf.getMinimumFractionDigits() + ".." +
nf.getMaximumFractionDigits());
} catch (InvalidObjectException e) {
System.out.println("Ok: " + e.getMessage());
}
istream.close();
}
/**
* Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
* This includes the minus sign, currency symbol, international currency
@@ -1930,20 +1849,6 @@ public class NumberRegression {
}
}
@SuppressWarnings("serial")
class myformat implements Serializable
{
DateFormat _dateFormat = DateFormat.getDateInstance();
public String Now()
{
GregorianCalendar calendar = new GregorianCalendar();
Date t = calendar.getTime();
String nowStr = _dateFormat.format(t);
return nowStr;
}
}
@SuppressWarnings("serial")
class MyNumberFormatTest extends NumberFormat {
public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
@@ -1,89 +0,0 @@
/*
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 4101150
* @library /java/text/testlib
* @build SerializationLoadTest HexDumpReader
* @run main SerializationLoadTest
* @summary test serialization compatibility of DecimalFormat and DecimalFormatSymbols
* @key randomness
*/
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Random;
public class SerializationLoadTest {
public static void main(String[] args)
{
try {
InputStream istream1 = HexDumpReader.getStreamFromHexDump("DecimalFormat.114.txt");
ObjectInputStream p = new ObjectInputStream(istream1);
CheckDecimalFormat it = (CheckDecimalFormat)p.readObject();
System.out.println("1.1.4 DecimalFormat Loaded ok.");
System.out.println(it.Update());
System.out.println("Called Update successfully.");
istream1.close();
InputStream istream2 = HexDumpReader.getStreamFromHexDump("DecimalFormatSymbols.114.txt");
ObjectInputStream p2 = new ObjectInputStream(istream2);
CheckDecimalFormatSymbols it2 = (CheckDecimalFormatSymbols)p2.readObject();
System.out.println("1.1.4 DecimalFormatSymbols Loaded ok.");
System.out.println("getDigit : " + it2.Update());
System.out.println("Called Update successfully.");
istream2.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("serial")
class CheckDecimalFormat implements Serializable
{
DecimalFormat _decFormat = (DecimalFormat)NumberFormat.getInstance();
public String Update()
{
Random r = new Random();
return _decFormat.format(r.nextDouble());
}
}
@SuppressWarnings("serial")
class CheckDecimalFormatSymbols implements Serializable
{
DecimalFormatSymbols _decFormatSymbols = new DecimalFormatSymbols();
public char Update()
{
return _decFormatSymbols.getDigit();
}
}
@@ -1,81 +0,0 @@
/*
* Copyright (c) 1998, 2016, 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.
*/
/*
* No at-test for this test, because it needs to be run on JDK 1.1.4.
* Instead, the resulting serialized files DecimalFormat.114 and
* DecimalFormatSymbols.114 are archived.
*/
import java.awt.*;
import java.text.*;
import java.util.*;
import java.io.*;
public class SerializationSaveTest {
public static void main(String[] args)
{
try {
CheckDecimalFormat it = new CheckDecimalFormat();
System.out.println(it.Update());
FileOutputStream ostream = new FileOutputStream("DecimalFormat.114");
ObjectOutputStream p = new ObjectOutputStream(ostream);
p.writeObject(it);
ostream.close();
System.out.println("DecimalFormat saved ok.");
CheckDecimalFormatSymbols it2 = new CheckDecimalFormatSymbols();
System.out.println("getDigit : " + it2.Update());
FileOutputStream ostream2 = new FileOutputStream("DecimalFormatSymbols.114");
ObjectOutputStream p2 = new ObjectOutputStream(ostream2);
p2.writeObject(it2);
ostream2.close();
System.out.println("DecimalFormatSymbols saved ok.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("serial")
class CheckDecimalFormat implements Serializable
{
DecimalFormat _decFormat = (DecimalFormat)NumberFormat.getInstance();
public String Update()
{
Random r = new Random();
return _decFormat.format(r.nextDouble());
}
}
@SuppressWarnings("serial")
class CheckDecimalFormatSymbols implements Serializable
{
DecimalFormatSymbols _decFormatSymbols = new DecimalFormatSymbols();
public char Update()
{
return _decFormatSymbols.getDigit();
}
}
@@ -39,20 +39,15 @@ import jdk.test.lib.jfr.EventNames;
* @run main/timeout=480 jdk.jfr.event.profiling.TestCPUTimeSampleMultipleRecordings
*/
public class TestCPUTimeSampleMultipleRecordings {
static String nativeEvent = EventNames.CPUTimeSample;
static volatile boolean alive = true;
public static void main(String[] args) throws Exception {
Thread t = new Thread(TestCPUTimeSampleMultipleRecordings::nativeMethod);
t.setDaemon(true);
t.start();
for (int i = 0; i < 2; i++) {
try (RecordingStream rs = new RecordingStream()) {
rs.enable(nativeEvent).with("throttle", "1ms");
rs.onEvent(nativeEvent, e -> {
alive = false;
rs.enable(EventNames.CPUTimeSample).with("throttle", "1ms");
rs.onEvent(EventNames.CPUTimeSample, e -> {
rs.close();
});
@@ -60,6 +55,7 @@ public class TestCPUTimeSampleMultipleRecordings {
}
}
alive = false;
t.join();
}
public static void nativeMethod() {
@@ -0,0 +1,154 @@
/*
* Copyright (c) 2025 SAP SE. 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 jdk.jfr.event.profiling;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.stream.Collectors;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import jdk.jfr.Recording;
import jdk.jfr.consumer.RecordingStream;
import jdk.jfr.consumer.RecordedEvent;
import jdk.jfr.internal.JVM;
import jdk.test.lib.Asserts;
import jdk.test.lib.jfr.EventNames;
import jdk.test.whitebox.WhiteBox;
/*
* Tests the sample queues increase in size as needed, when loss is recorded.
* @test
* @requires vm.hasJFR & os.family == "linux" & vm.debug
* @library /test/lib
* @modules jdk.jfr/jdk.jfr.internal
* @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
* -Xbatch -XX:StartFlightRecording:dumponexit=true jdk.jfr.event.profiling.TestCPUTimeSampleQueueAutoSizes
*/
public class TestCPUTimeSampleQueueAutoSizes {
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
private static final String BURST_THREAD_NAME = "Burst-Thread-1";
static volatile boolean alive = true;
record LossEvent(long relativeTimeMillis, long lostSamples) {}
/** A data collection from the CPUTimeSampleLost events for the burst thread */
static class LossEventCollection {
private final List<LossEvent> events = new ArrayList<>();
public synchronized void addEvent(LossEvent event) {
events.add(event);
}
public synchronized List<LossEvent> getSortedEvents() {
return events.stream()
.sorted(Comparator.comparingLong(e -> e.relativeTimeMillis))
.collect(Collectors.toList());
}
public List<LossEvent> getEventsPerInterval(long widthMillis, long stopTimeMillis) {
List<LossEvent> ret = new ArrayList<>();
for (long start = 0; start < stopTimeMillis; start += widthMillis) {
long actualStart = Math.min(start, stopTimeMillis - widthMillis);
long lostSamples = events.stream()
.filter(e -> e.relativeTimeMillis >= actualStart && e.relativeTimeMillis < actualStart + widthMillis)
.mapToLong(e -> e.lostSamples)
.sum();
ret.add(new LossEvent(actualStart, lostSamples));
}
return ret;
}
}
public static void main(String[] args) throws Exception {
try (RecordingStream rs = new RecordingStream()) {
// setup recording
AtomicLong firstSampleTimeMillis = new AtomicLong(0);
AtomicLong lastSampleTimeMillis = new AtomicLong(0);
LossEventCollection lossEvents = new LossEventCollection();
rs.enable(EventNames.CPUTimeSample).with("throttle", "1ms");
rs.onEvent(EventNames.CPUTimeSample, e -> {
if (firstSampleTimeMillis.get() == 0 && e.getThread("eventThread").getJavaName().equals(BURST_THREAD_NAME)) {
firstSampleTimeMillis.set(e.getStartTime().toEpochMilli());
}
if (e.getThread("eventThread").getJavaName().equals(BURST_THREAD_NAME)) {
lastSampleTimeMillis.set(e.getStartTime().toEpochMilli());
}
});
rs.enable(EventNames.CPUTimeSamplesLost);
rs.onEvent(EventNames.CPUTimeSamplesLost, e -> {
if (e.getThread("eventThread").getJavaName().equals(BURST_THREAD_NAME)) {
long eventTime = e.getStartTime().toEpochMilli();
long relativeTime = firstSampleTimeMillis.get() > 0 ? (eventTime - firstSampleTimeMillis.get()) : eventTime;
System.out.println("Lost samples: " + e.getLong("lostSamples") + " at " + relativeTime);
lossEvents.addEvent(new LossEvent(relativeTime, e.getLong("lostSamples")));
}
});
WHITE_BOX.cpuSamplerSetOutOfStackWalking(false);
rs.startAsync();
// this thread runs all along
Thread burstThread = new Thread(() -> WHITE_BOX.busyWait(11000));
burstThread.setName(BURST_THREAD_NAME);
burstThread.start();
// now we toggle out-of-stack-walking off, wait 1 second and then turn it on for 500ms a few times
for (int i = 0; i < 5; i++) {
boolean supported = WHITE_BOX.cpuSamplerSetOutOfStackWalking(false);
if (!supported) {
System.out.println("Out-of-stack-walking not supported, skipping test");
Asserts.assertFalse(true);
return;
}
Thread.sleep(700);
long iterations = WHITE_BOX.cpuSamplerOutOfStackWalkingIterations();
WHITE_BOX.cpuSamplerSetOutOfStackWalking(true);
Thread.sleep(300);
while (WHITE_BOX.cpuSamplerOutOfStackWalkingIterations() == iterations) {
Thread.sleep(50); // just to make sure the stack walking really ran
}
}
rs.close();
checkThatLossDecreased(lossEvents, lastSampleTimeMillis.get() - firstSampleTimeMillis.get());
}
}
static void checkThatLossDecreased(LossEventCollection lossEvents, long lastSampleTimeMillis) {
List<LossEvent> intervalLosses = lossEvents.getEventsPerInterval(1000, lastSampleTimeMillis);
for (LossEvent interval : intervalLosses) {
System.out.println("Lost samples in interval " + interval.relativeTimeMillis + ": " + interval.lostSamples);
}
// check that there are at least 3 intervals
Asserts.assertTrue(intervalLosses.size() > 2);
// check that the second to last interval has far fewer lost samples than the first
Asserts.assertTrue(intervalLosses.get(intervalLosses.size() - 2).lostSamples <
intervalLosses.get(0).lostSamples / 2);
}
}
+7
View File
@@ -841,6 +841,13 @@ public class WhiteBox {
public native void waitUnsafe(int time_ms);
public native void busyWait(int cpuTimeMs);
// returns true if supported, false if not
public native boolean cpuSamplerSetOutOfStackWalking(boolean enable);
public native long cpuSamplerOutOfStackWalkingIterations();
public native void pinObject(Object o);
public native void unpinObject(Object o);
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2023, Arm Limited. All rights reserved.
* Copyright (c) 2025, NVIDIA CORPORATION & 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
@@ -28,7 +29,9 @@ import org.openjdk.jmh.annotations.*;
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
@Fork(jvmArgs = {"--add-modules=jdk.incubator.vector"})
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 1, jvmArgs = {"--add-modules=jdk.incubator.vector"})
public class VectorExtractBenchmark {
private int idx = 0;
private boolean[] res = new boolean[8];