Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3747153d91 | |||
| 789ead61bb | |||
| ab772dd2cc | |||
| 6c751f29e4 | |||
| 668808f8a3 | |||
| ec0d44cf30 | |||
| 9776e4dd74 | |||
| 5861aa7803 | |||
| a8b394bdea | |||
| 5ade8576ab | |||
| 076de11535 | |||
| 00318ca3eb | |||
| 17c9b9f9bf | |||
| 1fa7ec84db | |||
| 40a6020568 | |||
| 503ba0a93f | |||
| 147c08cc3a | |||
| 74c0684839 | |||
| 3f9c665586 | |||
| e90d54198d | |||
| 1482b6a0db | |||
| 3c07c11d16 | |||
| c2d79609d8 | |||
| 00be643fa3 | |||
| cefd94515e | |||
| 147ed00b20 | |||
| 304f253df0 | |||
| 81493188d6 | |||
| 4bc1dc3260 | |||
| c357a2f7db | |||
| d930cc5895 | |||
| 8b686d9ee4 | |||
| 1a69c6b56a | |||
| 9f2d753643 | |||
| d9981960c5 | |||
| d8b2de8154 | |||
| 9373d2786c | |||
| a66fe2a876 | |||
| 9a0e2ef7f0 | |||
| fbfcb14383 | |||
| 76798c4739 | |||
| b2484b5e2d | |||
| c1c5c95496 | |||
| b3bd1ec2f7 | |||
| 43d9fcc879 | |||
| f542b8f0cc | |||
| f80b3a08d7 | |||
| 211e9435d2 | |||
| 2a46b6b439 | |||
| 27c9af8e2f | |||
| d241152fb1 | |||
| 07fb86296c | |||
| 2ec608f487 | |||
| 569b97fa16 | |||
| 156fdbe911 | |||
| 520ded534d | |||
| 1173f8ee7c | |||
| 96698162e6 | |||
| 4ad231aa5d |
@@ -64,33 +64,33 @@ jobs:
|
||||
gnu-arch: aarch64
|
||||
debian-arch: arm64
|
||||
debian-repository: https://httpredir.debian.org/debian/
|
||||
debian-version: bookworm
|
||||
debian-version: trixie
|
||||
tolerate-sysroot-errors: false
|
||||
- target-cpu: arm
|
||||
gnu-arch: arm
|
||||
debian-arch: armhf
|
||||
debian-repository: https://httpredir.debian.org/debian/
|
||||
debian-version: bookworm
|
||||
debian-version: trixie
|
||||
tolerate-sysroot-errors: false
|
||||
gnu-abi: eabihf
|
||||
- target-cpu: s390x
|
||||
gnu-arch: s390x
|
||||
debian-arch: s390x
|
||||
debian-repository: https://httpredir.debian.org/debian/
|
||||
debian-version: bookworm
|
||||
debian-version: trixie
|
||||
tolerate-sysroot-errors: false
|
||||
- target-cpu: ppc64le
|
||||
gnu-arch: powerpc64le
|
||||
debian-arch: ppc64el
|
||||
debian-repository: https://httpredir.debian.org/debian/
|
||||
debian-version: bookworm
|
||||
debian-version: trixie
|
||||
tolerate-sysroot-errors: false
|
||||
- target-cpu: riscv64
|
||||
gnu-arch: riscv64
|
||||
debian-arch: riscv64
|
||||
debian-repository: https://httpredir.debian.org/debian/
|
||||
debian-version: sid
|
||||
tolerate-sysroot-errors: true
|
||||
debian-version: trixie
|
||||
tolerate-sysroot-errors: false
|
||||
|
||||
steps:
|
||||
- name: 'Checkout the JDK source'
|
||||
|
||||
@@ -221,6 +221,9 @@ JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER
|
||||
# LeakSanitizer
|
||||
JDKOPT_SETUP_LEAK_SANITIZER
|
||||
|
||||
# Setup static analyzer
|
||||
JDKOPT_SETUP_STATIC_ANALYZER
|
||||
|
||||
# Fallback linker
|
||||
# This needs to go before 'LIB_DETERMINE_DEPENDENCIES'
|
||||
JDKOPT_SETUP_FALLBACK_LINKER
|
||||
|
||||
@@ -940,7 +940,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
|
||||
# ACLE and this flag are required to build the aarch64 SVE related functions in
|
||||
# libvectormath. Apple Silicon does not support SVE; use macOS as a proxy for
|
||||
# that check.
|
||||
if test "x$OPENJDK_TARGET_CPU" = "xaarch64" && test "x$OPENJDK_TARGET_CPU" = "xlinux"; then
|
||||
if test "x$OPENJDK_TARGET_CPU" = "xaarch64" && test "x$OPENJDK_TARGET_OS" = "xlinux"; then
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
AC_LANG_PUSH(C)
|
||||
OLD_CFLAGS="$CFLAGS"
|
||||
@@ -954,6 +954,17 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
$2SVE_CFLAGS="-march=armv8-a+sve"
|
||||
# Switching the initialization mode with gcc from 'pattern' to 'zero'
|
||||
# avoids the use of unsupported `__builtin_clear_padding` for variable
|
||||
# length aggregates
|
||||
if test "x$DEBUG_LEVEL" != xrelease && test "x$TOOLCHAIN_TYPE" = xgcc ; then
|
||||
INIT_ZERO_FLAG="-ftrivial-auto-var-init=zero"
|
||||
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$INIT_ZERO_FLAG],
|
||||
IF_TRUE: [
|
||||
$2SVE_CFLAGS="${$2SVE_CFLAGS} $INIT_ZERO_FLAG"
|
||||
]
|
||||
)
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([no])
|
||||
|
||||
@@ -479,6 +479,31 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_ADDRESS_SANITIZER],
|
||||
AC_SUBST(ASAN_ENABLED)
|
||||
])
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Static analyzer
|
||||
#
|
||||
AC_DEFUN_ONCE([JDKOPT_SETUP_STATIC_ANALYZER],
|
||||
[
|
||||
UTIL_ARG_ENABLE(NAME: static-analyzer, DEFAULT: false, RESULT: STATIC_ANALYZER_ENABLED,
|
||||
DESC: [enable the GCC static analyzer],
|
||||
CHECK_AVAILABLE: [
|
||||
AC_MSG_CHECKING([if static analyzer is available])
|
||||
if test "x$TOOLCHAIN_TYPE" = "xgcc"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AVAILABLE=false
|
||||
fi
|
||||
],
|
||||
IF_ENABLED: [
|
||||
STATIC_ANALYZER_CFLAGS="-fanalyzer -Wno-analyzer-fd-leak"
|
||||
CFLAGS_JDKLIB="$CFLAGS_JDKLIB $STATIC_ANALYZER_CFLAGS"
|
||||
CFLAGS_JDKEXE="$CFLAGS_JDKEXE $STATIC_ANALYZER_CFLAGS"
|
||||
])
|
||||
AC_SUBST(STATIC_ANALYZER_ENABLED)
|
||||
])
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# LeakSanitizer
|
||||
|
||||
@@ -100,7 +100,7 @@ int AbstractInterpreter::size_activation(int max_stack,
|
||||
// It is also guaranteed to be walkable even though it is in a skeletal state
|
||||
//
|
||||
// is_top_frame == true:
|
||||
// We're processing the *oldest* interpreter frame!
|
||||
// We're processing the *youngest* interpreter frame on top of stack!
|
||||
//
|
||||
// pop_frame_extra_args:
|
||||
// If this is != 0 we are returning to a deoptimized frame by popping
|
||||
@@ -131,8 +131,9 @@ void AbstractInterpreter::layout_activation(Method* method,
|
||||
#ifdef ASSERT
|
||||
if (caller->is_interpreted_frame()) {
|
||||
assert(locals_base <= caller->interpreter_frame_expression_stack(), "bad placement");
|
||||
const int caller_abi_bytesize = (is_bottom_frame ? frame::top_ijava_frame_abi_size : frame::parent_ijava_frame_abi_size);
|
||||
intptr_t* l2 = caller->sp() + method->max_locals() - 1 + (caller_abi_bytesize / Interpreter::stackElementSize);
|
||||
// If the bottom frame's caller was thawed then it has frame::java_abi (aka parent_ijava_frame_abi).
|
||||
// With an ordinary i2c call it would keep the larger frame::top_ijava_frame_abi
|
||||
intptr_t* l2 = caller->sp() + method->max_locals() - 1 + (frame::parent_ijava_frame_abi_size / Interpreter::stackElementSize);
|
||||
assert(locals_base >= l2, "bad placement");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -912,6 +912,32 @@ protected:
|
||||
emit(insn);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static uint32_t encode_jal(Register Rd, const int32_t offset) {
|
||||
guarantee(is_simm21(offset) && ((offset % 2) == 0), "offset is invalid.");
|
||||
uint32_t insn = 0;
|
||||
patch((address)&insn, 6, 0, 0b1101111);
|
||||
patch_reg((address)&insn, 7, Rd);
|
||||
patch((address)&insn, 19, 12, (uint32_t)((offset >> 12) & 0xff));
|
||||
patch((address)&insn, 20, (uint32_t)((offset >> 11) & 0x1));
|
||||
patch((address)&insn, 30, 21, (uint32_t)((offset >> 1) & 0x3ff));
|
||||
patch((address)&insn, 31, (uint32_t)((offset >> 20) & 0x1));
|
||||
return insn;
|
||||
}
|
||||
|
||||
static uint32_t encode_jalr(Register Rd, Register Rs, const int32_t offset) {
|
||||
guarantee(is_simm12(offset), "offset is invalid.");
|
||||
uint32_t insn = 0;
|
||||
patch((address)&insn, 6, 0, 0b1100111);
|
||||
patch_reg((address)&insn, 7, Rd);
|
||||
patch((address)&insn, 14, 12, 0b000);
|
||||
patch_reg((address)&insn, 15, Rs);
|
||||
int32_t val = offset & 0xfff;
|
||||
patch((address)&insn, 31, 20, val);
|
||||
return insn;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
enum barrier {
|
||||
|
||||
@@ -3402,6 +3402,8 @@ void MacroAssembler::decode_klass_not_null(Register r, Register tmp) {
|
||||
|
||||
void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register tmp) {
|
||||
assert(UseCompressedClassPointers, "should only be used for compressed headers");
|
||||
assert_different_registers(dst, tmp);
|
||||
assert_different_registers(src, tmp);
|
||||
|
||||
if (CompressedKlassPointers::base() == nullptr) {
|
||||
if (CompressedKlassPointers::shift() != 0) {
|
||||
@@ -3412,18 +3414,13 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register
|
||||
return;
|
||||
}
|
||||
|
||||
Register xbase = dst;
|
||||
if (dst == src) {
|
||||
xbase = tmp;
|
||||
}
|
||||
Register xbase = tmp;
|
||||
|
||||
assert_different_registers(src, xbase);
|
||||
mv(xbase, (uintptr_t)CompressedKlassPointers::base());
|
||||
|
||||
if (CompressedKlassPointers::shift() != 0) {
|
||||
Register t = src == dst ? dst : t0;
|
||||
assert_different_registers(t, xbase);
|
||||
shadd(dst, src, xbase, t, CompressedKlassPointers::shift());
|
||||
// dst = (src << shift) + xbase
|
||||
shadd(dst, src, xbase, dst /* temporary, dst != xbase */, CompressedKlassPointers::shift());
|
||||
} else {
|
||||
add(dst, xbase, src);
|
||||
}
|
||||
@@ -5874,13 +5871,14 @@ void MacroAssembler::fill_words(Register base, Register cnt, Register value) {
|
||||
// in cnt.
|
||||
//
|
||||
// NOTE: This is intended to be used in the zero_blocks() stub. If
|
||||
// you want to use it elsewhere, note that cnt must be >= CacheLineSize.
|
||||
// you want to use it elsewhere, note that cnt must be >= zicboz_block_size.
|
||||
void MacroAssembler::zero_dcache_blocks(Register base, Register cnt, Register tmp1, Register tmp2) {
|
||||
int zicboz_block_size = VM_Version::zicboz_block_size.value();
|
||||
Label initial_table_end, loop;
|
||||
|
||||
// Align base with cache line size.
|
||||
neg(tmp1, base);
|
||||
andi(tmp1, tmp1, CacheLineSize - 1);
|
||||
andi(tmp1, tmp1, zicboz_block_size - 1);
|
||||
|
||||
// tmp1: the number of bytes to be filled to align the base with cache line size.
|
||||
add(base, base, tmp1);
|
||||
@@ -5890,16 +5888,16 @@ void MacroAssembler::zero_dcache_blocks(Register base, Register cnt, Register tm
|
||||
la(tmp1, initial_table_end);
|
||||
sub(tmp2, tmp1, tmp2);
|
||||
jr(tmp2);
|
||||
for (int i = -CacheLineSize + wordSize; i < 0; i += wordSize) {
|
||||
for (int i = -zicboz_block_size + wordSize; i < 0; i += wordSize) {
|
||||
sd(zr, Address(base, i));
|
||||
}
|
||||
bind(initial_table_end);
|
||||
|
||||
mv(tmp1, CacheLineSize / wordSize);
|
||||
mv(tmp1, zicboz_block_size / wordSize);
|
||||
bind(loop);
|
||||
cbo_zero(base);
|
||||
sub(cnt, cnt, tmp1);
|
||||
addi(base, base, CacheLineSize);
|
||||
addi(base, base, zicboz_block_size);
|
||||
bge(cnt, tmp1, loop);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
#ifdef COMPILER1
|
||||
#include "c1/c1_Runtime1.hpp"
|
||||
@@ -52,15 +53,15 @@ address NativeCall::destination() const {
|
||||
address addr = instruction_address();
|
||||
assert(NativeCall::is_at(addr), "unexpected code at call site");
|
||||
|
||||
address destination = MacroAssembler::target_addr_for_insn(addr);
|
||||
address stub_addr = MacroAssembler::target_addr_for_insn(addr);
|
||||
|
||||
CodeBlob* cb = CodeCache::find_blob(addr);
|
||||
assert(cb != nullptr && cb->is_nmethod(), "nmethod expected");
|
||||
nmethod *nm = (nmethod *)cb;
|
||||
assert(nm != nullptr, "Sanity");
|
||||
assert(nm->stub_contains(destination), "Sanity");
|
||||
assert(destination != nullptr, "Sanity");
|
||||
return stub_address_destination_at(destination);
|
||||
assert(nm->stub_contains(stub_addr), "Sanity");
|
||||
assert(stub_addr != nullptr, "Sanity");
|
||||
|
||||
return stub_address_destination_at(stub_addr);
|
||||
}
|
||||
|
||||
address NativeCall::reloc_destination() {
|
||||
@@ -89,6 +90,30 @@ void NativeCall::print() {
|
||||
tty->print_cr(PTR_FORMAT ": auipc,ld,jalr x1, offset/reg, ", p2i(instruction_address()));
|
||||
}
|
||||
|
||||
void NativeCall::optimize_call(address dest, bool mt_safe) {
|
||||
// Skip over auipc + ld
|
||||
address jmp_ins_pc = instruction_address() + 2 * NativeInstruction::instruction_size;
|
||||
// Rutime calls may be unaligned, but they are never changed after relocation.
|
||||
assert(!mt_safe || is_aligned(jmp_ins_pc, NativeInstruction::instruction_size), "Must be naturally aligned: %p", jmp_ins_pc);
|
||||
// If reachable use JAL
|
||||
if (Assembler::reachable_from_branch_at(jmp_ins_pc, dest)) {
|
||||
int64_t distance = dest - jmp_ins_pc;
|
||||
uint32_t new_jal = Assembler::encode_jal(ra, distance);
|
||||
Atomic::store((uint32_t *)jmp_ins_pc, new_jal);
|
||||
} else if (!MacroAssembler::is_jalr_at(jmp_ins_pc)) { // The jalr is always identical: jalr ra, 0(t1)
|
||||
uint32_t new_jalr = Assembler::encode_jalr(ra, t1, 0);
|
||||
Atomic::store((uint32_t *)jmp_ins_pc, new_jalr);
|
||||
} else {
|
||||
// No change to instruction stream
|
||||
return;
|
||||
}
|
||||
// We changed instruction stream
|
||||
if (mt_safe) {
|
||||
// IC invalidate provides a leading full fence, it thus happens after we changed the instruction stream.
|
||||
ICache::invalidate_range(jmp_ins_pc, NativeInstruction::instruction_size);
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeCall::set_destination_mt_safe(address dest) {
|
||||
assert(NativeCall::is_at(instruction_address()), "unexpected code at call site");
|
||||
assert((CodeCache_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) ||
|
||||
@@ -96,15 +121,17 @@ bool NativeCall::set_destination_mt_safe(address dest) {
|
||||
"concurrent code patching");
|
||||
|
||||
address stub_addr = stub_address();
|
||||
if (stub_addr != nullptr) {
|
||||
set_stub_address_destination_at(stub_addr, dest);
|
||||
return true;
|
||||
}
|
||||
assert(stub_addr != nullptr, "No stub?");
|
||||
set_stub_address_destination_at(stub_addr, dest); // release
|
||||
// optimize_call happens after we stored new address in addr stub.
|
||||
// patches jalr -> jal/jal -> jalr depending on dest
|
||||
optimize_call(dest, true);
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NativeCall::reloc_set_destination(address dest) {
|
||||
// The argument passed in is the address to the stub containing the destination
|
||||
bool NativeCall::reloc_set_destination(address stub_addr) {
|
||||
address call_addr = instruction_address();
|
||||
assert(NativeCall::is_at(call_addr), "unexpected code at call site");
|
||||
|
||||
@@ -113,10 +140,12 @@ bool NativeCall::reloc_set_destination(address dest) {
|
||||
|
||||
if (code->is_nmethod()) {
|
||||
// TODO: Need to revisit this when porting the AOT features.
|
||||
assert(dest != nullptr, "Sanity");
|
||||
assert(dest == trampoline_stub_Relocation::get_trampoline_for(call_addr,
|
||||
code->as_nmethod()), "Sanity");
|
||||
MacroAssembler::pd_patch_instruction_size(call_addr, dest);
|
||||
assert(stub_addr != nullptr, "Sanity");
|
||||
assert(stub_addr == trampoline_stub_Relocation::get_trampoline_for(call_addr, code->as_nmethod()), "Sanity");
|
||||
MacroAssembler::pd_patch_instruction_size(call_addr, stub_addr); // patches auipc + ld to stub_addr
|
||||
|
||||
address dest = stub_address_destination_at(stub_addr);
|
||||
optimize_call(dest, false); // patches jalr -> jal/jal -> jalr depending on dest
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -142,9 +171,9 @@ address NativeCall::stub_address() {
|
||||
CodeBlob *code = CodeCache::find_blob(call_addr);
|
||||
assert(code != nullptr, "Could not find the containing code blob");
|
||||
|
||||
address dest = MacroAssembler::target_addr_for_insn(call_addr);
|
||||
assert(code->contains(dest), "Sanity");
|
||||
return dest;
|
||||
address stub_addr = MacroAssembler::target_addr_for_insn(call_addr);
|
||||
assert(code->contains(stub_addr), "Sanity");
|
||||
return stub_addr;
|
||||
}
|
||||
|
||||
bool NativeCall::is_at(address addr) {
|
||||
@@ -160,6 +189,15 @@ bool NativeCall::is_at(address addr) {
|
||||
(MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) {
|
||||
return true;
|
||||
}
|
||||
if (MacroAssembler::is_auipc_at(addr) &&
|
||||
MacroAssembler::is_ld_at(addr + instr_size) &&
|
||||
MacroAssembler::is_jal_at(addr + 2 * instr_size) &&
|
||||
(MacroAssembler::extract_rd(addr) == x6) &&
|
||||
(MacroAssembler::extract_rd(addr + instr_size) == x6) &&
|
||||
(MacroAssembler::extract_rs1(addr + instr_size) == x6) &&
|
||||
(MacroAssembler::extract_rd(addr + 2 * instr_size) == x1)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,6 +157,10 @@ class NativeCall: private NativeInstruction {
|
||||
static void set_stub_address_destination_at(address dest, address value);
|
||||
// return target address at stub
|
||||
static address stub_address_destination_at(address src);
|
||||
// We either have a jalr or jal depending on distance to old destination.
|
||||
// This method emits a new jal if new destination is within jal reach.
|
||||
// Otherwise restores the jalr which can reach any destination.
|
||||
void optimize_call(address dest, bool mt_safe = true);
|
||||
};
|
||||
|
||||
// An interface for accessing/manipulating native mov reg, imm instructions.
|
||||
|
||||
@@ -8932,7 +8932,7 @@ instruct encodeKlass_not_null(iRegNNoSp dst, iRegP src) %{
|
||||
instruct decodeKlass_not_null(iRegPNoSp dst, iRegN src, iRegPNoSp tmp) %{
|
||||
match(Set dst (DecodeNKlass src));
|
||||
|
||||
effect(TEMP tmp);
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
|
||||
ins_cost(ALU_COST);
|
||||
format %{ "decode_klass_not_null $dst, $src\t#@decodeKlass_not_null" %}
|
||||
|
||||
@@ -683,10 +683,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
address start = __ pc();
|
||||
|
||||
if (UseBlockZeroing) {
|
||||
// Ensure count >= 2*CacheLineSize so that it still deserves a cbo.zero
|
||||
// after alignment.
|
||||
int zicboz_block_size = VM_Version::zicboz_block_size.value();
|
||||
// Ensure count >= 2 * zicboz_block_size so that it still deserves
|
||||
// a cbo.zero after alignment.
|
||||
Label small;
|
||||
int low_limit = MAX2(2 * CacheLineSize, BlockZeroingLowLimit) / wordSize;
|
||||
int low_limit = MAX2(2 * zicboz_block_size, (int)BlockZeroingLowLimit) / wordSize;
|
||||
__ mv(tmp1, low_limit);
|
||||
__ blt(cnt, tmp1, small);
|
||||
__ zero_dcache_blocks(base, cnt, tmp1, tmp2);
|
||||
|
||||
@@ -181,12 +181,13 @@ void VM_Version::common_initialize() {
|
||||
FLAG_SET_DEFAULT(UsePopCountInstruction, false);
|
||||
}
|
||||
|
||||
if (UseZicboz) {
|
||||
if (UseZicboz && zicboz_block_size.enabled() && zicboz_block_size.value() > 0) {
|
||||
assert(is_power_of_2(zicboz_block_size.value()), "Sanity");
|
||||
if (FLAG_IS_DEFAULT(UseBlockZeroing)) {
|
||||
FLAG_SET_DEFAULT(UseBlockZeroing, true);
|
||||
}
|
||||
if (FLAG_IS_DEFAULT(BlockZeroingLowLimit)) {
|
||||
FLAG_SET_DEFAULT(BlockZeroingLowLimit, 2 * CacheLineSize);
|
||||
FLAG_SET_DEFAULT(BlockZeroingLowLimit, 4 * zicboz_block_size.value());
|
||||
}
|
||||
} else if (UseBlockZeroing) {
|
||||
warning("Block zeroing is not available");
|
||||
@@ -476,10 +477,6 @@ void VM_Version::c2_initialize() {
|
||||
warning("AES/CTR intrinsics are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
|
||||
}
|
||||
|
||||
if (FLAG_IS_DEFAULT(AlignVector)) {
|
||||
FLAG_SET_DEFAULT(AlignVector, AvoidUnalignedAccesses);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // COMPILER2
|
||||
|
||||
@@ -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,45 +162,46 @@ 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) \
|
||||
#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 DECLARE_RV_FEATURE(NAME, PRETTY, BIT, FSTRING, FLAGF) \
|
||||
struct NAME##RVFeatureValue : public RVFeatureValue { \
|
||||
|
||||
@@ -1069,6 +1069,7 @@ void VM_Version::get_processor_features() {
|
||||
|
||||
if (FLAG_IS_DEFAULT(IntelJccErratumMitigation)) {
|
||||
_has_intel_jcc_erratum = compute_has_intel_jcc_erratum();
|
||||
FLAG_SET_ERGO(IntelJccErratumMitigation, _has_intel_jcc_erratum);
|
||||
} else {
|
||||
_has_intel_jcc_erratum = IntelJccErratumMitigation;
|
||||
}
|
||||
|
||||
@@ -89,6 +89,8 @@
|
||||
#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
|
||||
#define NR_arch_specific_syscall 244
|
||||
@@ -114,7 +116,8 @@ 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_CPUPERF_0, 0},
|
||||
{RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE, 0}};
|
||||
|
||||
bool RiscvHwprobe::probe_features() {
|
||||
assert(!rw_hwprobe_completed, "Called twice.");
|
||||
@@ -188,6 +191,9 @@ void RiscvHwprobe::add_features_from_query_result() {
|
||||
VM_Version::ext_Zbs.enable_feature();
|
||||
}
|
||||
#ifndef PRODUCT
|
||||
if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICBOZ)) {
|
||||
VM_Version::ext_Zicboz.enable_feature();
|
||||
}
|
||||
if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBKB)) {
|
||||
VM_Version::ext_Zbkb.enable_feature();
|
||||
}
|
||||
@@ -244,4 +250,7 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ friend class ciObjectFactory; \
|
||||
// Any more access must be given explicitly.
|
||||
#define CI_PACKAGE_ACCESS_TO \
|
||||
friend class ciObjectFactory; \
|
||||
friend class VMStructs; \
|
||||
friend class ciCallSite; \
|
||||
friend class ciConstantPoolCache; \
|
||||
friend class ciField; \
|
||||
|
||||
@@ -404,7 +404,7 @@ double CompilationPolicy::threshold_scale(CompLevel level, int feedback_k) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CompilationPolicy::print_counters(const char* prefix, Method* m) {
|
||||
void CompilationPolicy::print_counters_on(outputStream* st, const char* prefix, Method* m) {
|
||||
int invocation_count = m->invocation_count();
|
||||
int backedge_count = m->backedge_count();
|
||||
MethodData* mdh = m->method_data();
|
||||
@@ -416,133 +416,140 @@ void CompilationPolicy::print_counters(const char* prefix, Method* m) {
|
||||
mdo_invocations_start = mdh->invocation_count_start();
|
||||
mdo_backedges_start = mdh->backedge_count_start();
|
||||
}
|
||||
tty->print(" %stotal=%d,%d %smdo=%d(%d),%d(%d)", prefix,
|
||||
invocation_count, backedge_count, prefix,
|
||||
mdo_invocations, mdo_invocations_start,
|
||||
mdo_backedges, mdo_backedges_start);
|
||||
tty->print(" %smax levels=%d,%d", prefix,
|
||||
m->highest_comp_level(), m->highest_osr_comp_level());
|
||||
st->print(" %stotal=%d,%d %smdo=%d(%d),%d(%d)", prefix,
|
||||
invocation_count, backedge_count, prefix,
|
||||
mdo_invocations, mdo_invocations_start,
|
||||
mdo_backedges, mdo_backedges_start);
|
||||
st->print(" %smax levels=%d,%d", prefix, m->highest_comp_level(), m->highest_osr_comp_level());
|
||||
}
|
||||
|
||||
void CompilationPolicy::print_training_data(const char* prefix, Method* method) {
|
||||
void CompilationPolicy::print_training_data_on(outputStream* st, const char* prefix, Method* method) {
|
||||
methodHandle m(Thread::current(), method);
|
||||
tty->print(" %smtd: ", prefix);
|
||||
st->print(" %smtd: ", prefix);
|
||||
MethodTrainingData* mtd = MethodTrainingData::find(m);
|
||||
if (mtd == nullptr) {
|
||||
tty->print("null");
|
||||
st->print("null");
|
||||
} else {
|
||||
MethodData* md = mtd->final_profile();
|
||||
tty->print("mdo=");
|
||||
st->print("mdo=");
|
||||
if (md == nullptr) {
|
||||
tty->print("null");
|
||||
st->print("null");
|
||||
} else {
|
||||
int mdo_invocations = md->invocation_count();
|
||||
int mdo_backedges = md->backedge_count();
|
||||
int mdo_invocations_start = md->invocation_count_start();
|
||||
int mdo_backedges_start = md->backedge_count_start();
|
||||
tty->print("%d(%d), %d(%d)", mdo_invocations, mdo_invocations_start, mdo_backedges, mdo_backedges_start);
|
||||
st->print("%d(%d), %d(%d)", mdo_invocations, mdo_invocations_start, mdo_backedges, mdo_backedges_start);
|
||||
}
|
||||
CompileTrainingData* ctd = mtd->last_toplevel_compile(CompLevel_full_optimization);
|
||||
tty->print(", deps=");
|
||||
st->print(", deps=");
|
||||
if (ctd == nullptr) {
|
||||
tty->print("null");
|
||||
st->print("null");
|
||||
} else {
|
||||
tty->print("%d", ctd->init_deps_left());
|
||||
st->print("%d", ctd->init_deps_left());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print an event.
|
||||
void CompilationPolicy::print_event(EventType type, Method* m, Method* im, int bci, CompLevel level) {
|
||||
void CompilationPolicy::print_event_on(outputStream *st, EventType type, Method* m, Method* im, int bci, CompLevel level) {
|
||||
bool inlinee_event = m != im;
|
||||
|
||||
ttyLocker tty_lock;
|
||||
tty->print("%lf: [", os::elapsedTime());
|
||||
st->print("%lf: [", os::elapsedTime());
|
||||
|
||||
switch(type) {
|
||||
case CALL:
|
||||
tty->print("call");
|
||||
st->print("call");
|
||||
break;
|
||||
case LOOP:
|
||||
tty->print("loop");
|
||||
st->print("loop");
|
||||
break;
|
||||
case COMPILE:
|
||||
tty->print("compile");
|
||||
st->print("compile");
|
||||
break;
|
||||
case FORCE_COMPILE:
|
||||
tty->print("force-compile");
|
||||
st->print("force-compile");
|
||||
break;
|
||||
case REMOVE_FROM_QUEUE:
|
||||
tty->print("remove-from-queue");
|
||||
st->print("remove-from-queue");
|
||||
break;
|
||||
case UPDATE_IN_QUEUE:
|
||||
tty->print("update-in-queue");
|
||||
st->print("update-in-queue");
|
||||
break;
|
||||
case REPROFILE:
|
||||
tty->print("reprofile");
|
||||
st->print("reprofile");
|
||||
break;
|
||||
case MAKE_NOT_ENTRANT:
|
||||
tty->print("make-not-entrant");
|
||||
st->print("make-not-entrant");
|
||||
break;
|
||||
default:
|
||||
tty->print("unknown");
|
||||
st->print("unknown");
|
||||
}
|
||||
|
||||
tty->print(" level=%d ", level);
|
||||
st->print(" level=%d ", level);
|
||||
|
||||
ResourceMark rm;
|
||||
char *method_name = m->name_and_sig_as_C_string();
|
||||
tty->print("[%s", method_name);
|
||||
st->print("[%s", method_name);
|
||||
if (inlinee_event) {
|
||||
char *inlinee_name = im->name_and_sig_as_C_string();
|
||||
tty->print(" [%s]] ", inlinee_name);
|
||||
st->print(" [%s]] ", inlinee_name);
|
||||
}
|
||||
else tty->print("] ");
|
||||
tty->print("@%d queues=%d,%d", bci, CompileBroker::queue_size(CompLevel_full_profile),
|
||||
CompileBroker::queue_size(CompLevel_full_optimization));
|
||||
else st->print("] ");
|
||||
st->print("@%d queues=%d,%d", bci, CompileBroker::queue_size(CompLevel_full_profile),
|
||||
CompileBroker::queue_size(CompLevel_full_optimization));
|
||||
|
||||
tty->print(" rate=");
|
||||
if (m->prev_time() == 0) tty->print("n/a");
|
||||
else tty->print("%f", m->rate());
|
||||
st->print(" rate=");
|
||||
if (m->prev_time() == 0) st->print("n/a");
|
||||
else st->print("%f", m->rate());
|
||||
|
||||
tty->print(" k=%.2lf,%.2lf", threshold_scale(CompLevel_full_profile, Tier3LoadFeedback),
|
||||
threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback));
|
||||
st->print(" k=%.2lf,%.2lf", threshold_scale(CompLevel_full_profile, Tier3LoadFeedback),
|
||||
threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback));
|
||||
|
||||
if (type != COMPILE) {
|
||||
print_counters("", m);
|
||||
print_counters_on(st, "", m);
|
||||
if (inlinee_event) {
|
||||
print_counters("inlinee ", im);
|
||||
print_counters_on(st, "inlinee ", im);
|
||||
}
|
||||
tty->print(" compilable=");
|
||||
st->print(" compilable=");
|
||||
bool need_comma = false;
|
||||
if (!m->is_not_compilable(CompLevel_full_profile)) {
|
||||
tty->print("c1");
|
||||
st->print("c1");
|
||||
need_comma = true;
|
||||
}
|
||||
if (!m->is_not_osr_compilable(CompLevel_full_profile)) {
|
||||
if (need_comma) tty->print(",");
|
||||
tty->print("c1-osr");
|
||||
if (need_comma) st->print(",");
|
||||
st->print("c1-osr");
|
||||
need_comma = true;
|
||||
}
|
||||
if (!m->is_not_compilable(CompLevel_full_optimization)) {
|
||||
if (need_comma) tty->print(",");
|
||||
tty->print("c2");
|
||||
if (need_comma) st->print(",");
|
||||
st->print("c2");
|
||||
need_comma = true;
|
||||
}
|
||||
if (!m->is_not_osr_compilable(CompLevel_full_optimization)) {
|
||||
if (need_comma) tty->print(",");
|
||||
tty->print("c2-osr");
|
||||
if (need_comma) st->print(",");
|
||||
st->print("c2-osr");
|
||||
}
|
||||
tty->print(" status=");
|
||||
st->print(" status=");
|
||||
if (m->queued_for_compilation()) {
|
||||
tty->print("in-queue");
|
||||
} else tty->print("idle");
|
||||
print_training_data("", m);
|
||||
st->print("in-queue");
|
||||
} else st->print("idle");
|
||||
|
||||
print_training_data_on(st, "", m);
|
||||
if (inlinee_event) {
|
||||
print_training_data("inlinee ", im);
|
||||
print_training_data_on(st, "inlinee ", im);
|
||||
}
|
||||
}
|
||||
tty->print_cr("]");
|
||||
st->print_cr("]");
|
||||
|
||||
}
|
||||
|
||||
void CompilationPolicy::print_event(EventType type, Method* m, Method* im, int bci, CompLevel level) {
|
||||
stringStream s;
|
||||
print_event_on(&s, type, m, im, bci, level);
|
||||
ResourceMark rm;
|
||||
tty->print("%s", s.as_string());
|
||||
}
|
||||
|
||||
void CompilationPolicy::initialize() {
|
||||
@@ -1335,17 +1342,24 @@ CompLevel CompilationPolicy::standard_transition(const methodHandle& method, Com
|
||||
return next_level;
|
||||
}
|
||||
|
||||
template<typename Predicate> static inline bool apply_predicate(const methodHandle& method, CompLevel cur_level, int i, int b, bool delay_profiling, double delay_profiling_scale) {
|
||||
if (delay_profiling) {
|
||||
return Predicate::apply_scaled(method, cur_level, i, b, delay_profiling_scale);
|
||||
} else {
|
||||
return Predicate::apply(method, cur_level, i, b);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Predicate>
|
||||
CompLevel CompilationPolicy::transition_from_none(const methodHandle& method, CompLevel cur_level, bool delay_profiling, bool disable_feedback) {
|
||||
precond(cur_level == CompLevel_none);
|
||||
CompLevel next_level = cur_level;
|
||||
int i = method->invocation_count();
|
||||
int b = method->backedge_count();
|
||||
double scale = delay_profiling ? Tier0ProfileDelayFactor : 1.0;
|
||||
// If we were at full profile level, would we switch to full opt?
|
||||
if (transition_from_full_profile<Predicate>(method, CompLevel_full_profile) == CompLevel_full_optimization) {
|
||||
next_level = CompLevel_full_optimization;
|
||||
} else if (!CompilationModeFlag::disable_intermediate() && Predicate::apply_scaled(method, cur_level, i, b, scale)) {
|
||||
} else if (!CompilationModeFlag::disable_intermediate() && apply_predicate<Predicate>(method, cur_level, i, b, delay_profiling, Tier0ProfileDelayFactor)) {
|
||||
// C1-generated fully profiled code is about 30% slower than the limited profile
|
||||
// code that has only invocation and backedge counters. The observation is that
|
||||
// if C2 queue is large enough we can spend too much time in the fully profiled code
|
||||
@@ -1387,13 +1401,12 @@ CompLevel CompilationPolicy::transition_from_limited_profile(const methodHandle&
|
||||
CompLevel next_level = cur_level;
|
||||
int i = method->invocation_count();
|
||||
int b = method->backedge_count();
|
||||
double scale = delay_profiling ? Tier2ProfileDelayFactor : 1.0;
|
||||
MethodData* mdo = method->method_data();
|
||||
if (mdo != nullptr) {
|
||||
if (mdo->would_profile()) {
|
||||
if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <=
|
||||
Tier3DelayOff * compiler_count(CompLevel_full_optimization) &&
|
||||
Predicate::apply_scaled(method, cur_level, i, b, scale))) {
|
||||
apply_predicate<Predicate>(method, cur_level, i, b, delay_profiling, Tier2ProfileDelayFactor))) {
|
||||
next_level = CompLevel_full_profile;
|
||||
}
|
||||
} else {
|
||||
@@ -1403,7 +1416,7 @@ CompLevel CompilationPolicy::transition_from_limited_profile(const methodHandle&
|
||||
// If there is no MDO we need to profile
|
||||
if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <=
|
||||
Tier3DelayOff * compiler_count(CompLevel_full_optimization) &&
|
||||
Predicate::apply_scaled(method, cur_level, i, b, scale))) {
|
||||
apply_predicate<Predicate>(method, cur_level, i, b, delay_profiling, Tier2ProfileDelayFactor))) {
|
||||
next_level = CompLevel_full_profile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,8 +287,8 @@ class CompilationPolicy : AllStatic {
|
||||
// loop_event checks if a method should be OSR compiled at a different
|
||||
// level.
|
||||
static CompLevel loop_event(const methodHandle& method, CompLevel cur_level, JavaThread* THREAD);
|
||||
static void print_counters(const char* prefix, Method* m);
|
||||
static void print_training_data(const char* prefix, Method* method);
|
||||
static void print_counters_on(outputStream* st, const char* prefix, Method* m);
|
||||
static void print_training_data_on(outputStream* st, const char* prefix, Method* method);
|
||||
// Has a method been long around?
|
||||
// We don't remove old methods from the compile queue even if they have
|
||||
// very low activity (see select_task()).
|
||||
@@ -318,6 +318,7 @@ class CompilationPolicy : AllStatic {
|
||||
static void set_c2_count(int x) { _c2_count = x; }
|
||||
|
||||
enum EventType { CALL, LOOP, COMPILE, FORCE_COMPILE, FORCE_RECOMPILE, REMOVE_FROM_QUEUE, UPDATE_IN_QUEUE, REPROFILE, MAKE_NOT_ENTRANT };
|
||||
static void print_event_on(outputStream *st, EventType type, Method* m, Method* im, int bci, CompLevel level);
|
||||
static void print_event(EventType type, Method* m, Method* im, int bci, CompLevel level);
|
||||
// Check if the method can be compiled, change level if necessary
|
||||
static void compile(const methodHandle& mh, int bci, CompLevel level, TRAPS);
|
||||
|
||||
@@ -34,6 +34,7 @@ public:
|
||||
enum Type {
|
||||
_alloc_shared, // Allocate common, outside of TLAB
|
||||
_alloc_shared_gc, // Allocate common, outside of GCLAB/PLAB
|
||||
_alloc_cds, // Allocate for CDS
|
||||
_alloc_tlab, // Allocate TLAB
|
||||
_alloc_gclab, // Allocate GCLAB
|
||||
_alloc_plab, // Allocate PLAB
|
||||
@@ -46,6 +47,8 @@ public:
|
||||
return "Shared";
|
||||
case _alloc_shared_gc:
|
||||
return "Shared GC";
|
||||
case _alloc_cds:
|
||||
return "CDS";
|
||||
case _alloc_tlab:
|
||||
return "TLAB";
|
||||
case _alloc_gclab:
|
||||
@@ -121,6 +124,10 @@ public:
|
||||
return ShenandoahAllocRequest(0, requested_size, _alloc_shared, ShenandoahAffiliation::YOUNG_GENERATION);
|
||||
}
|
||||
|
||||
static inline ShenandoahAllocRequest for_cds(size_t requested_size) {
|
||||
return ShenandoahAllocRequest(0, requested_size, _alloc_cds, ShenandoahAffiliation::YOUNG_GENERATION);
|
||||
}
|
||||
|
||||
inline size_t size() const {
|
||||
return _requested_size;
|
||||
}
|
||||
@@ -163,6 +170,7 @@ public:
|
||||
switch (_alloc_type) {
|
||||
case _alloc_tlab:
|
||||
case _alloc_shared:
|
||||
case _alloc_cds:
|
||||
return true;
|
||||
case _alloc_gclab:
|
||||
case _alloc_plab:
|
||||
@@ -178,6 +186,7 @@ public:
|
||||
switch (_alloc_type) {
|
||||
case _alloc_tlab:
|
||||
case _alloc_shared:
|
||||
case _alloc_cds:
|
||||
return false;
|
||||
case _alloc_gclab:
|
||||
case _alloc_plab:
|
||||
@@ -197,6 +206,7 @@ public:
|
||||
return true;
|
||||
case _alloc_shared:
|
||||
case _alloc_shared_gc:
|
||||
case _alloc_cds:
|
||||
return false;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
|
||||
@@ -1198,6 +1198,7 @@ void ShenandoahConcurrentGC::op_final_update_refs() {
|
||||
// We are not concerned about skipping this step in abbreviated cycles because regions
|
||||
// with no live objects cannot have been written to and so cannot have entries in the SATB
|
||||
// buffers.
|
||||
ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_transfer_satb);
|
||||
heap->old_generation()->transfer_pointers_from_satb();
|
||||
|
||||
// Aging_cycle is only relevant during evacuation cycle for individual objects and during final mark for
|
||||
|
||||
@@ -816,6 +816,7 @@ HeapWord* ShenandoahFreeSet::allocate_single(ShenandoahAllocRequest& req, bool&
|
||||
switch (req.type()) {
|
||||
case ShenandoahAllocRequest::_alloc_tlab:
|
||||
case ShenandoahAllocRequest::_alloc_shared:
|
||||
case ShenandoahAllocRequest::_alloc_cds:
|
||||
return allocate_for_mutator(req, in_new_region);
|
||||
case ShenandoahAllocRequest::_alloc_gclab:
|
||||
case ShenandoahAllocRequest::_alloc_plab:
|
||||
@@ -1169,8 +1170,8 @@ HeapWord* ShenandoahFreeSet::try_allocate_in(ShenandoahHeapRegion* r, Shenandoah
|
||||
return result;
|
||||
}
|
||||
|
||||
HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) {
|
||||
assert(req.is_mutator_alloc(), "All humongous allocations are performed by mutator");
|
||||
HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req, bool is_humongous) {
|
||||
assert(req.is_mutator_alloc(), "All contiguous allocations are performed by mutator");
|
||||
shenandoah_assert_heaplocked();
|
||||
|
||||
size_t words_size = req.size();
|
||||
@@ -1244,10 +1245,16 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) {
|
||||
assert(i == beg || _heap->get_region(i - 1)->index() + 1 == r->index(), "Should be contiguous");
|
||||
assert(r->is_empty(), "Should be empty");
|
||||
|
||||
if (i == beg) {
|
||||
r->make_humongous_start();
|
||||
r->set_affiliation(req.affiliation());
|
||||
|
||||
if (is_humongous) {
|
||||
if (i == beg) {
|
||||
r->make_humongous_start();
|
||||
} else {
|
||||
r->make_humongous_cont();
|
||||
}
|
||||
} else {
|
||||
r->make_humongous_cont();
|
||||
r->make_regular_allocation(req.affiliation());
|
||||
}
|
||||
|
||||
// Trailing region may be non-full, record the remainder there
|
||||
@@ -1257,8 +1264,6 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) {
|
||||
} else {
|
||||
used_words = ShenandoahHeapRegion::region_size_words();
|
||||
}
|
||||
|
||||
r->set_affiliation(req.affiliation());
|
||||
r->set_update_watermark(r->bottom());
|
||||
r->set_top(r->bottom() + used_words);
|
||||
}
|
||||
@@ -1268,14 +1273,26 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) {
|
||||
_heap->notify_mutator_alloc_words(ShenandoahHeapRegion::region_size_words() - remainder, true);
|
||||
}
|
||||
|
||||
// retire_range_from_partition() will adjust bounds on Mutator free set if appropriate
|
||||
_partitions.retire_range_from_partition(ShenandoahFreeSetPartitionId::Mutator, beg, end);
|
||||
|
||||
size_t total_humongous_size = ShenandoahHeapRegion::region_size_bytes() * num;
|
||||
_partitions.increase_used(ShenandoahFreeSetPartitionId::Mutator, total_humongous_size);
|
||||
size_t total_used = 0;
|
||||
if (is_humongous) {
|
||||
// Humongous allocation retires all regions at once: no allocation is possible anymore.
|
||||
_partitions.retire_range_from_partition(ShenandoahFreeSetPartitionId::Mutator, beg, end);
|
||||
total_used = ShenandoahHeapRegion::region_size_bytes() * num;
|
||||
} else {
|
||||
// Non-humongous allocation retires only the regions that cannot be used for allocation anymore.
|
||||
for (idx_t i = beg; i <= end; i++) {
|
||||
ShenandoahHeapRegion* r = _heap->get_region(i);
|
||||
if (r->free() < PLAB::min_size() * HeapWordSize) {
|
||||
_partitions.retire_from_partition(ShenandoahFreeSetPartitionId::Mutator, i, r->used());
|
||||
}
|
||||
total_used += r->used();
|
||||
}
|
||||
}
|
||||
_partitions.increase_used(ShenandoahFreeSetPartitionId::Mutator, total_used);
|
||||
_partitions.assert_bounds();
|
||||
|
||||
req.set_actual_size(words_size);
|
||||
if (remainder != 0) {
|
||||
if (remainder != 0 && is_humongous) {
|
||||
req.set_waste(ShenandoahHeapRegion::region_size_words() - remainder);
|
||||
}
|
||||
return _heap->get_region(beg)->bottom();
|
||||
@@ -2064,7 +2081,10 @@ HeapWord* ShenandoahFreeSet::allocate(ShenandoahAllocRequest& req, bool& in_new_
|
||||
case ShenandoahAllocRequest::_alloc_shared:
|
||||
case ShenandoahAllocRequest::_alloc_shared_gc:
|
||||
in_new_region = true;
|
||||
return allocate_contiguous(req);
|
||||
return allocate_contiguous(req, /* is_humongous = */ true);
|
||||
case ShenandoahAllocRequest::_alloc_cds:
|
||||
in_new_region = true;
|
||||
return allocate_contiguous(req, /* is_humongous = */ false);
|
||||
case ShenandoahAllocRequest::_alloc_plab:
|
||||
case ShenandoahAllocRequest::_alloc_gclab:
|
||||
case ShenandoahAllocRequest::_alloc_tlab:
|
||||
|
||||
@@ -345,7 +345,7 @@ private:
|
||||
// object. No other objects are packed into these regions.
|
||||
//
|
||||
// Precondition: ShenandoahHeapRegion::requires_humongous(req.size())
|
||||
HeapWord* allocate_contiguous(ShenandoahAllocRequest& req);
|
||||
HeapWord* allocate_contiguous(ShenandoahAllocRequest& req, bool is_humongous);
|
||||
|
||||
// Change region r from the Mutator partition to the GC's Collector or OldCollector partition. This requires that the
|
||||
// region is entirely empty.
|
||||
|
||||
@@ -2796,41 +2796,15 @@ bool ShenandoahHeap::requires_barriers(stackChunkOop obj) const {
|
||||
|
||||
HeapWord* ShenandoahHeap::allocate_loaded_archive_space(size_t size) {
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
// CDS wants a continuous memory range to load a bunch of objects.
|
||||
// This effectively bypasses normal allocation paths, and requires
|
||||
// a bit of massaging to unbreak GC invariants.
|
||||
// CDS wants a raw continuous memory range to load a bunch of objects itself.
|
||||
// This is an unusual request, since all requested regions should be regular, not humongous.
|
||||
//
|
||||
// CDS would guarantee no objects straddle multiple regions, as long as regions are as large
|
||||
// as MIN_GC_REGION_ALIGNMENT.
|
||||
guarantee(ShenandoahHeapRegion::region_size_bytes() >= ArchiveHeapWriter::MIN_GC_REGION_ALIGNMENT, "Must be");
|
||||
|
||||
ShenandoahAllocRequest req = ShenandoahAllocRequest::for_shared(size);
|
||||
|
||||
// Easy case: a single regular region, no further adjustments needed.
|
||||
if (!ShenandoahHeapRegion::requires_humongous(size)) {
|
||||
return allocate_memory(req);
|
||||
}
|
||||
|
||||
// Hard case: the requested size would cause a humongous allocation.
|
||||
// We need to make sure it looks like regular allocation to the rest of GC.
|
||||
|
||||
// CDS code would guarantee no objects straddle multiple regions, as long as
|
||||
// regions are as large as MIN_GC_REGION_ALIGNMENT. It is impractical at this
|
||||
// point to deal with case when Shenandoah runs with smaller regions.
|
||||
// TODO: This check can be dropped once MIN_GC_REGION_ALIGNMENT agrees more with Shenandoah.
|
||||
if (ShenandoahHeapRegion::region_size_bytes() < ArchiveHeapWriter::MIN_GC_REGION_ALIGNMENT) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HeapWord* mem = allocate_memory(req);
|
||||
size_t start_idx = heap_region_index_containing(mem);
|
||||
size_t num_regions = ShenandoahHeapRegion::required_regions(size * HeapWordSize);
|
||||
|
||||
// Flip humongous -> regular.
|
||||
{
|
||||
ShenandoahHeapLocker locker(lock(), false);
|
||||
for (size_t c = start_idx; c < start_idx + num_regions; c++) {
|
||||
get_region(c)->make_regular_bypass();
|
||||
}
|
||||
}
|
||||
|
||||
return mem;
|
||||
ShenandoahAllocRequest req = ShenandoahAllocRequest::for_cds(size);
|
||||
return allocate_memory(req);
|
||||
#else
|
||||
assert(false, "Archive heap loader should not be available, should not be here");
|
||||
return nullptr;
|
||||
@@ -2857,17 +2831,25 @@ void ShenandoahHeap::complete_loaded_archive_space(MemRegion archive_space) {
|
||||
"Archive space should be fully used: " PTR_FORMAT " " PTR_FORMAT,
|
||||
p2i(cur), p2i(end));
|
||||
|
||||
// Region bounds are good.
|
||||
ShenandoahHeapRegion* begin_reg = heap_region_containing(start);
|
||||
ShenandoahHeapRegion* end_reg = heap_region_containing(end);
|
||||
assert(begin_reg->is_regular(), "Must be");
|
||||
assert(end_reg->is_regular(), "Must be");
|
||||
assert(begin_reg->bottom() == start,
|
||||
"Must agree: archive-space-start: " PTR_FORMAT ", begin-region-bottom: " PTR_FORMAT,
|
||||
p2i(start), p2i(begin_reg->bottom()));
|
||||
assert(end_reg->top() == end,
|
||||
"Must agree: archive-space-end: " PTR_FORMAT ", end-region-top: " PTR_FORMAT,
|
||||
p2i(end), p2i(end_reg->top()));
|
||||
// All regions in contiguous space have good state.
|
||||
size_t begin_reg_idx = heap_region_index_containing(start);
|
||||
size_t end_reg_idx = heap_region_index_containing(end);
|
||||
|
||||
for (size_t idx = begin_reg_idx; idx <= end_reg_idx; idx++) {
|
||||
ShenandoahHeapRegion* r = get_region(idx);
|
||||
assert(r->is_regular(), "Must be regular");
|
||||
assert(r->is_young(), "Must be young");
|
||||
assert(idx == end_reg_idx || r->top() == r->end(),
|
||||
"All regions except the last one should be full: " PTR_FORMAT " " PTR_FORMAT,
|
||||
p2i(r->top()), p2i(r->end()));
|
||||
assert(idx != begin_reg_idx || r->bottom() == start,
|
||||
"Archive space start should be at the bottom of first region: " PTR_FORMAT " " PTR_FORMAT,
|
||||
p2i(r->bottom()), p2i(start));
|
||||
assert(idx != end_reg_idx || r->top() == end,
|
||||
"Archive space end should be at the top of last region: " PTR_FORMAT " " PTR_FORMAT,
|
||||
p2i(r->top()), p2i(end));
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -142,27 +142,17 @@ void ShenandoahHeapRegion::make_affiliated_maybe() {
|
||||
|
||||
void ShenandoahHeapRegion::make_regular_bypass() {
|
||||
shenandoah_assert_heaplocked();
|
||||
assert (!Universe::is_fully_initialized() ||
|
||||
ShenandoahHeap::heap()->is_full_gc_in_progress() ||
|
||||
assert (ShenandoahHeap::heap()->is_full_gc_in_progress() ||
|
||||
ShenandoahHeap::heap()->is_degenerated_gc_in_progress(),
|
||||
"Only for STW GC or when Universe is initializing (CDS)");
|
||||
"Only for STW GC");
|
||||
reset_age();
|
||||
auto cur_state = state();
|
||||
switch (cur_state) {
|
||||
switch (state()) {
|
||||
case _empty_uncommitted:
|
||||
do_commit();
|
||||
case _empty_committed:
|
||||
case _cset:
|
||||
case _humongous_start:
|
||||
case _humongous_cont:
|
||||
if (cur_state == _humongous_start || cur_state == _humongous_cont) {
|
||||
// CDS allocates chunks of the heap to fill with regular objects. The allocator
|
||||
// will dutifully track any waste in the unused portion of the last region. Once
|
||||
// CDS has finished initializing the objects, it will convert these regions to
|
||||
// regular regions. The 'waste' in the last region is no longer wasted at this point,
|
||||
// so we must stop treating it as such.
|
||||
decrement_humongous_waste();
|
||||
}
|
||||
set_state(_regular);
|
||||
return;
|
||||
case _pinned_cset:
|
||||
|
||||
@@ -113,6 +113,7 @@ inline void ShenandoahHeapRegion::adjust_alloc_metadata(ShenandoahAllocRequest::
|
||||
switch (type) {
|
||||
case ShenandoahAllocRequest::_alloc_shared:
|
||||
case ShenandoahAllocRequest::_alloc_shared_gc:
|
||||
case ShenandoahAllocRequest::_alloc_cds:
|
||||
// Counted implicitly by tlab/gclab allocs
|
||||
break;
|
||||
case ShenandoahAllocRequest::_alloc_tlab:
|
||||
|
||||
@@ -126,6 +126,7 @@ class outputStream;
|
||||
f(final_update_refs, "Pause Final Update Refs (N)") \
|
||||
f(final_update_refs_verify, " Verify") \
|
||||
f(final_update_refs_update_region_states, " Update Region States") \
|
||||
f(final_update_refs_transfer_satb, " Transfer Old From SATB") \
|
||||
f(final_update_refs_trash_cset, " Trash Collection Set") \
|
||||
f(final_update_refs_rebuild_freeset, " Rebuild Free Set") \
|
||||
f(final_update_refs_propagate_gc_state, " Propagate GC State") \
|
||||
|
||||
@@ -1087,7 +1087,8 @@ void ZPartition::free_memory_alloc_failed(ZMemoryAllocation* allocation) {
|
||||
freed += vmem.size();
|
||||
_cache.insert(vmem);
|
||||
}
|
||||
assert(allocation->harvested() + allocation->committed_capacity() == freed, "must have freed all");
|
||||
assert(allocation->harvested() + allocation->committed_capacity() == freed, "must have freed all"
|
||||
" %zu + %zu == %zu", allocation->harvested(), allocation->committed_capacity(), freed);
|
||||
|
||||
// Adjust capacity to reflect the failed capacity increase
|
||||
const size_t remaining = allocation->size() - freed;
|
||||
@@ -1904,23 +1905,27 @@ void ZPageAllocator::cleanup_failed_commit_single_partition(ZSinglePartitionAllo
|
||||
ZMemoryAllocation* const allocation = single_partition_allocation->allocation();
|
||||
|
||||
assert(allocation->commit_failed(), "Must have failed to commit");
|
||||
assert(allocation->partial_vmems()->is_empty(), "Invariant for single partition commit failure");
|
||||
|
||||
const size_t committed = allocation->committed_capacity();
|
||||
const ZVirtualMemory non_harvested_vmem = vmem.last_part(allocation->harvested());
|
||||
const ZVirtualMemory committed_vmem = non_harvested_vmem.first_part(committed);
|
||||
const ZVirtualMemory non_committed_vmem = non_harvested_vmem.last_part(committed);
|
||||
// For a single partition we have unmapped the harvested memory before we
|
||||
// started committing, and moved its physical memory association to the start
|
||||
// of the vmem. As such, the partial_vmems is empty. All the harvested and
|
||||
// partially successfully committed memory is mapped in the first part of vmem.
|
||||
const size_t harvested_and_committed_capacity = allocation->harvested() + allocation->committed_capacity();
|
||||
const ZVirtualMemory succeeded_vmem = vmem.first_part(harvested_and_committed_capacity);
|
||||
const ZVirtualMemory failed_vmem = vmem.last_part(harvested_and_committed_capacity);
|
||||
|
||||
if (committed_vmem.size() > 0) {
|
||||
if (succeeded_vmem.size() > 0) {
|
||||
// Register the committed and mapped memory. We insert the committed
|
||||
// memory into partial_vmems so that it will be inserted into the cache
|
||||
// in a subsequent step.
|
||||
allocation->partial_vmems()->append(committed_vmem);
|
||||
allocation->partial_vmems()->append(succeeded_vmem);
|
||||
}
|
||||
|
||||
// Free the virtual and physical memory we fetched to use but failed to commit
|
||||
ZPartition& partition = allocation->partition();
|
||||
partition.free_physical(non_committed_vmem);
|
||||
partition.free_virtual(non_committed_vmem);
|
||||
partition.free_physical(failed_vmem);
|
||||
partition.free_virtual(failed_vmem);
|
||||
}
|
||||
|
||||
void ZPageAllocator::cleanup_failed_commit_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem) {
|
||||
|
||||
@@ -113,12 +113,13 @@ static char* reserve_memory_inner(char* requested_address,
|
||||
ReservedSpace MemoryReserver::reserve_memory(char* requested_address,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
size_t page_size,
|
||||
bool exec,
|
||||
MemTag mem_tag) {
|
||||
char* base = reserve_memory_inner(requested_address, size, alignment, exec, mem_tag);
|
||||
|
||||
if (base != nullptr) {
|
||||
return ReservedSpace(base, size, alignment, os::vm_page_size(), exec, false /* special */);
|
||||
return ReservedSpace(base, size, alignment, page_size, exec, false /* special */);
|
||||
}
|
||||
|
||||
// Failed
|
||||
@@ -191,7 +192,7 @@ ReservedSpace MemoryReserver::reserve(char* requested_address,
|
||||
}
|
||||
|
||||
// == Case 3 ==
|
||||
return reserve_memory(requested_address, size, alignment, executable, mem_tag);
|
||||
return reserve_memory(requested_address, size, alignment, page_size, executable, mem_tag);
|
||||
}
|
||||
|
||||
ReservedSpace MemoryReserver::reserve(char* requested_address,
|
||||
|
||||
@@ -34,6 +34,7 @@ class MemoryReserver : AllStatic {
|
||||
static ReservedSpace reserve_memory(char* requested_address,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
size_t page_size,
|
||||
bool exec,
|
||||
MemTag mem_tag);
|
||||
|
||||
|
||||
@@ -52,6 +52,9 @@ class InstanceMirrorKlass: public InstanceKlass {
|
||||
|
||||
InstanceMirrorKlass(const ClassFileParser& parser) : InstanceKlass(parser, Kind) {}
|
||||
|
||||
template <class OopClosureType>
|
||||
inline void do_metadata(oop obj, OopClosureType* closure);
|
||||
|
||||
public:
|
||||
InstanceMirrorKlass();
|
||||
|
||||
|
||||
@@ -46,38 +46,41 @@ void InstanceMirrorKlass::oop_oop_iterate_statics(oop obj, OopClosureType* closu
|
||||
}
|
||||
}
|
||||
|
||||
template <class OopClosureType>
|
||||
void InstanceMirrorKlass::do_metadata(oop obj, OopClosureType* closure) {
|
||||
Klass* klass = java_lang_Class::as_Klass(obj);
|
||||
if (klass != nullptr) {
|
||||
if (klass->class_loader_data() == nullptr) {
|
||||
// This is a mirror that belongs to a shared class that has not been loaded yet.
|
||||
assert(klass->is_shared(), "Must be");
|
||||
} else if (klass->is_instance_klass() && klass->class_loader_data()->has_class_mirror_holder()) {
|
||||
// A non-strong hidden class doesn't have its own class loader,
|
||||
// so when handling the java mirror for the class we need to make sure its class
|
||||
// loader data is claimed, this is done by calling do_cld explicitly.
|
||||
// For non-strong hidden classes the call to do_cld is made when the class
|
||||
// loader itself is handled.
|
||||
Devirtualizer::do_cld(closure, klass->class_loader_data());
|
||||
} else {
|
||||
Devirtualizer::do_klass(closure, klass);
|
||||
}
|
||||
} else {
|
||||
// Java mirror -> Klass* "nullptr" backlink means either:
|
||||
// 1. This is a Java mirror for a primitive class. We do not need to follow it,
|
||||
// these mirrors are always strong roots.
|
||||
// 2. This is a Java mirror for a newly allocated non-primitive class, and we
|
||||
// somehow managed to reach the newly allocated Java mirror with not yet
|
||||
// installed backlink. We cannot do anything here, this case would be handled
|
||||
// separately by GC, e.g. by keeping the relevant metadata alive during the GC.
|
||||
// Unfortunately, the existence of corner case (2) prevents us from asserting (1).
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, class OopClosureType>
|
||||
void InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
|
||||
InstanceKlass::oop_oop_iterate<T>(obj, closure);
|
||||
|
||||
if (Devirtualizer::do_metadata(closure)) {
|
||||
Klass* klass = java_lang_Class::as_Klass(obj);
|
||||
// We'll get null for primitive mirrors.
|
||||
if (klass != nullptr) {
|
||||
if (klass->class_loader_data() == nullptr) {
|
||||
// This is a mirror that belongs to a shared class that has not be loaded yet.
|
||||
assert(klass->is_shared(), "must be");
|
||||
} else if (klass->is_instance_klass() && klass->class_loader_data()->has_class_mirror_holder()) {
|
||||
// A non-strong hidden class doesn't have its own class loader,
|
||||
// so when handling the java mirror for the class we need to make sure its class
|
||||
// loader data is claimed, this is done by calling do_cld explicitly.
|
||||
// For non-strong hidden classes the call to do_cld is made when the class
|
||||
// loader itself is handled.
|
||||
Devirtualizer::do_cld(closure, klass->class_loader_data());
|
||||
} else {
|
||||
Devirtualizer::do_klass(closure, klass);
|
||||
}
|
||||
} else {
|
||||
// We would like to assert here (as below) that if klass has been null, then
|
||||
// this has been a mirror for a primitive type that we do not need to follow
|
||||
// as they are always strong roots.
|
||||
// However, we might get across a klass that just changed during CMS concurrent
|
||||
// marking if allocation occurred in the old generation.
|
||||
// This is benign here, as we keep alive all CLDs that were loaded during the
|
||||
// CMS concurrent phase in the class loading, i.e. they will be iterated over
|
||||
// and kept alive during remark.
|
||||
// assert(java_lang_Class::is_primitive(obj), "Sanity check");
|
||||
}
|
||||
do_metadata<OopClosureType>(obj, closure);
|
||||
}
|
||||
|
||||
oop_oop_iterate_statics<T>(obj, closure);
|
||||
@@ -121,11 +124,7 @@ void InstanceMirrorKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closu
|
||||
|
||||
if (Devirtualizer::do_metadata(closure)) {
|
||||
if (mr.contains(obj)) {
|
||||
Klass* klass = java_lang_Class::as_Klass(obj);
|
||||
// We'll get null for primitive mirrors.
|
||||
if (klass != nullptr) {
|
||||
Devirtualizer::do_klass(closure, klass);
|
||||
}
|
||||
do_metadata<OopClosureType>(obj, closure);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
|
||||
// TrainingDataLocker is used to guard read/write operations on non-MT-safe data structures.
|
||||
// It supports recursive locking and a read-only mode (in which case no locks are taken).
|
||||
// It is also a part of the TD collection termination protocol (see the "spanshot" field).
|
||||
// It is also a part of the TD collection termination protocol (see the "snapshot" field).
|
||||
class TrainingDataLocker {
|
||||
static volatile bool _snapshot; // If true we're not allocating new training data
|
||||
static int _lock_mode;
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
#if INCLUDE_CDS
|
||||
assert(_lock_mode != 0, "Forgot to call TrainingDataLocker::initialize()");
|
||||
if (_lock_mode > 0) {
|
||||
TrainingData_lock->lock();
|
||||
TrainingData_lock->lock_without_safepoint_check();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -152,6 +152,9 @@ public:
|
||||
_lock_mode = need_data() ? +1 : -1; // if -1, we go lock-free
|
||||
#endif
|
||||
}
|
||||
static void assert_locked_or_snapshotted() {
|
||||
assert(safely_locked() || _snapshot, "use under TrainingDataLocker or after snapshot");
|
||||
}
|
||||
static void assert_locked() {
|
||||
assert(safely_locked(), "use under TrainingDataLocker");
|
||||
}
|
||||
@@ -338,20 +341,24 @@ private:
|
||||
}
|
||||
|
||||
int length() const {
|
||||
TrainingDataLocker::assert_locked_or_snapshotted();
|
||||
return (_deps_dyn != nullptr ? _deps_dyn->length()
|
||||
: _deps != nullptr ? _deps->length()
|
||||
: 0);
|
||||
}
|
||||
E* adr_at(int i) const {
|
||||
TrainingDataLocker::assert_locked_or_snapshotted();
|
||||
return (_deps_dyn != nullptr ? _deps_dyn->adr_at(i)
|
||||
: _deps != nullptr ? _deps->adr_at(i)
|
||||
: nullptr);
|
||||
}
|
||||
E at(int i) const {
|
||||
TrainingDataLocker::assert_locked_or_snapshotted();
|
||||
assert(i >= 0 && i < length(), "oob");
|
||||
return *adr_at(i);
|
||||
}
|
||||
bool append_if_missing(E dep) {
|
||||
TrainingDataLocker::assert_can_add();
|
||||
if (_deps_dyn == nullptr) {
|
||||
_deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(10);
|
||||
_deps_dyn->append(dep);
|
||||
@@ -361,23 +368,27 @@ private:
|
||||
}
|
||||
}
|
||||
bool remove_if_existing(E dep) {
|
||||
TrainingDataLocker::assert_can_add();
|
||||
if (_deps_dyn != nullptr) {
|
||||
return _deps_dyn->remove_if_existing(dep);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void clear() {
|
||||
TrainingDataLocker::assert_can_add();
|
||||
if (_deps_dyn != nullptr) {
|
||||
_deps_dyn->clear();
|
||||
}
|
||||
}
|
||||
void append(E dep) {
|
||||
TrainingDataLocker::assert_can_add();
|
||||
if (_deps_dyn == nullptr) {
|
||||
_deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(10);
|
||||
}
|
||||
_deps_dyn->append(dep);
|
||||
}
|
||||
bool contains(E dep) {
|
||||
TrainingDataLocker::assert_locked();
|
||||
for (int i = 0; i < length(); i++) {
|
||||
if (dep == at(i)) {
|
||||
return true; // found
|
||||
@@ -593,6 +604,7 @@ public:
|
||||
DepList<Record> _data;
|
||||
public:
|
||||
OptionalReturnType find(const Args&... args) {
|
||||
TrainingDataLocker l;
|
||||
ArgumentsType a(args...);
|
||||
for (int i = 0; i < _data.length(); i++) {
|
||||
if (_data.at(i).arguments() == a) {
|
||||
@@ -601,8 +613,11 @@ public:
|
||||
}
|
||||
return OptionalReturnType(false, ReturnType());
|
||||
}
|
||||
bool append_if_missing(const ReturnType& result, const Args&... args) {
|
||||
return _data.append_if_missing(Record(result, ArgumentsType(args...)));
|
||||
void append_if_missing(const ReturnType& result, const Args&... args) {
|
||||
TrainingDataLocker l;
|
||||
if (l.can_add()) {
|
||||
_data.append_if_missing(Record(result, ArgumentsType(args...)));
|
||||
}
|
||||
}
|
||||
#if INCLUDE_CDS
|
||||
void remove_unshareable_info() { _data.remove_unshareable_info(); }
|
||||
|
||||
@@ -2593,6 +2593,8 @@ static bool can_subword_truncate(Node* in, const Type* type) {
|
||||
case Op_ReverseI:
|
||||
case Op_CountLeadingZerosI:
|
||||
case Op_CountTrailingZerosI:
|
||||
case Op_IsFiniteF:
|
||||
case Op_IsFiniteD:
|
||||
case Op_IsInfiniteF:
|
||||
case Op_IsInfiniteD:
|
||||
case Op_ExtractS:
|
||||
|
||||
@@ -996,6 +996,11 @@ void JvmtiClassFileReconstituter::write_u8(u8 x) {
|
||||
|
||||
void JvmtiClassFileReconstituter::copy_bytecodes(const methodHandle& mh,
|
||||
unsigned char* bytecodes) {
|
||||
// We must copy bytecodes only from linked classes.
|
||||
// Being linked guarantees we are not getting bytecodes at
|
||||
// the same time the linking process is rewriting them.
|
||||
guarantee(mh->method_holder()->is_linked(), "Bytecodes must be copied from a linked class");
|
||||
|
||||
// use a BytecodeStream to iterate over the bytecodes. JVM/fast bytecodes
|
||||
// and the breakpoint bytecode are converted to their original bytecodes.
|
||||
|
||||
|
||||
@@ -451,6 +451,18 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {
|
||||
|
||||
InstanceKlass* ik = InstanceKlass::cast(klass);
|
||||
if (ik->get_cached_class_file_bytes() == nullptr) {
|
||||
// Link the class to avoid races with the rewriter. This will call the verifier also
|
||||
// on the class. Linking is also done in VM_RedefineClasses below, but we need
|
||||
// to keep that for other VM_RedefineClasses callers.
|
||||
JavaThread* THREAD = current_thread;
|
||||
ik->link_class(THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// Retransform/JVMTI swallows error messages. Using this class will rerun the verifier in a context
|
||||
// that propagates the VerifyError, if thrown.
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
return JVMTI_ERROR_INVALID_CLASS;
|
||||
}
|
||||
|
||||
// Not cached, we need to reconstitute the class file from the
|
||||
// VM representation. We don't attach the reconstituted class
|
||||
// bytes to the InstanceKlass here because they have not been
|
||||
@@ -3428,7 +3440,8 @@ jvmtiError
|
||||
JvmtiEnv::GetBytecodes(Method* method, jint* bytecode_count_ptr, unsigned char** bytecodes_ptr) {
|
||||
NULL_CHECK(method, JVMTI_ERROR_INVALID_METHODID);
|
||||
|
||||
methodHandle mh(Thread::current(), method);
|
||||
JavaThread* current_thread = JavaThread::current();
|
||||
methodHandle mh(current_thread, method);
|
||||
jint size = (jint)mh->code_size();
|
||||
jvmtiError err = allocate(size, bytecodes_ptr);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
@@ -3437,6 +3450,13 @@ JvmtiEnv::GetBytecodes(Method* method, jint* bytecode_count_ptr, unsigned char**
|
||||
|
||||
(*bytecode_count_ptr) = size;
|
||||
// get byte codes
|
||||
// Make sure the class is verified and rewritten first.
|
||||
JavaThread* THREAD = current_thread;
|
||||
mh->method_holder()->link_class(THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
return JVMTI_ERROR_INVALID_CLASS;
|
||||
}
|
||||
JvmtiClassFileReconstituter::copy_bytecodes(mh, *bytecodes_ptr);
|
||||
|
||||
return JVMTI_ERROR_NONE;
|
||||
|
||||
@@ -593,6 +593,25 @@ int VectorSupport::vop2ideal(jint id, BasicType bt) {
|
||||
break;
|
||||
}
|
||||
|
||||
case VECTOR_OP_TAN: // fall-through
|
||||
case VECTOR_OP_TANH: // fall-through
|
||||
case VECTOR_OP_SIN: // fall-through
|
||||
case VECTOR_OP_SINH: // fall-through
|
||||
case VECTOR_OP_COS: // fall-through
|
||||
case VECTOR_OP_COSH: // fall-through
|
||||
case VECTOR_OP_ASIN: // fall-through
|
||||
case VECTOR_OP_ACOS: // fall-through
|
||||
case VECTOR_OP_ATAN: // fall-through
|
||||
case VECTOR_OP_ATAN2: // fall-through
|
||||
case VECTOR_OP_CBRT: // fall-through
|
||||
case VECTOR_OP_LOG: // fall-through
|
||||
case VECTOR_OP_LOG10: // fall-through
|
||||
case VECTOR_OP_LOG1P: // fall-through
|
||||
case VECTOR_OP_POW: // fall-through
|
||||
case VECTOR_OP_EXP: // fall-through
|
||||
case VECTOR_OP_EXPM1: // fall-through
|
||||
case VECTOR_OP_HYPOT: return 0; // not supported; should be handled in Java code
|
||||
|
||||
default: fatal("unknown op: %d", vop);
|
||||
}
|
||||
return 0; // Unimplemented
|
||||
|
||||
@@ -101,6 +101,25 @@ class VectorSupport : AllStatic {
|
||||
VECTOR_OP_COMPRESS_BITS = 33,
|
||||
VECTOR_OP_EXPAND_BITS = 34,
|
||||
|
||||
VECTOR_OP_TAN = 101,
|
||||
VECTOR_OP_TANH = 102,
|
||||
VECTOR_OP_SIN = 103,
|
||||
VECTOR_OP_SINH = 104,
|
||||
VECTOR_OP_COS = 105,
|
||||
VECTOR_OP_COSH = 106,
|
||||
VECTOR_OP_ASIN = 107,
|
||||
VECTOR_OP_ACOS = 108,
|
||||
VECTOR_OP_ATAN = 109,
|
||||
VECTOR_OP_ATAN2 = 110,
|
||||
VECTOR_OP_CBRT = 111,
|
||||
VECTOR_OP_LOG = 112,
|
||||
VECTOR_OP_LOG10 = 113,
|
||||
VECTOR_OP_LOG1P = 114,
|
||||
VECTOR_OP_POW = 115,
|
||||
VECTOR_OP_EXP = 116,
|
||||
VECTOR_OP_EXPM1 = 117,
|
||||
VECTOR_OP_HYPOT = 118,
|
||||
|
||||
VECTOR_OP_SADD = 119,
|
||||
VECTOR_OP_SSUB = 120,
|
||||
VECTOR_OP_SUADD = 121,
|
||||
|
||||
@@ -259,7 +259,7 @@ void mutex_init() {
|
||||
|
||||
MUTEX_DEFN(CompiledIC_lock , PaddedMutex , nosafepoint); // locks VtableStubs_lock
|
||||
MUTEX_DEFN(MethodCompileQueue_lock , PaddedMonitor, safepoint);
|
||||
MUTEX_DEFL(TrainingData_lock , PaddedMutex , MethodCompileQueue_lock);
|
||||
MUTEX_DEFN(TrainingData_lock , PaddedMutex , nosafepoint);
|
||||
MUTEX_DEFN(TrainingReplayQueue_lock , PaddedMonitor, safepoint);
|
||||
MUTEX_DEFN(CompileStatistics_lock , PaddedMutex , safepoint);
|
||||
MUTEX_DEFN(DirectivesStack_lock , PaddedMutex , nosafepoint);
|
||||
|
||||
@@ -667,6 +667,14 @@
|
||||
static_field(VMRegImpl, regName[0], const char*) \
|
||||
static_field(VMRegImpl, stack0, VMReg) \
|
||||
\
|
||||
/******************************************************************************************/ \
|
||||
/* CI (NOTE: these CI fields are retained in VMStructs for the benefit of external tools, */ \
|
||||
/* to ease their migration to a future alternative.) */ \
|
||||
/******************************************************************************************/ \
|
||||
\
|
||||
nonstatic_field(CompilerThread, _env, ciEnv*) \
|
||||
nonstatic_field(ciEnv, _task, CompileTask*) \
|
||||
\
|
||||
/************/ \
|
||||
/* Monitors */ \
|
||||
/************/ \
|
||||
@@ -1150,6 +1158,12 @@
|
||||
declare_toplevel_type(BasicLock) \
|
||||
declare_toplevel_type(BasicObjectLock) \
|
||||
\
|
||||
/*********************/ \
|
||||
/* CI */ \
|
||||
/*********************/ \
|
||||
\
|
||||
declare_toplevel_type(ciEnv) \
|
||||
\
|
||||
/********************/ \
|
||||
/* -XX flags */ \
|
||||
/********************/ \
|
||||
|
||||
@@ -182,11 +182,11 @@ public final class LocalDate
|
||||
/**
|
||||
* @serial The month-of-year.
|
||||
*/
|
||||
private final byte month;
|
||||
private final short month;
|
||||
/**
|
||||
* @serial The day-of-month.
|
||||
*/
|
||||
private final byte day;
|
||||
private final short day;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@@ -490,8 +490,8 @@ public final class LocalDate
|
||||
*/
|
||||
private LocalDate(int year, int month, int dayOfMonth) {
|
||||
this.year = year;
|
||||
this.month = (byte) month;
|
||||
this.day = (byte) dayOfMonth;
|
||||
this.month = (short) month;
|
||||
this.day = (short) dayOfMonth;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@@ -146,11 +146,11 @@ public final class MonthDay
|
||||
/**
|
||||
* @serial The month-of-year, not null.
|
||||
*/
|
||||
private final byte month;
|
||||
private final int month;
|
||||
/**
|
||||
* @serial The day-of-month.
|
||||
*/
|
||||
private final byte day;
|
||||
private final int day;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@@ -319,8 +319,8 @@ public final class MonthDay
|
||||
* @param dayOfMonth the day-of-month to represent, validated from 1 to 29-31
|
||||
*/
|
||||
private MonthDay(int month, int dayOfMonth) {
|
||||
this.month = (byte) month;
|
||||
this.day = (byte) dayOfMonth;
|
||||
this.month = month;
|
||||
this.day = dayOfMonth;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@@ -153,7 +153,7 @@ public final class YearMonth
|
||||
/**
|
||||
* @serial The month-of-year, not null.
|
||||
*/
|
||||
private final byte month;
|
||||
private final int month;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@@ -306,7 +306,7 @@ public final class YearMonth
|
||||
*/
|
||||
private YearMonth(int year, int month) {
|
||||
this.year = year;
|
||||
this.month = (byte) month;
|
||||
this.month = month;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2019, 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
|
||||
@@ -137,11 +137,11 @@ public final class HijrahDate
|
||||
/**
|
||||
* The month-of-year.
|
||||
*/
|
||||
private final transient byte monthOfYear;
|
||||
private final transient int monthOfYear;
|
||||
/**
|
||||
* The day-of-month.
|
||||
*/
|
||||
private final transient byte dayOfMonth;
|
||||
private final transient int dayOfMonth;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
@@ -273,8 +273,8 @@ public final class HijrahDate
|
||||
|
||||
this.chrono = chrono;
|
||||
this.prolepticYear = prolepticYear;
|
||||
this.monthOfYear = (byte) monthOfYear;
|
||||
this.dayOfMonth = (byte) dayOfMonth;
|
||||
this.monthOfYear = monthOfYear;
|
||||
this.dayOfMonth = dayOfMonth;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,8 +287,8 @@ public final class HijrahDate
|
||||
|
||||
this.chrono = chrono;
|
||||
this.prolepticYear = dateInfo[0];
|
||||
this.monthOfYear = (byte) dateInfo[1];
|
||||
this.dayOfMonth = (byte) dateInfo[2];
|
||||
this.monthOfYear = dateInfo[1];
|
||||
this.dayOfMonth = dateInfo[2];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@@ -32,7 +32,7 @@ formatVersion=3
|
||||
# Version of the currency code information in this class.
|
||||
# It is a serial number that accompanies with each amendment.
|
||||
|
||||
dataVersion=179
|
||||
dataVersion=180
|
||||
|
||||
# List of all valid ISO 4217 currency codes.
|
||||
# To ensure compatibility, do not remove codes.
|
||||
@@ -147,7 +147,7 @@ IO=USD
|
||||
# BRUNEI DARUSSALAM
|
||||
BN=BND
|
||||
# BULGARIA
|
||||
BG=BGN
|
||||
BG=BGN;2025-12-31-22-00-00;EUR
|
||||
# BURKINA FASO
|
||||
BF=XOF
|
||||
# BURUNDI
|
||||
@@ -193,7 +193,7 @@ HR=EUR
|
||||
# CUBA
|
||||
CU=CUP
|
||||
# Curaçao
|
||||
CW=ANG;2025-04-01-04-00-00;XCG
|
||||
CW=XCG
|
||||
# CYPRUS
|
||||
CY=EUR
|
||||
# CZECHIA
|
||||
@@ -510,7 +510,7 @@ SR=SRD
|
||||
# SVALBARD AND JAN MAYEN
|
||||
SJ=NOK
|
||||
# Sint Maarten (Dutch part)
|
||||
SX=ANG;2025-04-01-04-00-00;XCG
|
||||
SX=XCG
|
||||
# ESWATINI
|
||||
SZ=SZL
|
||||
# SWEDEN
|
||||
|
||||
@@ -72,10 +72,6 @@ public class SwingUtilities3 {
|
||||
private static final Object DELEGATE_REPAINT_MANAGER_KEY =
|
||||
new StringBuilder("DelegateRepaintManagerKey");
|
||||
|
||||
private static Color disabledForeground;
|
||||
private static Color acceleratorSelectionForeground;
|
||||
private static Color acceleratorForeground;
|
||||
|
||||
/**
|
||||
* Registers delegate RepaintManager for {@code JComponent}.
|
||||
*/
|
||||
@@ -210,7 +206,10 @@ public class SwingUtilities3 {
|
||||
|
||||
|
||||
public static void paintAccText(Graphics g, MenuItemLayoutHelper lh,
|
||||
MenuItemLayoutHelper.LayoutResult lr) {
|
||||
MenuItemLayoutHelper.LayoutResult lr,
|
||||
Color disabledForeground,
|
||||
Color acceleratorSelectionForeground,
|
||||
Color acceleratorForeground) {
|
||||
if (!lh.getAccText().isEmpty()) {
|
||||
ButtonModel model = lh.getMenuItem().getModel();
|
||||
g.setFont(lh.getAccFontMetrics().getFont());
|
||||
@@ -249,18 +248,6 @@ public class SwingUtilities3 {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setDisabledForeground(Color disabledFg) {
|
||||
disabledForeground = disabledFg;
|
||||
}
|
||||
|
||||
public static void setAcceleratorSelectionForeground(Color acceleratorSelectionFg) {
|
||||
acceleratorSelectionForeground = acceleratorSelectionFg;
|
||||
}
|
||||
|
||||
public static void setAcceleratorForeground(Color acceleratorFg) {
|
||||
acceleratorForeground = acceleratorFg;
|
||||
}
|
||||
|
||||
public static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
|
||||
MenuItemLayoutHelper.LayoutResult lr,
|
||||
Color foreground) {
|
||||
|
||||
@@ -1120,6 +1120,9 @@ class GTKFileChooserUI extends SynthFileChooserUI {
|
||||
if (showFileIcons) {
|
||||
setIcon(getFileChooser().getIcon((File)value));
|
||||
}
|
||||
|
||||
putClientProperty("html.disable", getFileChooser().getClientProperty("html.disable"));
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1137,6 +1140,9 @@ class GTKFileChooserUI extends SynthFileChooserUI {
|
||||
} else {
|
||||
setText(getFileChooser().getName((File)value) + "/");
|
||||
}
|
||||
|
||||
putClientProperty("html.disable", getFileChooser().getClientProperty("html.disable"));
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,11 +716,10 @@ public class BasicMenuItemUI extends MenuItemUI
|
||||
|
||||
private void paintAccText(Graphics g, MenuItemLayoutHelper lh,
|
||||
MenuItemLayoutHelper.LayoutResult lr) {
|
||||
SwingUtilities3.setDisabledForeground(disabledForeground);
|
||||
SwingUtilities3.setAcceleratorSelectionForeground(
|
||||
acceleratorSelectionForeground);
|
||||
SwingUtilities3.setAcceleratorForeground(acceleratorForeground);
|
||||
SwingUtilities3.paintAccText(g, lh, lr);
|
||||
SwingUtilities3.paintAccText(g, lh, lr,
|
||||
disabledForeground,
|
||||
acceleratorSelectionForeground,
|
||||
acceleratorForeground);
|
||||
}
|
||||
|
||||
private void paintText(Graphics g, MenuItemLayoutHelper lh,
|
||||
|
||||
+3
-1
@@ -84,7 +84,9 @@ public final class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI {
|
||||
int defaultTextIconGap) {
|
||||
if (WindowsMenuItemUI.isVistaPainting()) {
|
||||
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
|
||||
arrowIcon, background, foreground, defaultTextIconGap,
|
||||
arrowIcon, background, foreground,
|
||||
disabledForeground, acceleratorSelectionForeground,
|
||||
acceleratorForeground, defaultTextIconGap,
|
||||
menuItem, getPropertyPrefix());
|
||||
return;
|
||||
}
|
||||
|
||||
+12
-39
@@ -67,9 +67,6 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
|
||||
* The instance of {@code PropertyChangeListener}.
|
||||
*/
|
||||
private PropertyChangeListener changeListener;
|
||||
private static Color disabledForeground;
|
||||
private static Color acceleratorSelectionForeground;
|
||||
private static Color acceleratorForeground;
|
||||
|
||||
final WindowsMenuItemUIAccessor accessor =
|
||||
new WindowsMenuItemUIAccessor() {
|
||||
@@ -167,36 +164,6 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
|
||||
changeListener = null;
|
||||
}
|
||||
|
||||
private static void applyInsets(Rectangle rect, Insets insets) {
|
||||
SwingUtilities3.applyInsets(rect, insets);
|
||||
}
|
||||
|
||||
private static void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh,
|
||||
MenuItemLayoutHelper.LayoutResult lr,
|
||||
Color holdc, Color foreground) {
|
||||
SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground);
|
||||
}
|
||||
|
||||
private static void paintIcon(Graphics g, MenuItemLayoutHelper lh,
|
||||
MenuItemLayoutHelper.LayoutResult lr, Color holdc) {
|
||||
SwingUtilities3.paintIcon(g, lh, lr, holdc);
|
||||
}
|
||||
|
||||
private static void paintAccText(Graphics g, MenuItemLayoutHelper lh,
|
||||
MenuItemLayoutHelper.LayoutResult lr) {
|
||||
SwingUtilities3.setDisabledForeground(disabledForeground);
|
||||
SwingUtilities3.setAcceleratorSelectionForeground(
|
||||
acceleratorSelectionForeground);
|
||||
SwingUtilities3.setAcceleratorForeground(acceleratorForeground);
|
||||
SwingUtilities3.paintAccText(g, lh, lr);
|
||||
}
|
||||
|
||||
private static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
|
||||
MenuItemLayoutHelper.LayoutResult lr,
|
||||
Color foreground) {
|
||||
SwingUtilities3.paintArrowIcon(g, lh, lr, foreground);
|
||||
}
|
||||
|
||||
protected void paintMenuItem(Graphics g, JComponent c,
|
||||
Icon checkIcon, Icon arrowIcon,
|
||||
Color background, Color foreground,
|
||||
@@ -204,7 +171,8 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
|
||||
if (WindowsMenuItemUI.isVistaPainting()) {
|
||||
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
|
||||
arrowIcon, background, foreground,
|
||||
defaultTextIconGap, menuItem,
|
||||
disabledForeground, acceleratorSelectionForeground,
|
||||
acceleratorForeground, defaultTextIconGap, menuItem,
|
||||
getPropertyPrefix());
|
||||
return;
|
||||
}
|
||||
@@ -215,6 +183,9 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
|
||||
static void paintMenuItem(WindowsMenuItemUIAccessor accessor, Graphics g,
|
||||
JComponent c, Icon checkIcon, Icon arrowIcon,
|
||||
Color background, Color foreground,
|
||||
Color disabledForeground,
|
||||
Color acceleratorSelectionForeground,
|
||||
Color acceleratorForeground,
|
||||
int defaultTextIconGap, JMenuItem menuItem, String prefix) {
|
||||
// Save original graphics font and color
|
||||
Font holdf = g.getFont();
|
||||
@@ -224,7 +195,7 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
|
||||
g.setFont(mi.getFont());
|
||||
|
||||
Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
|
||||
applyInsets(viewRect, mi.getInsets());
|
||||
SwingUtilities3.applyInsets(viewRect, mi.getInsets());
|
||||
|
||||
String acceleratorDelimiter =
|
||||
UIManager.getString("MenuItem.acceleratorDelimiter");
|
||||
@@ -242,8 +213,8 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
|
||||
MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
|
||||
|
||||
paintBackground(accessor, g, mi, background);
|
||||
paintCheckIcon(g, lh, lr, holdc, foreground);
|
||||
paintIcon(g, lh, lr, holdc);
|
||||
SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground);
|
||||
SwingUtilities3.paintIcon(g, lh, lr, holdc);
|
||||
|
||||
if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) {
|
||||
Rectangle rect = lr.getTextRect();
|
||||
@@ -267,8 +238,10 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
|
||||
rect.x += lh.getAfterCheckIconGap();
|
||||
lr.setAccRect(rect);
|
||||
}
|
||||
paintAccText(g, lh, lr);
|
||||
paintArrowIcon(g, lh, lr, foreground);
|
||||
SwingUtilities3.paintAccText(g, lh, lr, disabledForeground,
|
||||
acceleratorSelectionForeground,
|
||||
acceleratorForeground);
|
||||
SwingUtilities3.paintArrowIcon(g, lh, lr, foreground);
|
||||
|
||||
// Restore original graphics font and color
|
||||
g.setColor(holdc);
|
||||
|
||||
@@ -140,7 +140,8 @@ public final class WindowsMenuUI extends BasicMenuUI {
|
||||
if (WindowsMenuItemUI.isVistaPainting()) {
|
||||
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, arrowIcon,
|
||||
background, foreground,
|
||||
defaultTextIconGap, menuItem,
|
||||
disabledForeground, acceleratorSelectionForeground,
|
||||
acceleratorForeground, defaultTextIconGap, menuItem,
|
||||
getPropertyPrefix());
|
||||
return;
|
||||
}
|
||||
|
||||
+3
-1
@@ -84,7 +84,9 @@ public final class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItem
|
||||
int defaultTextIconGap) {
|
||||
if (WindowsMenuItemUI.isVistaPainting()) {
|
||||
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
|
||||
arrowIcon, background, foreground, defaultTextIconGap,
|
||||
arrowIcon, background, foreground,
|
||||
disabledForeground, acceleratorSelectionForeground,
|
||||
acceleratorForeground, defaultTextIconGap,
|
||||
menuItem, getPropertyPrefix());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2498,32 +2498,22 @@ jint AwtWindow::_GetScreenImOn(void *param)
|
||||
|
||||
jobject self = (jobject)param;
|
||||
|
||||
// It's entirely possible that our native resources have been destroyed
|
||||
// before our java peer - if we're dispose()d, for instance.
|
||||
// Alert caller w/ IllegalComponentStateException.
|
||||
if (self == NULL) {
|
||||
JNU_ThrowByName(env, "java/awt/IllegalComponentStateException",
|
||||
"Peer null in JNI");
|
||||
return 0;
|
||||
}
|
||||
PDATA pData = JNI_GET_PDATA(self);
|
||||
if (pData == NULL) {
|
||||
JNU_ThrowByName(env, "java/awt/IllegalComponentStateException",
|
||||
"Native resources unavailable");
|
||||
env->DeleteGlobalRef(self);
|
||||
return 0;
|
||||
}
|
||||
jint result = -1;
|
||||
AwtWindow* window = NULL;
|
||||
|
||||
jint result = 0;
|
||||
AwtWindow *w = (AwtWindow *)pData;
|
||||
if (::IsWindow(w->GetHWnd()))
|
||||
// Our native resources may have been destroyed before the Java peer,
|
||||
// e.g., if dispose() was called. In that case, return the default screen.
|
||||
PDATA pData;
|
||||
JNI_CHECK_PEER_GOTO(self, ret);
|
||||
window = (AwtWindow *)pData;
|
||||
if (::IsWindow(window->GetHWnd()))
|
||||
{
|
||||
result = (jint)w->GetScreenImOn();
|
||||
result = (jint)window->GetScreenImOn();
|
||||
}
|
||||
|
||||
ret:
|
||||
env->DeleteGlobalRef(self);
|
||||
|
||||
return result;
|
||||
return (result != -1) ? result : AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
|
||||
}
|
||||
|
||||
void AwtWindow::_SetFocusableWindow(void *param)
|
||||
|
||||
@@ -420,7 +420,8 @@ public class Main {
|
||||
if (fname != null) {
|
||||
file = new File(fname);
|
||||
} else {
|
||||
file = createTemporaryFile("tmpJar", ".jar");
|
||||
tmpFile = createTemporaryFile("tmpJar", ".jar");
|
||||
file = tmpFile;
|
||||
try (InputStream in = new FileInputStream(FileDescriptor.in);
|
||||
OutputStream os = Files.newOutputStream(file.toPath())) {
|
||||
in.transferTo(os);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 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
|
||||
@@ -256,6 +256,16 @@ bool needRestartLauncher(AppLauncher& appLauncher, CfgFile& cfgFile) {
|
||||
}
|
||||
|
||||
|
||||
void enableConsoleCtrlHandler(bool enable) {
|
||||
if (!SetConsoleCtrlHandler(NULL, enable ? FALSE : TRUE)) {
|
||||
JP_THROW(SysError(tstrings::any() << "SetConsoleCtrlHandler(NULL, "
|
||||
<< (enable ? "FALSE" : "TRUE")
|
||||
<< ") failed",
|
||||
SetConsoleCtrlHandler));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void launchApp() {
|
||||
// [RT-31061] otherwise UI can be left in back of other windows.
|
||||
::AllowSetForegroundWindow(ASFW_ANY);
|
||||
@@ -310,6 +320,19 @@ void launchApp() {
|
||||
exec.arg(arg);
|
||||
});
|
||||
|
||||
exec.afterProcessCreated([&](HANDLE pid) {
|
||||
//
|
||||
// Ignore Ctrl+C in the current process.
|
||||
// This will prevent child process termination without allowing
|
||||
// it to handle Ctrl+C events.
|
||||
//
|
||||
// Disable the default Ctrl+C handler *after* the child process
|
||||
// has been created as it is inheritable and we want the child
|
||||
// process to have the default handler.
|
||||
//
|
||||
enableConsoleCtrlHandler(false);
|
||||
});
|
||||
|
||||
DWORD exitCode = RunExecutorWithMsgLoop::apply(exec);
|
||||
|
||||
exit(exitCode);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 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
|
||||
@@ -161,6 +161,10 @@ UniqueHandle Executor::startProcess(UniqueHandle* threadHandle) const {
|
||||
}
|
||||
}
|
||||
|
||||
if (afterProcessCreatedCallback) {
|
||||
afterProcessCreatedCallback(processInfo.hProcess);
|
||||
}
|
||||
|
||||
// Return process handle.
|
||||
return UniqueHandle(processInfo.hProcess);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 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
|
||||
@@ -26,6 +26,8 @@
|
||||
#ifndef EXECUTOR_H
|
||||
#define EXECUTOR_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "tstrings.h"
|
||||
#include "UniqueHandle.h"
|
||||
|
||||
@@ -97,6 +99,14 @@ public:
|
||||
*/
|
||||
int execAndWaitForExit() const;
|
||||
|
||||
/**
|
||||
* Call provided function after the process hass been created.
|
||||
*/
|
||||
Executor& afterProcessCreated(const std::function<void(HANDLE)>& v) {
|
||||
afterProcessCreatedCallback = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
UniqueHandle startProcess(UniqueHandle* threadHandle=0) const;
|
||||
|
||||
@@ -106,6 +116,7 @@ private:
|
||||
HANDLE jobHandle;
|
||||
tstring_array argsArray;
|
||||
std::wstring appPath;
|
||||
std::function<void(HANDLE)> afterProcessCreatedCallback;
|
||||
};
|
||||
|
||||
#endif // #ifndef EXECUTOR_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@@ -195,7 +195,7 @@ static int get_jvmticks(ticks *pticks) {
|
||||
uint64_t userTicks;
|
||||
uint64_t systemTicks;
|
||||
|
||||
if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) < 0) {
|
||||
if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) != 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
*/
|
||||
|
||||
#include "jvm.h"
|
||||
#include "unittest.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/flags/jvmFlag.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
@@ -30,6 +29,8 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "unittest.hpp"
|
||||
|
||||
class ArgumentsTest : public ::testing::Test {
|
||||
public:
|
||||
static intx parse_xss_inner_annotated(const char* str, jint expected_err, const char* file, int line_number);
|
||||
@@ -57,7 +58,7 @@ public:
|
||||
|
||||
TEST_F(ArgumentsTest, atojulong) {
|
||||
char ullong_max[32];
|
||||
int ret = jio_snprintf(ullong_max, sizeof(ullong_max), JULONG_FORMAT, ULLONG_MAX);
|
||||
int ret = jio_snprintf(ullong_max, sizeof(ullong_max), "%llu", ULLONG_MAX);
|
||||
ASSERT_NE(-1, ret);
|
||||
|
||||
julong value;
|
||||
|
||||
@@ -79,6 +79,8 @@ requires.properties= \
|
||||
vm.rtm.cpu \
|
||||
vm.rtm.compiler \
|
||||
vm.cds \
|
||||
vm.cds.default.archive.available \
|
||||
vm.cds.nocoops.archive.available \
|
||||
vm.cds.custom.loaders \
|
||||
vm.cds.supports.aot.class.linking \
|
||||
vm.cds.supports.aot.code.caching \
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package compiler.vectorapi;
|
||||
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
import jdk.incubator.vector.VectorOperators;
|
||||
import jdk.incubator.vector.VectorSpecies;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8367333
|
||||
* @requires vm.compiler2.enabled
|
||||
* @modules jdk.incubator.vector
|
||||
* @library /test/lib
|
||||
*
|
||||
* @run main/othervm -Xbatch -XX:-TieredCompilation
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+StressIncrementalInlining
|
||||
* -XX:CompileCommand=quiet
|
||||
* -XX:CompileCommand=compileonly,compiler.vectorapi.TestVectorMathLib::test*
|
||||
* compiler.vectorapi.TestVectorMathLib
|
||||
*/
|
||||
|
||||
public class TestVectorMathLib {
|
||||
private static final VectorSpecies SPECIES = FloatVector.SPECIES_PREFERRED;
|
||||
|
||||
static FloatVector testTAN(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.TAN);
|
||||
}
|
||||
static FloatVector testTANH(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.TANH);
|
||||
}
|
||||
static FloatVector testSIN(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.SIN);
|
||||
}
|
||||
static FloatVector testSINH(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.SINH);
|
||||
}
|
||||
static FloatVector testCOS(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.COS);
|
||||
}
|
||||
static FloatVector testCOSH(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.COSH);
|
||||
}
|
||||
static FloatVector testASIN(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.ASIN);
|
||||
}
|
||||
static FloatVector testACOS(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.ACOS);
|
||||
}
|
||||
static FloatVector testATAN(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.ATAN);
|
||||
}
|
||||
static FloatVector testATAN2(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.ATAN2, fv);
|
||||
}
|
||||
static FloatVector testCBRT(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.CBRT);
|
||||
}
|
||||
static FloatVector testLOG(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.LOG);
|
||||
}
|
||||
static FloatVector testLOG10(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.LOG10);
|
||||
}
|
||||
static FloatVector testLOG1P(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.LOG1P);
|
||||
}
|
||||
static FloatVector testPOW(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.POW, fv);
|
||||
}
|
||||
static FloatVector testEXP(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.EXP);
|
||||
}
|
||||
static FloatVector testEXPM1(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.EXPM1);
|
||||
}
|
||||
static FloatVector testHYPOT(FloatVector fv) {
|
||||
return fv.lanewise(VectorOperators.HYPOT, fv);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
FloatVector z = FloatVector.zero(SPECIES);
|
||||
for (int i = 0; i < 20_000; i++) {
|
||||
z.neg(); // unary
|
||||
z.add(z); // binary
|
||||
|
||||
testTAN(z);
|
||||
testTANH(z);
|
||||
testSIN(z);
|
||||
testSINH(z);
|
||||
testCOS(z);
|
||||
testCOSH(z);
|
||||
testASIN(z);
|
||||
testACOS(z);
|
||||
testATAN(z);
|
||||
testATAN2(z);
|
||||
testCBRT(z);
|
||||
testLOG(z);
|
||||
testLOG10(z);
|
||||
testLOG1P(z);
|
||||
testPOW(z);
|
||||
testEXP(z);
|
||||
testEXPM1(z);
|
||||
testHYPOT(z);
|
||||
}
|
||||
|
||||
System.out.println("TEST PASSED");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=G1
|
||||
* @summary Run tests with G1
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Platform
|
||||
* @requires os.family == "linux"
|
||||
* @requires vm.gc.G1
|
||||
* @run driver TestTransparentHugePagesHeap G1
|
||||
*/
|
||||
/*
|
||||
* @test id=Parallel
|
||||
* @summary Run tests with Parallel
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Platform
|
||||
* @requires os.family == "linux"
|
||||
* @requires vm.gc.Parallel
|
||||
* @run driver TestTransparentHugePagesHeap Parallel
|
||||
*/
|
||||
/*
|
||||
* @test id=Serial
|
||||
* @summary Run tests with Serial
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Platform
|
||||
* @requires os.family == "linux"
|
||||
* @requires vm.gc.Serial
|
||||
* @run driver TestTransparentHugePagesHeap Serial
|
||||
*/
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.Scanner;
|
||||
|
||||
import jdk.test.lib.os.linux.HugePageConfiguration;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
import jtreg.SkippedException;
|
||||
|
||||
// We verify that the heap can be backed by THP by looking at the
|
||||
// THPeligible field for the heap section in /proc/self/smaps. This
|
||||
// field indicates if a mapping can use THP.
|
||||
// THP mode 'always': this field is 1 whenever huge pages can be used
|
||||
// THP mode 'madvise': this field is 1 if the mapping has been madvised
|
||||
// as MADV_HUGEPAGE. In the JVM that should happen when the flag
|
||||
// -XX:+UseTransparentHugePages is specified.
|
||||
//
|
||||
// Note: we don't verify if the heap is backed by huge pages because we
|
||||
// can't know if the underlying system have any available.
|
||||
public class TestTransparentHugePagesHeap {
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
// To be able to detect large page use (esp. THP) somewhat reliably, we
|
||||
// need at least kernel 3.8 to get the "VmFlags" tag in smaps.
|
||||
// (Note: its still good we started the VM at least since this serves as a nice
|
||||
// test for all manners of large page options).
|
||||
if (Platform.getOsVersionMajor() < 3 ||
|
||||
(Platform.getOsVersionMajor() == 3 && Platform.getOsVersionMinor() < 8)) {
|
||||
throw new SkippedException("Kernel older than 3.8 - skipping this test.");
|
||||
}
|
||||
|
||||
final HugePageConfiguration hugePageConfiguration = HugePageConfiguration.readFromOS();
|
||||
if (!hugePageConfiguration.supportsTHP()) {
|
||||
throw new SkippedException("THP is turned off");
|
||||
}
|
||||
|
||||
OutputAnalyzer oa = ProcessTools.executeTestJava("-XX:+Use" + args[0] + "GC", "-Xmx128m", "-Xms128m", "-Xlog:pagesize:thp-%p.log", "-XX:+UseTransparentHugePages", VerifyTHPEnabledForHeap.class.getName());
|
||||
oa.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
class VerifyTHPEnabledForHeap {
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
// Extract the heap start from pagesize logging
|
||||
BigInteger heapStart = extractHeapStartFromLog();
|
||||
|
||||
Path smaps = makeSmapsCopy();
|
||||
|
||||
final Pattern addressRangePattern = Pattern.compile("([0-9a-f]*?)-([0-9a-f]*?) .*");
|
||||
final Pattern thpEligiblePattern = Pattern.compile("THPeligible:\\s+(\\d)\\s*");
|
||||
|
||||
Scanner smapsFile = new Scanner(smaps);
|
||||
while (smapsFile.hasNextLine()) {
|
||||
Matcher addressRangeMatcher = addressRangePattern.matcher(smapsFile.nextLine());
|
||||
if (!addressRangeMatcher.matches()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found an address range line in the smaps file
|
||||
|
||||
BigInteger addressStart = new BigInteger(addressRangeMatcher.group(1), 16);
|
||||
BigInteger addressEnd = new BigInteger(addressRangeMatcher.group(2), 16);
|
||||
|
||||
// Linux sometimes merges adjacent VMAs so we can't search for a range that
|
||||
// exactly matches the heap range. Instead we look for the first range that
|
||||
// contains the start of the heap and verify that that range is THP eligible.
|
||||
|
||||
if (addressStart.compareTo(heapStart) > 0 || heapStart.compareTo(addressEnd) >= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found a range that contains the start of the heap, verify that it is THP eligible.
|
||||
|
||||
while (smapsFile.hasNextLine()) {
|
||||
Matcher m = thpEligiblePattern.matcher(smapsFile.nextLine());
|
||||
if (!m.matches()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found the THPeligible line
|
||||
|
||||
if (m.group(1).equals("1")) {
|
||||
// Success - THPeligible is 1, heap can be backed by huge pages
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("The address range 0x" + addressStart.toString(16)
|
||||
+ "-0x" + addressEnd.toString(16)
|
||||
+ " that contains the heap start" + heapStart
|
||||
+ " is not THPeligible");
|
||||
}
|
||||
|
||||
throw new RuntimeException("Couldn't find THPeligible in the smaps file");
|
||||
}
|
||||
|
||||
throw new RuntimeException("Could not find an address range containing the heap start " + heapStart + " in the smaps file");
|
||||
}
|
||||
|
||||
private static BigInteger extractHeapStartFromLog() throws Exception {
|
||||
// [0.041s][info][pagesize] Heap: min=128M max=128M base=0x0000ffff5c600000 size=128M page_size=2M
|
||||
final Pattern heapAddress = Pattern.compile(".* Heap: .*base=0x([0-9A-Fa-f]*).*");
|
||||
|
||||
Scanner logFile = new Scanner(Paths.get("thp-" + ProcessHandle.current().pid() + ".log"));
|
||||
while (logFile.hasNextLine()) {
|
||||
String line = logFile.nextLine();
|
||||
|
||||
Matcher m = heapAddress.matcher(line);
|
||||
if (m.matches()) {
|
||||
return new BigInteger(m.group(1), 16);
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Failed to find heap start");
|
||||
}
|
||||
|
||||
private static Path makeSmapsCopy() throws Exception {
|
||||
Path src = Paths.get("/proc/self/smaps");
|
||||
Path dest = Paths.get("smaps-copy-" + ProcessHandle.current().pid() + ".txt");
|
||||
Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,14 @@
|
||||
|
||||
package gc.z;
|
||||
|
||||
/*
|
||||
* @test id=Normal
|
||||
* @requires vm.gc.Z & vm.debug
|
||||
* @summary Test ZGC graceful failure when a commit fails
|
||||
* @library / /test/lib
|
||||
* @run driver gc.z.TestCommitFailure
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=ZFakeNUMA
|
||||
* @requires vm.gc.Z & vm.debug
|
||||
|
||||
@@ -108,7 +108,16 @@ public class TestUncommit {
|
||||
throw new Exception("Uncommitted too fast");
|
||||
}
|
||||
|
||||
// In typical conditions (system not over-provisioned or slow),
|
||||
// uncommitting is expected to complete within 3 * ZUncommitDelay after
|
||||
// the last commit. To accommodate less ideal environments, only
|
||||
// durations exceeding 5 * ZUncommitDelay are flagged as errors.
|
||||
|
||||
if (actualDelay > delay * 3) {
|
||||
log(" *** Uncommit slower than expected. ***");
|
||||
}
|
||||
|
||||
if (actualDelay > delay * 5) {
|
||||
throw new Exception("Uncommitted too slow");
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -28,6 +28,7 @@
|
||||
* @requires vm.bits == 64 & !vm.graal.enabled & vm.debug == true
|
||||
* @requires vm.flagless
|
||||
* @requires vm.cds
|
||||
* @requires vm.cds.default.archive.available
|
||||
* @requires (os.family != "windows") & (os.family != "aix")
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
* jdk.internal.jvmstat/sun.jvmstat.monitor
|
||||
* @run driver CreateCoredumpOnCrash
|
||||
* @requires vm.flagless
|
||||
* @requires !vm.asan
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
* @test id=nocoops_nocoh
|
||||
* @summary Test Loading of default archives in all configurations
|
||||
* @requires vm.cds
|
||||
* @requires vm.cds.default.archive.available
|
||||
* @requires vm.cds.write.archived.java.heap
|
||||
* @requires vm.bits == 64
|
||||
* @library /test/lib
|
||||
@@ -38,6 +39,7 @@
|
||||
* @test id=nocoops_coh
|
||||
* @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh)
|
||||
* @requires vm.cds
|
||||
* @requires vm.cds.default.archive.available
|
||||
* @requires vm.cds.write.archived.java.heap
|
||||
* @requires vm.bits == 64
|
||||
* @library /test/lib
|
||||
@@ -50,6 +52,7 @@
|
||||
* @test id=coops_nocoh
|
||||
* @summary Test Loading of default archives in all configurations
|
||||
* @requires vm.cds
|
||||
* @requires vm.cds.default.archive.available
|
||||
* @requires vm.cds.write.archived.java.heap
|
||||
* @requires vm.bits == 64
|
||||
* @library /test/lib
|
||||
@@ -62,6 +65,7 @@
|
||||
* @test id=coops_coh
|
||||
* @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh)
|
||||
* @requires vm.cds
|
||||
* @requires vm.cds.default.archive.available
|
||||
* @requires vm.cds.write.archived.java.heap
|
||||
* @requires vm.bits == 64
|
||||
* @library /test/lib
|
||||
@@ -90,8 +94,8 @@ public class TestDefaultArchiveLoading {
|
||||
"server", archiveName(archiveSuffix));
|
||||
}
|
||||
|
||||
private static boolean isCOHArchiveAvailable(char coops, char coh,
|
||||
String archiveSuffix) throws Exception {
|
||||
private static boolean isArchiveAvailable(char coops, char coh,
|
||||
String archiveSuffix) throws Exception {
|
||||
Path archive= archivePath(archiveSuffix);
|
||||
return Files.exists(archive);
|
||||
}
|
||||
@@ -109,12 +113,16 @@ public class TestDefaultArchiveLoading {
|
||||
case "nocoops_nocoh":
|
||||
coh = coops = '-';
|
||||
archiveSuffix = "_nocoops";
|
||||
if (!isArchiveAvailable(coops, coh, archiveSuffix)) {
|
||||
throw new SkippedException("Skipping test due to " +
|
||||
archivePath(archiveSuffix).toString() + " not available");
|
||||
}
|
||||
break;
|
||||
case "nocoops_coh":
|
||||
coops = '-';
|
||||
coh = '+';
|
||||
archiveSuffix = "_nocoops_coh";
|
||||
if (!isCOHArchiveAvailable(coops, coh, archiveSuffix)) {
|
||||
if (!isArchiveAvailable(coops, coh, archiveSuffix)) {
|
||||
throw new SkippedException("Skipping test due to " +
|
||||
archivePath(archiveSuffix).toString() + " not available");
|
||||
}
|
||||
@@ -123,11 +131,15 @@ public class TestDefaultArchiveLoading {
|
||||
coops = '+';
|
||||
coh = '-';
|
||||
archiveSuffix = "";
|
||||
if (!isArchiveAvailable(coops, coh, archiveSuffix)) {
|
||||
throw new SkippedException("Skipping test due to " +
|
||||
archivePath(archiveSuffix).toString() + " not available");
|
||||
}
|
||||
break;
|
||||
case "coops_coh":
|
||||
coh = coops = '+';
|
||||
archiveSuffix = "_coh";
|
||||
if (!isCOHArchiveAvailable(coops, coh, archiveSuffix)) {
|
||||
if (!isArchiveAvailable(coops, coh, archiveSuffix)) {
|
||||
throw new SkippedException("Skipping test due to " +
|
||||
archivePath(archiveSuffix).toString() + " not available");
|
||||
}
|
||||
|
||||
@@ -67,6 +67,8 @@ public class ArchiveRelocationTest {
|
||||
String logArg = "-Xlog:cds=debug,cds+reloc=debug,aot+heap";
|
||||
String unlockArg = "-XX:+UnlockDiagnosticVMOptions";
|
||||
String nmtArg = "-XX:NativeMemoryTracking=detail";
|
||||
String relocMsg1 = "ArchiveRelocationMode == 1: always map archive(s) at an alternative address";
|
||||
String relocMsg2 = "Try to map archive(s) at an alternative address";
|
||||
|
||||
OutputAnalyzer out = TestCommon.dump(appJar,
|
||||
TestCommon.list(mainClass),
|
||||
@@ -76,8 +78,10 @@ public class ArchiveRelocationTest {
|
||||
TestCommon.run("-cp", appJar, unlockArg, runRelocArg, logArg, mainClass)
|
||||
.assertNormalExit(output -> {
|
||||
if (run_reloc) {
|
||||
output.shouldContain("ArchiveRelocationMode == 1: always map archive(s) at an alternative address")
|
||||
.shouldContain("Try to map archive(s) at an alternative address");
|
||||
if (!output.contains(relocMsg1) && !output.contains(relocMsg2)) {
|
||||
throw new RuntimeException("Relocation messages \"" + relocMsg1 +
|
||||
"\" and \"" + relocMsg2 + "\" are missing from the output");
|
||||
}
|
||||
} else {
|
||||
output.shouldContain("ArchiveRelocationMode: 0");
|
||||
}
|
||||
|
||||
@@ -120,9 +120,9 @@ public class LotsOfSyntheticClasses {
|
||||
OutputAnalyzer output = TestCommon.createArchive(
|
||||
APP_JAR.toString(),
|
||||
listAppClasses(),
|
||||
MAIN_CLASS_NAME,
|
||||
// Verification for lots of classes slows down the test.
|
||||
"-XX:+IgnoreUnrecognizedVMOptions",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:-VerifyDependencies",
|
||||
"-XX:-VerifyBeforeExit"
|
||||
);
|
||||
@@ -134,6 +134,7 @@ public class LotsOfSyntheticClasses {
|
||||
TestCommon.run(
|
||||
// Verification for lots of classes slows down the test.
|
||||
"-XX:+IgnoreUnrecognizedVMOptions",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:-VerifyDependencies",
|
||||
"-XX:-VerifyBeforeExit",
|
||||
"-cp", APP_JAR.toString(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
@@ -427,8 +427,6 @@ public class TestCommon extends CDSTestUtils {
|
||||
cmd.add(opts.appJar);
|
||||
}
|
||||
|
||||
CDSTestUtils.addVerifyArchivedFields(cmd);
|
||||
|
||||
for (String s : opts.suffix) cmd.add(s);
|
||||
|
||||
if (RUN_WITH_JFR) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 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,6 +28,7 @@
|
||||
* @summary test dynamic dump meanwhile output loaded class list
|
||||
* @bug 8279009 8275084
|
||||
* @requires vm.cds
|
||||
* @requires vm.cds.default.archive.available
|
||||
* @requires vm.cds.custom.loaders
|
||||
* @requires vm.flagless
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
|
||||
|
||||
@@ -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
|
||||
@@ -28,6 +28,7 @@
|
||||
* @summary Transforming an interface of an archived lambda proxy class should not
|
||||
* crash the VM. The lambda proxy class should be regenerated during runtime.
|
||||
* @requires vm.cds
|
||||
* @requires vm.cds.default.archive.available
|
||||
* @requires vm.jvmti
|
||||
* @requires vm.flagless
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
|
||||
|
||||
@@ -98,11 +98,8 @@ public class ExcludedClasses {
|
||||
|
||||
@Override
|
||||
public void checkExecution(OutputAnalyzer out, RunMode runMode) {
|
||||
if (runMode == RunMode.TRAINING) {
|
||||
out.shouldMatch("aot,resolve.*reverted field.*TestApp.Foo => TestApp.Foo.ShouldBeExcluded.f:I");
|
||||
} else if (runMode == RunMode.ASSEMBLY) {
|
||||
if (runMode == RunMode.ASSEMBLY) {
|
||||
out.shouldNotMatch("aot,resolve.*archived field.*TestApp.Foo => TestApp.Foo.ShouldBeExcluded.f:I");
|
||||
out.shouldMatch("aot,resolve.*archived method.*TestApp.Foo java/lang/Integer.intValue:[(][)]I => java/lang/Integer");
|
||||
} else if (runMode == RunMode.PRODUCTION) {
|
||||
out.shouldContain("check_verification_constraint: TestApp$Foo$Taz: TestApp$Foo$ShouldBeExcludedChild must be subclass of TestApp$Foo$ShouldBeExcluded");
|
||||
out.shouldContain("jdk.jfr.Event source: jrt:/jdk.jfr");
|
||||
|
||||
@@ -257,6 +257,16 @@ public class AOTFlags {
|
||||
out.shouldContain("AOTCache creation is complete: hello.aot");
|
||||
out.shouldMatch("Picked up JAVA_TOOL_OPTIONS:.* -Dmy.prop=My' 'string' '-Xshare:off' 'here");
|
||||
out.shouldHaveExitValue(0);
|
||||
|
||||
// Training run with -XX:+PrintTieredEvents (see JDK-8362530).
|
||||
printTestCase("Training run with -XX:+PrintTieredEvents");
|
||||
pb = ProcessTools.createLimitedTestJavaProcessBuilder(
|
||||
"-XX:AOTMode=record",
|
||||
"-XX:+PrintTieredEvents",
|
||||
"-XX:AOTConfiguration=" + aotConfigFile,
|
||||
"-cp", appJar, helloClass);
|
||||
out = CDSTestUtils.executeAndLog(pb, "train-with-tiered-events");
|
||||
out.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
static void negativeTests() throws Exception {
|
||||
|
||||
+1
@@ -27,6 +27,7 @@
|
||||
* @summary Test -XX:+AutoCreateSharedArchive on a copied JDK without default shared archive
|
||||
* @bug 8261455
|
||||
* @requires vm.cds
|
||||
* @requires vm.cds.default.archive.available
|
||||
* @requires vm.flagless
|
||||
* @comment This test doesn't work on Windows because it depends on symlinks
|
||||
* @requires os.family != "windows"
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 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
|
||||
@@ -55,6 +55,7 @@
|
||||
/**
|
||||
* @test id=custom-cl-zgc
|
||||
* @requires vm.cds.custom.loaders
|
||||
* @requires vm.cds.nocoops.archive.available
|
||||
* @requires vm.gc.Z
|
||||
* @summary Test dumptime_table entries are removed with zgc eager class unloading
|
||||
* @bug 8274935
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, Google and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -47,12 +47,36 @@ extern "C" {
|
||||
|
||||
#endif
|
||||
|
||||
// JVMTI_ERROR_WRONG_PHASE guard
|
||||
static jrawMonitorID event_mon = NULL;
|
||||
static int is_vm_dead = 0;
|
||||
|
||||
void lock(jvmtiEnv *jvmti, JNIEnv *jni) {
|
||||
jvmtiError err = (*jvmti)->RawMonitorEnter(jvmti, event_mon);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
JNI_ENV_PTR(jni)->FatalError(JNI_ENV_ARGS2(jni, "RawMonitorEnter failed"));
|
||||
}
|
||||
}
|
||||
|
||||
void unlock(jvmtiEnv *jvmti, JNIEnv *jni) {
|
||||
jvmtiError err = (*jvmti)->RawMonitorExit(jvmti, event_mon);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
JNI_ENV_PTR(jni)->FatalError(JNI_ENV_ARGS2(jni, "RawMonitorExit failed"));
|
||||
}
|
||||
}
|
||||
|
||||
extern JNIEXPORT void JNICALL VMObjectAlloc(jvmtiEnv *jvmti,
|
||||
JNIEnv* jni,
|
||||
jthread thread,
|
||||
jobject object,
|
||||
jclass klass,
|
||||
jlong size) {
|
||||
lock(jvmti, jni);
|
||||
if (is_vm_dead) {
|
||||
unlock(jvmti, jni);
|
||||
return;
|
||||
}
|
||||
|
||||
char *signature = NULL;
|
||||
jvmtiError error = (*jvmti)->GetClassSignature(jvmti, klass, &signature, NULL);
|
||||
|
||||
@@ -78,25 +102,40 @@ extern JNIEXPORT void JNICALL VMObjectAlloc(jvmtiEnv *jvmti,
|
||||
JNI_ENV_ARGS2(jni, "Failed during the CallObjectMethod call"));
|
||||
}
|
||||
}
|
||||
unlock(jvmti, jni);
|
||||
}
|
||||
|
||||
extern JNIEXPORT void JNICALL OnVMInit(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread) {
|
||||
(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL);
|
||||
}
|
||||
|
||||
extern JNIEXPORT void JNICALL OnVMDeath(jvmtiEnv *jvmti, JNIEnv *jni) {
|
||||
lock(jvmti, jni);
|
||||
is_vm_dead = 1;
|
||||
unlock(jvmti, jni);
|
||||
}
|
||||
|
||||
extern JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options,
|
||||
void *reserved) {
|
||||
jvmtiEnv *jvmti;
|
||||
jvmtiEventCallbacks callbacks;
|
||||
jvmtiCapabilities caps;
|
||||
jvmtiError err;
|
||||
|
||||
if ((*jvm)->GetEnv(jvm, (void **) (&jvmti), JVMTI_VERSION) != JNI_OK) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
err = (*jvmti)->CreateRawMonitor(jvmti, "Event Monitor", &event_mon);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
printf("CreateRawMonitor failed: %d\n", err);
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.VMObjectAlloc = &VMObjectAlloc;
|
||||
callbacks.VMInit = &OnVMInit;
|
||||
callbacks.VMDeath = &OnVMDeath;
|
||||
|
||||
memset(&caps, 0, sizeof(caps));
|
||||
caps.can_generate_vm_object_alloc_events = 1;
|
||||
@@ -104,6 +143,7 @@ extern JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options,
|
||||
|
||||
(*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(jvmtiEventCallbacks));
|
||||
(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
|
||||
(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,9 +58,12 @@ public class Stresser implements ExecutionController {
|
||||
private String name;
|
||||
private long maxIterations;
|
||||
private long iterations;
|
||||
|
||||
// In nanoseconds
|
||||
private long startTime;
|
||||
private long finishTime;
|
||||
private long currentTime;
|
||||
private long stressTime;
|
||||
|
||||
private PrintStream defaultOutput = System.out;
|
||||
|
||||
/*
|
||||
@@ -179,15 +182,15 @@ public class Stresser implements ExecutionController {
|
||||
*/
|
||||
public void printExecutionInfo(PrintStream out) {
|
||||
println(out, "Completed iterations: " + iterations);
|
||||
println(out, "Execution time: " + (currentTime - startTime) + " seconds");
|
||||
println(out, "Execution time: " + (currentTime - startTime) / 1_000_000_000.0 + " seconds");
|
||||
if (!finished) {
|
||||
println(out, "Execution is not finished yet");
|
||||
} else if (forceFinish) {
|
||||
println(out, "Execution was forced to finish");
|
||||
} else if (maxIterations != 0 && iterations >= maxIterations) {
|
||||
println(out, "Execution finished because number of iterations was exceeded: " + iterations + " >= " + maxIterations);
|
||||
} else if (finishTime != 0 && currentTime >= finishTime) {
|
||||
println(out, "Execution finished because time was exceeded: " + (currentTime - startTime) + " >= " + (finishTime - startTime));
|
||||
} else if (stressTime != 0 && (currentTime - startTime) >= stressTime) {
|
||||
println(out, "Execution finished because time has exceeded stress time: " + stressTime / 1_000_000_000 + " seconds");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,13 +211,8 @@ public class Stresser implements ExecutionController {
|
||||
public void start(long stdIterations) {
|
||||
maxIterations = stdIterations * options.getIterationsFactor();
|
||||
iterations = 0;
|
||||
long stressTime = options.getTime();
|
||||
startTime = System.currentTimeMillis();
|
||||
if (stressTime == 0) {
|
||||
finishTime = 0;
|
||||
} else {
|
||||
finishTime = startTime + stressTime * 1000;
|
||||
}
|
||||
stressTime = options.getTime() * 1_000_000_000;
|
||||
startTime = System.nanoTime();
|
||||
finished = false;
|
||||
forceFinish = false;
|
||||
if (options.isDebugEnabled()) {
|
||||
@@ -232,7 +230,7 @@ public class Stresser implements ExecutionController {
|
||||
* finally {} block.
|
||||
*/
|
||||
public void finish() {
|
||||
currentTime = System.currentTimeMillis();
|
||||
currentTime = System.nanoTime();
|
||||
finished = true;
|
||||
if (options.isDebugEnabled()) {
|
||||
printExecutionInfo(defaultOutput);
|
||||
@@ -255,10 +253,12 @@ public class Stresser implements ExecutionController {
|
||||
*/
|
||||
public boolean iteration() {
|
||||
++iterations;
|
||||
boolean result = continueExecution();
|
||||
// Call print at the end to show the most up-to-date info.
|
||||
if (options.isDebugDetailed()) {
|
||||
printExecutionInfo(defaultOutput);
|
||||
}
|
||||
return continueExecution();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,14 +267,14 @@ public class Stresser implements ExecutionController {
|
||||
* @return true if execution needs to continue
|
||||
*/
|
||||
public boolean continueExecution() {
|
||||
currentTime = System.currentTimeMillis();
|
||||
currentTime = System.nanoTime();
|
||||
if (startTime == 0) {
|
||||
throw new TestBug("Stresser is not started.");
|
||||
}
|
||||
return !forceFinish
|
||||
&& !finished
|
||||
&& (maxIterations == 0 || iterations < maxIterations)
|
||||
&& (finishTime == 0 || currentTime < finishTime);
|
||||
&& (stressTime == 0 || (currentTime - startTime) < stressTime);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,7 +309,7 @@ public class Stresser implements ExecutionController {
|
||||
* @return time
|
||||
*/
|
||||
public long getExecutionTime() {
|
||||
return System.currentTimeMillis() - startTime;
|
||||
return (System.nanoTime() - startTime) / 1_000_000;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,11 +318,11 @@ public class Stresser implements ExecutionController {
|
||||
* @return time
|
||||
*/
|
||||
public long getTimeLeft() {
|
||||
long current = System.currentTimeMillis();
|
||||
if (current >= finishTime) {
|
||||
long elapsedTime = System.nanoTime() - startTime;
|
||||
if (elapsedTime >= stressTime) {
|
||||
return 0;
|
||||
} else {
|
||||
return finishTime - current;
|
||||
return (stressTime - elapsedTime) / 1_000_000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java 8081489 generi
|
||||
java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java 6849364 generic-all
|
||||
java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java 6848406 generic-all
|
||||
java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java 6848407 generic-all
|
||||
java/awt/Frame/BogusFocusableWindowState/BogusFocusableWindowState.java 8361521 linux-all
|
||||
java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java 8340374 macosx-all
|
||||
java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java 8022302 generic-all
|
||||
java/awt/Frame/RestoreToOppositeScreen/RestoreToOppositeScreen.java 8286840 linux-all
|
||||
@@ -455,7 +456,6 @@ java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java 6848810 macosx-all
|
||||
java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java 8194751 linux-all
|
||||
java/awt/image/VolatileImage/BitmaskVolatileImage.java 8133102 linux-all
|
||||
java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java 8203004 linux-all
|
||||
java/awt/ScrollPane/ScrollPositionTest.java 8040070 linux-all
|
||||
java/awt/ScrollPane/ScrollPaneEventType.java 8296516 macosx-all
|
||||
java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all
|
||||
java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java 8080676 linux-all
|
||||
@@ -803,7 +803,6 @@ java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_2.java 7131438,802
|
||||
java/awt/Modal/WsDisabledStyle/CloseBlocker/CloseBlocker.java 7187741 linux-all,macosx-all
|
||||
java/awt/xembed/server/TestXEmbedServerJava.java 8001150,8004031 generic-all
|
||||
java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java 8068378 generic-all
|
||||
java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java 8162380 generic-all
|
||||
java/awt/image/VolatileImage/VolatileImageConfigurationTest.java 8171069 macosx-all,linux-all
|
||||
java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java 8172245 linux-all
|
||||
java/awt/Frame/FrameStateTest/FrameStateTest.java 8203920 macosx-all,linux-all
|
||||
@@ -825,7 +824,6 @@ java/awt/Focus/FrameMinimizeTest/FrameMinimizeTest.java 8016266 linux-x64
|
||||
java/awt/Frame/SizeMinimizedTest.java 8305915 linux-x64
|
||||
java/awt/PopupMenu/PopupHangTest.java 8340022 windows-all
|
||||
java/awt/Focus/MinimizeNonfocusableWindowTest.java 8024487 windows-all
|
||||
java/awt/Focus/InactiveFocusRace.java 8023263 linux-all
|
||||
java/awt/List/HandlingKeyEventIfMousePressedTest.java 6848358 macosx-all,windows-all
|
||||
java/awt/List/ListScrollbarCursorTest.java 8066410 generic-all
|
||||
java/awt/Checkbox/CheckboxBoxSizeTest.java 8340870 windows-all
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
*
|
||||
* @comment Don't allow -Xcomp or -Xint as they impact memory useage and number of iterations.
|
||||
* Require compressed oops because not doing so increases memory usage.
|
||||
* @requires (vm.compMode == "Xmixed") & vm.opt.final.UseCompressedOops
|
||||
* @requires (vm.compMode == "Xmixed") & (vm.bits == 32 | vm.opt.final.UseCompressedOops)
|
||||
* @run build TestScaffold VMConnection TargetListener TargetAdapter
|
||||
* @run compile -g ThreadMemoryLeakTest.java
|
||||
* @comment run with -Xmx7m so any leak will quickly produce OOME
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 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
|
||||
@@ -30,6 +30,7 @@
|
||||
*/
|
||||
|
||||
import java.awt.Button;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Frame;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
@@ -48,19 +49,27 @@ public class InactiveFocusRace {
|
||||
Button activeButton, inactiveButton1, inactiveButton2;
|
||||
Semaphore sema;
|
||||
final static int TIMEOUT = 10000;
|
||||
private static Robot robot;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try {
|
||||
robot = new Robot();
|
||||
InactiveFocusRace test = new InactiveFocusRace();
|
||||
test.init();
|
||||
EventQueue.invokeAndWait(() -> {
|
||||
test.init();
|
||||
});
|
||||
robot.waitForIdle();
|
||||
robot.delay(1000);
|
||||
test.start();
|
||||
} finally {
|
||||
if (activeFrame != null) {
|
||||
activeFrame.dispose();
|
||||
}
|
||||
if (inactiveFrame != null) {
|
||||
inactiveFrame.dispose();
|
||||
}
|
||||
EventQueue.invokeAndWait(() -> {
|
||||
if (activeFrame != null) {
|
||||
activeFrame.dispose();
|
||||
}
|
||||
if (inactiveFrame != null) {
|
||||
inactiveFrame.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,24 +100,40 @@ public class InactiveFocusRace {
|
||||
sema.raise();
|
||||
}
|
||||
});
|
||||
inactiveFrame.addWindowListener(new WindowAdapter() {
|
||||
public void windowActivated(WindowEvent e) {
|
||||
System.err.println("inactive Window activated");
|
||||
sema.raise();
|
||||
}
|
||||
});
|
||||
activeFrame.addWindowListener(new WindowAdapter() {
|
||||
public void windowActivated(WindowEvent e) {
|
||||
System.err.println("Window activated");
|
||||
sema.raise();
|
||||
}
|
||||
});
|
||||
inactiveFrame.setVisible(true);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
Robot robot = null;
|
||||
try {
|
||||
robot = new Robot();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to create robot");
|
||||
}
|
||||
|
||||
inactiveFrame.setVisible(true);
|
||||
activeFrame.setVisible(true);
|
||||
|
||||
// Wait for inactive frame to become active
|
||||
try {
|
||||
sema.doWait(TIMEOUT);
|
||||
} catch (InterruptedException ie) {
|
||||
throw new RuntimeException("Wait was interrupted");
|
||||
}
|
||||
if (!sema.getState()) {
|
||||
throw new RuntimeException("Frame doesn't become active on show");
|
||||
}
|
||||
sema.setState(false);
|
||||
|
||||
try {
|
||||
EventQueue.invokeAndWait(() -> activeFrame.setVisible(true));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Interrupted active frame rendering");
|
||||
}
|
||||
|
||||
// Wait for active frame to become active
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.awt.Window;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8346952
|
||||
* @summary Verifies no exception occurs when triggering updateCG()
|
||||
* for an ownerless window.
|
||||
* @key headful
|
||||
*/
|
||||
public final class BogusFocusableWindowState {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Window frame = new Window(null) {
|
||||
@Override
|
||||
public boolean getFocusableWindowState() {
|
||||
removeNotify();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
try {
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
} finally {
|
||||
frame.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8235638 8235739 8285094
|
||||
* @bug 8235638 8235739 8285094 8346952
|
||||
* @key headful
|
||||
*/
|
||||
public final class GetGraphicsStressTest {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@@ -27,7 +27,6 @@ import java.awt.Frame;
|
||||
import java.awt.TextField;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/*
|
||||
* @test
|
||||
@@ -54,16 +53,17 @@ public class SetEchoCharTest4 extends Frame implements ActionListener {
|
||||
|
||||
Make sure the actual text matches what you typed in for each field.
|
||||
Press Pass if everything's ok, otherwise Fail
|
||||
""";
|
||||
""";
|
||||
|
||||
public SetEchoCharTest4() {
|
||||
super("SetEchoCharTest4");
|
||||
setLayout(new FlowLayout());
|
||||
tf1.setEchoChar('*');
|
||||
tf2.setEchoChar('$');
|
||||
tf3.setEchoChar('#');
|
||||
addStuff();
|
||||
b.addActionListener(this);
|
||||
setSize (200,200);
|
||||
setSize (300, 150);
|
||||
}
|
||||
|
||||
private void addStuff() {
|
||||
@@ -78,7 +78,6 @@ public class SetEchoCharTest4 extends Frame implements ActionListener {
|
||||
PassFailJFrame.log("TextField2 = " + tf2.getText());
|
||||
PassFailJFrame.log("TextField3 = " + tf3.getText());
|
||||
PassFailJFrame.log("--------------");
|
||||
setVisible(false);
|
||||
remove(tf1);
|
||||
remove(tf2);
|
||||
remove(tf3);
|
||||
@@ -86,16 +85,14 @@ public class SetEchoCharTest4 extends Frame implements ActionListener {
|
||||
addStuff();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException,
|
||||
InvocationTargetException {
|
||||
public static void main(String[] args) throws Exception {
|
||||
PassFailJFrame.builder()
|
||||
.title("Set Echo Character Test")
|
||||
.testUI(SetEchoCharTest4::new)
|
||||
.instructions(INSTRUCTIONS)
|
||||
.rows((int) INSTRUCTIONS.lines().count() + 1)
|
||||
.columns(40)
|
||||
.logArea()
|
||||
.build()
|
||||
.awaitAndCheck();
|
||||
.title("Set Echo Character Test")
|
||||
.testUI(SetEchoCharTest4::new)
|
||||
.instructions(INSTRUCTIONS)
|
||||
.columns(40)
|
||||
.logArea()
|
||||
.build()
|
||||
.awaitAndCheck();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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,55 +22,52 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* test
|
||||
* @test
|
||||
* @bug 6282388
|
||||
* @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit
|
||||
* @author artem.ananiev@sun.com: area=awt.headless
|
||||
* @run shell WrappedToolkitTest.sh
|
||||
* @summary Tests that AWT uses correct toolkit wrapped into HeadlessToolkit
|
||||
* @modules java.desktop/sun.awt:open
|
||||
* @library /test/lib
|
||||
* @run main/othervm -Djava.awt.headless=true TestWrapped
|
||||
*/
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Toolkit;
|
||||
import java.lang.Class;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
import sun.awt.*;
|
||||
public final class TestWrapped {
|
||||
|
||||
public class TestWrapped
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (args.length != 1) {
|
||||
System.err.println("No correct toolkit class name is specified, test is not run");
|
||||
System.exit(0);
|
||||
private static final String HEADLESS_TOOLKIT = "sun.awt.HeadlessToolkit";
|
||||
private static final String MACOSX_TOOLKIT = "sun.lwawt.macosx.LWCToolkit";
|
||||
private static final String UNIX_TOOLKIT = "sun.awt.X11.XToolkit";
|
||||
private static final String WINDOWS_TOOLKIT = "sun.awt.windows.WToolkit";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String expectedToolkitClassName;
|
||||
if (Platform.isWindows()) {
|
||||
expectedToolkitClassName = WINDOWS_TOOLKIT;
|
||||
} else if (Platform.isOSX()) {
|
||||
expectedToolkitClassName = MACOSX_TOOLKIT;
|
||||
} else {
|
||||
expectedToolkitClassName = UNIX_TOOLKIT;
|
||||
}
|
||||
|
||||
String correctToolkitClassName = args[0];
|
||||
Toolkit tk = Toolkit.getDefaultToolkit();
|
||||
Class tkClass = tk.getClass();
|
||||
if (!tkClass.getName().equals("sun.awt.HeadlessToolkit"))
|
||||
{
|
||||
System.err.println(tkClass.getName());
|
||||
System.err.println("Error: default toolkit is not an instance of HeadlessToolkit");
|
||||
System.exit(-1);
|
||||
Class<?> tkClass = tk.getClass();
|
||||
if (!tkClass.getName().equals(HEADLESS_TOOLKIT)) {
|
||||
System.err.println("Expected: " + HEADLESS_TOOLKIT);
|
||||
System.err.println("Actual: " + tkClass.getName());
|
||||
throw new RuntimeException("Wrong default toolkit");
|
||||
}
|
||||
|
||||
Field f = tkClass.getDeclaredField("tk");
|
||||
f.setAccessible(true);
|
||||
Class wrappedClass = f.get(tk).getClass();
|
||||
if (!wrappedClass.getName().equals(correctToolkitClassName)) {
|
||||
System.err.println(wrappedClass.getName());
|
||||
System.err.println("Error: wrapped toolkit is not an instance of " + correctToolkitClassName);
|
||||
System.exit(-1);
|
||||
Class<?> wrappedClass = f.get(tk).getClass();
|
||||
if (!wrappedClass.getName().equals(expectedToolkitClassName)) {
|
||||
System.err.println("Expected: " + expectedToolkitClassName);
|
||||
System.err.println("Actual: " + wrappedClass.getName());
|
||||
throw new RuntimeException("Wrong wrapped toolkit");
|
||||
}
|
||||
}
|
||||
catch (Exception z)
|
||||
{
|
||||
z.printStackTrace(System.err);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
#!/bin/ksh -p
|
||||
|
||||
#
|
||||
# Copyright (c) 2012, 2020, 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 6282388 8030640
|
||||
# @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit
|
||||
# @author artem.ananiev@sun.com: area=awt.headless
|
||||
# compile TestWrapped.java
|
||||
# @run shell WrappedToolkitTest.sh
|
||||
|
||||
# Beginning of subroutines:
|
||||
status=1
|
||||
|
||||
#Call this from anywhere to fail the test with an error message
|
||||
# usage: fail "reason why the test failed"
|
||||
fail()
|
||||
{ echo "The test failed :-("
|
||||
echo "$*" 1>&2
|
||||
echo "exit status was $status"
|
||||
exit $status
|
||||
} #end of fail()
|
||||
|
||||
#Call this from anywhere to pass the test with a message
|
||||
# usage: pass "reason why the test passed if applicable"
|
||||
pass()
|
||||
{ echo "The test passed!!!"
|
||||
echo "$*" 1>&2
|
||||
exit 0
|
||||
} #end of pass()
|
||||
|
||||
# end of subroutines
|
||||
|
||||
|
||||
# The beginning of the script proper
|
||||
|
||||
# Checking for proper OS
|
||||
OS=`uname -s`
|
||||
case "$OS" in
|
||||
AIX | CYGWIN* | Darwin | Linux )
|
||||
FILESEP="/"
|
||||
;;
|
||||
|
||||
Windows* )
|
||||
FILESEP="\\"
|
||||
;;
|
||||
|
||||
# catch all other OSs
|
||||
* )
|
||||
echo "Unrecognized system! $OS"
|
||||
fail "Unrecognized system! $OS"
|
||||
;;
|
||||
esac
|
||||
|
||||
# check that some executable or other file you need is available, abort if not
|
||||
# note that the name of the executable is in the fail string as well.
|
||||
# this is how to check for presence of the compiler, etc.
|
||||
#RESOURCE=`whence SomeProgramOrFileNeeded`
|
||||
#if [ "${RESOURCE}" = "" ] ;
|
||||
# then fail "Need SomeProgramOrFileNeeded to perform the test" ;
|
||||
#fi
|
||||
|
||||
# Want this test to run standalone as well as in the harness, so do the
|
||||
# following to copy the test's directory into the harness's scratch directory
|
||||
# and set all appropriate variables:
|
||||
|
||||
if [ -z "${TESTJAVA}" ] ; then
|
||||
# TESTJAVA is not set, so the test is running stand-alone.
|
||||
# TESTJAVA holds the path to the root directory of the build of the JDK
|
||||
# to be tested. That is, any java files run explicitly in this shell
|
||||
# should use TESTJAVA in the path to the java interpreter.
|
||||
# So, we'll set this to the JDK spec'd on the command line. If none
|
||||
# is given on the command line, tell the user that and use a cheesy
|
||||
# default.
|
||||
# THIS IS THE JDK BEING TESTED.
|
||||
if [ -n "$1" ] ;
|
||||
then TESTJAVA=$1
|
||||
else fail "no JDK specified on command line!"
|
||||
fi
|
||||
TESTSRC=.
|
||||
TESTCLASSES=.
|
||||
STANDALONE=1;
|
||||
fi
|
||||
echo "JDK under test is: $TESTJAVA"
|
||||
|
||||
#if in test harness, then copy the entire directory that the test is in over
|
||||
# to the scratch directory. This catches any support files needed by the test.
|
||||
if [ -z "${STANDALONE}" ] ;
|
||||
then cp ${TESTSRC}/* .
|
||||
fi
|
||||
case "$OS" in
|
||||
Windows* | CYGWIN* )
|
||||
${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
|
||||
*.java
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Compilation failed";
|
||||
fi
|
||||
;;
|
||||
|
||||
AIX | Linux )
|
||||
${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
|
||||
*.java
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Compilation failed";
|
||||
fi
|
||||
;;
|
||||
|
||||
Darwin)
|
||||
${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
|
||||
*.java
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Compilation failed";
|
||||
fi
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
#Just before executing anything, make sure it has executable permission!
|
||||
chmod 777 ./*
|
||||
|
||||
############### YOUR TEST CODE HERE!!!!!!! #############
|
||||
|
||||
case "$OS" in
|
||||
Windows* | CYGWIN* )
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
|
||||
--add-opens java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-opens java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
|
||||
TestWrapped sun.awt.windows.WToolkit
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit";
|
||||
fi
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
|
||||
--add-opens java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-opens java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
|
||||
-Dawt.toolkit=sun.awt.windows.WToolkit \
|
||||
TestWrapped sun.awt.windows.WToolkit
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit";
|
||||
fi
|
||||
;;
|
||||
|
||||
AIX | Linux )
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
|
||||
--add-opens java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-opens java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
|
||||
-Dawt.toolkit=sun.awt.X11.XToolkit \
|
||||
TestWrapped sun.awt.X11.XToolkit
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit";
|
||||
fi
|
||||
AWT_TOOLKIT=XToolkit ${TESTJAVA}/bin/java ${TESTVMOPTS} \
|
||||
--add-opens java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-opens java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
|
||||
-Djava.awt.headless=true \
|
||||
TestWrapped sun.awt.X11.XToolkit
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit";
|
||||
fi
|
||||
;;
|
||||
|
||||
Darwin)
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
|
||||
--add-opens java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
|
||||
TestWrapped sun.lwawt.macosx.LWCToolkit
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit";
|
||||
fi
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
|
||||
--add-opens java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
|
||||
-Dawt.toolkit=sun.lwawt.macosx.LWCToolkit \
|
||||
TestWrapped sun.lwawt.macosx.LWCToolkit
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit";
|
||||
fi
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
pass "All the tests are PASSED";
|
||||
|
||||
#For additional examples of how to write platform independent KSH scripts,
|
||||
# see the jtreg file itself. It is a KSH script for both Solaris and Win32
|
||||
+44
-212
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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,51 +22,57 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
@test
|
||||
@bug 8041928 8158616
|
||||
@requires (os.family != "mac")
|
||||
@summary Confirm that the Alt-Gr Modifier bit is set correctly.
|
||||
@run main/manual AltGraphModifierTest
|
||||
* @test
|
||||
* @bug 8041928 8158616
|
||||
* @requires (os.family != "mac")
|
||||
* @summary Confirm that the Alt-Gr Modifier bit is set correctly.
|
||||
* @library /java/awt/regtesthelpers
|
||||
* @build PassFailJFrame
|
||||
* @run main/manual AltGraphModifierTest
|
||||
*/
|
||||
|
||||
import java.awt.Button;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Panel;
|
||||
import java.awt.TextArea;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class AltGraphModifierTest {
|
||||
private static void init() throws Exception {
|
||||
String[] instructions
|
||||
= {
|
||||
"This test is for verifying Alt-Gr modifier of an event.",
|
||||
"Linux :-",
|
||||
"1. Please check if Alt-Gr key is present on keyboard.",
|
||||
"2. If present, press the Alt-Gr key and perform",
|
||||
" mouse click on the TestWindow.",
|
||||
"3. Navigate to System Settings-> Keyboard-> Shortcuts->",
|
||||
" Typing.",
|
||||
"4. Select an option for the Alternative Characters Key",
|
||||
" For example. Right Alt",
|
||||
"5. Close the settings and navigate to test",
|
||||
"6. Press Right Alt Key & perform mouse click on the",
|
||||
" TestWindow",
|
||||
"7. Test will exit by itself with appropriate result.",
|
||||
" ",
|
||||
};
|
||||
|
||||
Sysout.createDialog();
|
||||
Sysout.printInstructions(instructions);
|
||||
public static void main(String[] args) throws Exception {
|
||||
String INSTRUCTIONS = """
|
||||
This test is for verifying Alt-Gr modifier of an event.
|
||||
Please check if Alt-Gr key is present on keyboard.
|
||||
If not present, press Pass.
|
||||
On Windows:
|
||||
Press Alt-Gr or Right Alt key and simultaneously
|
||||
perform mouse click on the "TestWindow".
|
||||
On Linux:
|
||||
Navigate to
|
||||
System Settings-> Keyboard-> Special Character Entry
|
||||
Select "Right Alt" option for the "Alternate Characters Key"
|
||||
Close the settings and navigate to test
|
||||
Press Right Alt Key & simultaneously
|
||||
perform mouse click on the "TestWindow".
|
||||
|
||||
If the system does not have such setting, press Pass.
|
||||
After the test, change the Setting of "Alternate Characters Key"
|
||||
back to "Layout default".
|
||||
|
||||
If "Alt-Gr Modifier bit is set" message is displayed in logArea,
|
||||
press Pass else press Fail.
|
||||
""";
|
||||
|
||||
PassFailJFrame.builder()
|
||||
.instructions(INSTRUCTIONS)
|
||||
.columns(35)
|
||||
.testUI(AltGraphModifierTest::initTestWindow)
|
||||
.logArea()
|
||||
.build()
|
||||
.awaitAndCheck();
|
||||
}
|
||||
|
||||
static Frame mainFrame;
|
||||
public static void initTestWindow() {
|
||||
mainFrame = new Frame();
|
||||
public static Frame initTestWindow() {
|
||||
Frame mainFrame = new Frame();
|
||||
mainFrame.setTitle("TestWindow");
|
||||
mainFrame.setBounds(700, 10, 300, 300);
|
||||
mainFrame.addMouseListener(new MouseAdapter() {
|
||||
@@ -74,186 +80,12 @@ public class AltGraphModifierTest {
|
||||
public void mousePressed(MouseEvent e) {
|
||||
int ex = e.getModifiersEx();
|
||||
if ((ex & InputEvent.ALT_GRAPH_DOWN_MASK) == 0) {
|
||||
AltGraphModifierTest.fail("Alt-Gr Modifier bit is not set.");
|
||||
PassFailJFrame.log("Alt-Gr Modifier bit is not set.");
|
||||
} else {
|
||||
AltGraphModifierTest.pass();
|
||||
PassFailJFrame.log("Alt-Gr Modifier bit is set");
|
||||
}
|
||||
}
|
||||
});
|
||||
mainFrame.setVisible(true);
|
||||
}
|
||||
|
||||
public static void dispose() {
|
||||
Sysout.dispose();
|
||||
mainFrame.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* ***************************************************
|
||||
* Standard Test Machinery Section DO NOT modify anything in this section --
|
||||
* it's a standard chunk of code which has all of the synchronisation
|
||||
* necessary for the test harness. By keeping it the same in all tests, it
|
||||
* is easier to read and understand someone else's test, as well as insuring
|
||||
* that all tests behave correctly with the test harness. There is a section
|
||||
* following this for test-defined classes
|
||||
* ****************************************************
|
||||
*/
|
||||
private static boolean theTestPassed = false;
|
||||
private static boolean testGeneratedInterrupt = false;
|
||||
private static String failureMessage = "";
|
||||
private static Thread mainThread = null;
|
||||
final private static int sleepTime = 300000;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
mainThread = Thread.currentThread();
|
||||
try {
|
||||
init();
|
||||
initTestWindow();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
mainThread.sleep(sleepTime);
|
||||
} catch (InterruptedException e) {
|
||||
dispose();
|
||||
if (testGeneratedInterrupt && !theTestPassed) {
|
||||
throw new Exception(failureMessage);
|
||||
}
|
||||
}
|
||||
if (!testGeneratedInterrupt) {
|
||||
dispose();
|
||||
throw new RuntimeException("Timed out after " + sleepTime / 1000
|
||||
+ " seconds");
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void pass() {
|
||||
theTestPassed = true;
|
||||
testGeneratedInterrupt = true;
|
||||
mainThread.interrupt();
|
||||
}
|
||||
|
||||
public static synchronized void fail(String whyFailed) {
|
||||
theTestPassed = false;
|
||||
testGeneratedInterrupt = true;
|
||||
failureMessage = whyFailed;
|
||||
mainThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// *********** End Standard Test Machinery Section **********
|
||||
/**
|
||||
* **************************************************
|
||||
* Standard Test Machinery DO NOT modify anything below -- it's a standard chunk
|
||||
* of code whose purpose is to make user interaction uniform, and thereby make
|
||||
* it simpler to read and understand someone else's test.
|
||||
* **************************************************
|
||||
*/
|
||||
/**
|
||||
* This is part of the standard test machinery. It creates a dialog (with the
|
||||
* instructions), and is the interface for sending text messages to the user. To
|
||||
* print the instructions, send an array of strings to Sysout.createDialog
|
||||
* WithInstructions method. Put one line of instructions per array entry. To
|
||||
* display a message for the tester to see, simply call Sysout.println with the
|
||||
* string to be displayed. This mimics System.out.println but works within the
|
||||
* test harness as well as standalone.
|
||||
*/
|
||||
class Sysout {
|
||||
private static TestDialog dialog;
|
||||
private static Frame frame;
|
||||
|
||||
public static void createDialog() {
|
||||
frame = new Frame();
|
||||
dialog = new TestDialog(frame, "Instructions");
|
||||
String[] defInstr = {"Instructions will appear here. ", ""};
|
||||
dialog.printInstructions(defInstr);
|
||||
dialog.show();
|
||||
println("Any messages for the tester will display here.");
|
||||
}
|
||||
|
||||
public static void printInstructions(String[] instructions) {
|
||||
dialog.printInstructions(instructions);
|
||||
}
|
||||
|
||||
public static void println(String messageIn) {
|
||||
dialog.displayMessage(messageIn);
|
||||
}
|
||||
|
||||
public static void dispose() {
|
||||
dialog.dispose();
|
||||
frame.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is part of the standard test machinery. It provides a place for the test
|
||||
* instructions to be displayed, and a place for interactive messages to the
|
||||
* user to be displayed. To have the test instructions displayed, see Sysout. To
|
||||
* have a message to the user be displayed, see Sysout. Do not call anything in
|
||||
* this dialog directly.
|
||||
*/
|
||||
class TestDialog extends Dialog implements ActionListener {
|
||||
TextArea instructionsText;
|
||||
TextArea messageText;
|
||||
int maxStringLength = 80;
|
||||
Panel buttonP;
|
||||
Button failB;
|
||||
|
||||
// DO NOT call this directly, go through Sysout
|
||||
public TestDialog(Frame frame, String name) {
|
||||
super(frame, name);
|
||||
int scrollBoth = TextArea.SCROLLBARS_BOTH;
|
||||
instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
|
||||
add("North", instructionsText);
|
||||
|
||||
messageText = new TextArea("", 5, maxStringLength, scrollBoth);
|
||||
add("Center", messageText);
|
||||
|
||||
buttonP = new Panel();
|
||||
failB = new Button("Fail");
|
||||
failB.setActionCommand("fail");
|
||||
failB.addActionListener(this);
|
||||
buttonP.add("Center", failB);
|
||||
|
||||
add("South", buttonP);
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
// DO NOT call this directly, go through Sysout
|
||||
public void printInstructions(String[] instructions) {
|
||||
instructionsText.setText("");
|
||||
String printStr, remainingStr;
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
remainingStr = instructions[i];
|
||||
while (remainingStr.length() > 0) {
|
||||
if (remainingStr.length() >= maxStringLength) {
|
||||
int posOfSpace = remainingStr.
|
||||
lastIndexOf(' ', maxStringLength - 1);
|
||||
|
||||
if (posOfSpace <= 0) {
|
||||
posOfSpace = maxStringLength - 1;
|
||||
}
|
||||
|
||||
printStr = remainingStr.substring(0, posOfSpace + 1);
|
||||
remainingStr = remainingStr.substring(posOfSpace + 1);
|
||||
}
|
||||
else {
|
||||
printStr = remainingStr;
|
||||
remainingStr = "";
|
||||
}
|
||||
instructionsText.append(printStr + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void displayMessage(String messageIn) {
|
||||
messageText.append(messageIn + "\n");
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (e.getActionCommand() == "fail") {
|
||||
AltGraphModifierTest.fail("User Clicked Fail");
|
||||
}
|
||||
return mainFrame;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ import javax.swing.JSplitPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.Timer;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import javax.swing.text.html.StyleSheet;
|
||||
@@ -98,7 +99,8 @@ import static javax.swing.SwingUtilities.isEventDispatchThread;
|
||||
* tester. The instructions can be either plain text or HTML. If the
|
||||
* text of the instructions starts with {@code "<html>"}, the
|
||||
* instructions are displayed as HTML, as supported by Swing, which
|
||||
* provides richer formatting options.
|
||||
* provides richer formatting options. To handle navigating links in the
|
||||
* instructions, call {@link Builder#hyperlinkListener} to install a listener.
|
||||
* <p>
|
||||
* The instructions are displayed in a text component with word-wrapping
|
||||
* so that there's no horizontal scroll bar. If the text doesn't fit, a
|
||||
@@ -592,6 +594,7 @@ public final class PassFailJFrame {
|
||||
frame.add(createInstructionUIPanel(instructions,
|
||||
testTimeOut,
|
||||
rows, columns,
|
||||
null,
|
||||
false,
|
||||
false, 0),
|
||||
BorderLayout.CENTER);
|
||||
@@ -610,6 +613,7 @@ public final class PassFailJFrame {
|
||||
createInstructionUIPanel(builder.instructions,
|
||||
builder.testTimeOut,
|
||||
builder.rows, builder.columns,
|
||||
builder.hyperlinkListener,
|
||||
builder.screenCapture,
|
||||
builder.addLogArea,
|
||||
builder.logAreaRows);
|
||||
@@ -631,6 +635,7 @@ public final class PassFailJFrame {
|
||||
private static JComponent createInstructionUIPanel(String instructions,
|
||||
long testTimeOut,
|
||||
int rows, int columns,
|
||||
HyperlinkListener hyperlinkListener,
|
||||
boolean enableScreenCapture,
|
||||
boolean addLogArea,
|
||||
int logAreaRows) {
|
||||
@@ -643,6 +648,9 @@ public final class PassFailJFrame {
|
||||
JTextComponent text = instructions.startsWith("<html>")
|
||||
? configureHTML(instructions, rows, columns)
|
||||
: configurePlainText(instructions, rows, columns);
|
||||
if (hyperlinkListener != null && text instanceof JEditorPane ep) {
|
||||
ep.addHyperlinkListener(hyperlinkListener);
|
||||
}
|
||||
text.setEditable(false);
|
||||
text.setBorder(createTextBorder());
|
||||
text.setCaretPosition(0);
|
||||
@@ -716,7 +724,7 @@ public final class PassFailJFrame {
|
||||
// Reduce the list default margins
|
||||
styles.addRule("ol, ul { margin-left-ltr: 30; margin-left-rtl: 30 }");
|
||||
// Make the size of code (and other elements) the same as other text
|
||||
styles.addRule("code, kbd, samp, pre { font-size: inherit }");
|
||||
styles.addRule("code, kbd, samp, pre { font-size: inherit; background: #DDD; }");
|
||||
|
||||
return text;
|
||||
}
|
||||
@@ -1398,6 +1406,7 @@ public final class PassFailJFrame {
|
||||
private int rows;
|
||||
private int columns;
|
||||
private boolean screenCapture;
|
||||
private HyperlinkListener hyperlinkListener;
|
||||
private boolean addLogArea;
|
||||
private int logAreaRows = 10;
|
||||
|
||||
@@ -1478,6 +1487,18 @@ public final class PassFailJFrame {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a {@link HyperlinkListener} for navigating links inside
|
||||
* the instructions pane.
|
||||
*
|
||||
* @param hyperlinkListener the listener
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder hyperlinkListener(HyperlinkListener hyperlinkListener) {
|
||||
this.hyperlinkListener = hyperlinkListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder screenCapture() {
|
||||
this.screenCapture = true;
|
||||
return this;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
* 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
|
||||
* 4947220 7018606 7034570 4244896 5049299 8003488 8054494 8058464
|
||||
* 8067796 8224905 8263729 8265173 8272600 8231297 8282219 8285517
|
||||
* 8352533
|
||||
* 8352533 8368192
|
||||
* @key intermittent
|
||||
* @summary Basic tests for Process and Environment Variable code
|
||||
* @modules java.base/java.lang:open
|
||||
@@ -777,30 +777,29 @@ public class Basic {
|
||||
return Pattern.compile(regex).matcher(str).find();
|
||||
}
|
||||
|
||||
private static String matchAndExtract(String str, String regex) {
|
||||
Matcher matcher = Pattern.compile(regex).matcher(str);
|
||||
if (matcher.find()) {
|
||||
return matcher.group();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
// Return the string with the matching regex removed
|
||||
private static String matchAndRemove(String str, String regex) {
|
||||
return Pattern.compile(regex)
|
||||
.matcher(str)
|
||||
.replaceAll("");
|
||||
}
|
||||
|
||||
/* Only used for Mac OS X --
|
||||
* Mac OS X (may) add the variable __CF_USER_TEXT_ENCODING to an empty
|
||||
* environment. The environment variable JAVA_MAIN_CLASS_<pid> may also
|
||||
* be set in Mac OS X.
|
||||
* Remove them both from the list of env variables
|
||||
* Mac OS X (may) add the variables: __CF_USER_TEXT_ENCODING, JAVA_MAIN_CLASS_<pid>,
|
||||
* and TMPDIR.
|
||||
* Remove them from the list of env variables
|
||||
*/
|
||||
private static String removeMacExpectedVars(String vars) {
|
||||
// Check for __CF_USER_TEXT_ENCODING
|
||||
String cleanedVars = vars.replace("__CF_USER_TEXT_ENCODING="
|
||||
+cfUserTextEncoding+",","");
|
||||
String cleanedVars = matchAndRemove(vars,
|
||||
"__CF_USER_TEXT_ENCODING=" + cfUserTextEncoding + ",");
|
||||
// Check for JAVA_MAIN_CLASS_<pid>
|
||||
String javaMainClassStr
|
||||
= matchAndExtract(cleanedVars,
|
||||
"JAVA_MAIN_CLASS_\\d+=Basic.JavaChild,");
|
||||
return cleanedVars.replace(javaMainClassStr,"");
|
||||
cleanedVars = matchAndRemove(cleanedVars,
|
||||
"JAVA_MAIN_CLASS_\\d+=Basic.JavaChild,");
|
||||
// Check and remove TMPDIR
|
||||
cleanedVars = matchAndRemove(cleanedVars,
|
||||
"TMPDIR=[^,]*,");
|
||||
return cleanedVars;
|
||||
}
|
||||
|
||||
/* Only used for AIX --
|
||||
|
||||
@@ -53,8 +53,8 @@ public class GetStackTraceALotWhenBlocking {
|
||||
|
||||
int iterations;
|
||||
int value = Integer.parseInt(args[0]);
|
||||
if (Platform.isOSX() && Platform.isX64()) {
|
||||
// reduced iterations on macosx-x64
|
||||
if (Platform.isOSX()) {
|
||||
// reduced iterations on macosx
|
||||
iterations = Math.max(value / 4, 1);
|
||||
} else {
|
||||
iterations = value;
|
||||
|
||||
@@ -56,8 +56,8 @@ public class GetStackTraceALotWhenPinned {
|
||||
|
||||
int iterations;
|
||||
int value = Integer.parseInt(args[0]);
|
||||
if (Platform.isOSX() && Platform.isX64()) {
|
||||
// reduced iterations on macosx-x64
|
||||
if (Platform.isOSX()) {
|
||||
// reduced iterations on macosx
|
||||
iterations = Math.max(value / 4, 1);
|
||||
} else {
|
||||
iterations = value;
|
||||
|
||||
@@ -49,8 +49,8 @@ public class ParkALot {
|
||||
public static void main(String[] args) throws Exception {
|
||||
int iterations;
|
||||
int value = Integer.parseInt(args[0]);
|
||||
if (Platform.isOSX() && Platform.isX64()) {
|
||||
// reduced iterations on macosx-x64
|
||||
if (Platform.isOSX()) {
|
||||
// reduced iterations on macosx
|
||||
iterations = Math.max(value / 4, 1);
|
||||
} else {
|
||||
iterations = value;
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8277444
|
||||
*
|
||||
* @library /test/lib
|
||||
* @compile SimpleIdentityTransformer.java
|
||||
* @run shell MakeJAR.sh retransformAgent
|
||||
* @run main/othervm -javaagent:retransformAgent.jar RetransformBigClassTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.compiler.InMemoryJavaCompiler;
|
||||
|
||||
/*
|
||||
* JvmtiClassFileReconstituter::copy_bytecodes restores bytecodes rewritten
|
||||
* by the linking process. It is used by RetransformClasses.
|
||||
* JDK-8277444 is a data race between copy_bytecodes and the linking process.
|
||||
* This test puts the linking process in one thread and the retransforming process
|
||||
* in another thread. The test uses Class.forName("BigClass", false, classLoader)
|
||||
* which does not link the class. When the class is used, the linking process starts.
|
||||
* In another thread retransforming of the class is happening.
|
||||
* We generate a class with big methods. A number of methods and their size are
|
||||
* chosen to make the linking and retransforming processes run concurrently.
|
||||
* We delay the retransforming process to follow the linking process.
|
||||
* If there is no synchronization between the processes, a data race will happen.
|
||||
*/
|
||||
public class RetransformBigClassTest extends AInstrumentationTestCase {
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
private static final int COUNTER_INC_COUNT = 2000; // A number of 'c+=1;' statements in methods of a class.
|
||||
private static final int MIN_LINK_TIME_MS = 60; // Large enough so the linking and retransforming processes run in parallel.
|
||||
private static final int RETRANSFORM_CLASSES_DELAY_MS = 37; // We manage to create a data race when a delay is in the range 0.52x - 0.62x of MIN_LINK_TIME_MS.
|
||||
|
||||
private static Class<?> bigClass;
|
||||
private static byte[] bigClassBytecode;
|
||||
|
||||
private Thread retransformThread;
|
||||
|
||||
RetransformBigClassTest() {
|
||||
super("RetransformBigClassTest");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new RetransformBigClassTest().runTest();
|
||||
}
|
||||
|
||||
protected final void doRunTest() throws Throwable {
|
||||
ClassLoader classLoader = new ClassLoader() {
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
if (name.equals("BigClass")) {
|
||||
return defineClass(name, bigClassBytecode, 0, bigClassBytecode.length);
|
||||
}
|
||||
|
||||
return super.findClass(name);
|
||||
}
|
||||
};
|
||||
synchronized (LOCK) {
|
||||
bigClass = Class.forName("BigClass", false, classLoader);
|
||||
LOCK.notify();
|
||||
}
|
||||
// Make a use of the BigClass
|
||||
assertTrue(bigClass.getConstructor().newInstance().hashCode() != 0);
|
||||
retransformThread.join();
|
||||
}
|
||||
|
||||
private byte[] createClassBytecode(String className, int methodCount) throws Exception {
|
||||
String methodBody = "";
|
||||
for (int j = 0; j < COUNTER_INC_COUNT; j++) {
|
||||
methodBody += "c+=1;";
|
||||
}
|
||||
|
||||
String classSrc = "public class " + className + " { int c;";
|
||||
|
||||
for (int i = 0; i < methodCount; i++) {
|
||||
classSrc += "\npublic void m" + i + "(){";
|
||||
classSrc += methodBody;
|
||||
classSrc += "\n}";
|
||||
}
|
||||
classSrc += "\n}";
|
||||
|
||||
return InMemoryJavaCompiler.compile(className, classSrc);
|
||||
}
|
||||
|
||||
// We need a number of methods such that the linking time is greater than
|
||||
// or equal to MIN_LINK_TIME_MS.
|
||||
// We create a class having 5 methods and trigger the linking process.
|
||||
// We measure the time taken and use it to calculate the needed number.
|
||||
private int findMethodCount() throws Exception {
|
||||
int methodCount = 5;
|
||||
final String className = "BigClass" + methodCount;
|
||||
final byte[] bytecode = createClassBytecode(className, methodCount);
|
||||
ClassLoader classLoader = new ClassLoader() {
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
if (name.equals(className)) {
|
||||
return defineClass(name, bytecode, 0, bytecode.length);
|
||||
}
|
||||
|
||||
return super.findClass(name);
|
||||
}
|
||||
};
|
||||
var bigClass = Class.forName(className, false, classLoader);
|
||||
long startTime = System.nanoTime();
|
||||
assertTrue(bigClass.getConstructor().newInstance().hashCode() != 0);
|
||||
double linkTimeMs = (System.nanoTime() - startTime) / 1000000.0;
|
||||
System.out.println("Link time for a class with " + methodCount + " methods each having " + COUNTER_INC_COUNT + " counter increments: " + Math.round(linkTimeMs));
|
||||
if (linkTimeMs < MIN_LINK_TIME_MS) {
|
||||
methodCount = (int)Math.round((MIN_LINK_TIME_MS * methodCount) / linkTimeMs);
|
||||
}
|
||||
System.out.println("The number of methods to exceed " + MIN_LINK_TIME_MS + " ms linking time: " + methodCount);
|
||||
return methodCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
bigClassBytecode = createClassBytecode("BigClass", findMethodCount());
|
||||
fInst.addTransformer(new SimpleIdentityTransformer());
|
||||
retransformThread = new Thread(() -> {
|
||||
try {
|
||||
synchronized (LOCK) {
|
||||
while (bigClass == null) {
|
||||
System.out.println("[retransformThread]: Waiting for bigClass");
|
||||
LOCK.wait();
|
||||
}
|
||||
}
|
||||
Thread.sleep(RETRANSFORM_CLASSES_DELAY_MS);
|
||||
fInst.retransformClasses(bigClass);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
retransformThread.start();
|
||||
Thread.sleep(100);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@@ -40,7 +40,7 @@ import static java.util.stream.Collectors.toList;
|
||||
* Two threads are created per client connection. So, it's not
|
||||
* intended for large numbers of parallel connections.
|
||||
*/
|
||||
public class ProxyServer extends Thread implements Closeable {
|
||||
public final class ProxyServer implements Closeable {
|
||||
|
||||
// could use the test library here - Platform.isWindows(),
|
||||
// but it would force all tests that use ProxyServer to
|
||||
@@ -97,9 +97,7 @@ public class ProxyServer extends Thread implements Closeable {
|
||||
this(port, debug, null);
|
||||
}
|
||||
|
||||
public ProxyServer(Integer port,
|
||||
Boolean debug,
|
||||
Credentials credentials)
|
||||
private ProxyServer(Integer port, Boolean debug, Credentials credentials)
|
||||
throws IOException
|
||||
{
|
||||
this.debug = debug;
|
||||
@@ -108,15 +106,8 @@ public class ProxyServer extends Thread implements Closeable {
|
||||
listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), port));
|
||||
this.port = ((InetSocketAddress)listener.getLocalAddress()).getPort();
|
||||
this.credentials = credentials;
|
||||
setName("ProxyListener");
|
||||
setDaemon(true);
|
||||
connections = new CopyOnWriteArrayList<Connection>();
|
||||
start();
|
||||
}
|
||||
|
||||
public ProxyServer(String s) {
|
||||
credentials = null;
|
||||
connections = new CopyOnWriteArrayList<Connection>();
|
||||
Thread.ofPlatform().name("ProxyListener").daemon().start(this::run);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +139,7 @@ public class ProxyServer extends Thread implements Closeable {
|
||||
|
||||
volatile boolean done;
|
||||
|
||||
public void run() {
|
||||
private void run() {
|
||||
int id = 0;
|
||||
try {
|
||||
while (!done) {
|
||||
@@ -656,10 +647,11 @@ public class ProxyServer extends Thread implements Closeable {
|
||||
int port = Integer.parseInt(args[0]);
|
||||
boolean debug = args.length > 1 && args[1].equals("-debug");
|
||||
System.out.println("Debugging : " + debug);
|
||||
ProxyServer ps = new ProxyServer(port, debug);
|
||||
System.out.println("Proxy server listening on port " + ps.getPort());
|
||||
while (true) {
|
||||
Thread.sleep(5000);
|
||||
try (ProxyServer ps = new ProxyServer(port, debug)) {
|
||||
System.out.println("Proxy server listening on port " + ps.getPort());
|
||||
while (true) {
|
||||
Thread.sleep(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@
|
||||
* @summary Test for ExtendedOpenOption.DIRECT flag
|
||||
* @requires (os.family == "linux" | os.family == "aix")
|
||||
* @library /test/lib
|
||||
* @modules java.base/sun.nio.ch:+open java.base/java.io:+open
|
||||
* @build jdk.test.lib.Platform
|
||||
* @run main/native DirectIOTest
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.channels.*;
|
||||
@@ -47,10 +49,25 @@ import com.sun.nio.file.ExtendedOpenOption;
|
||||
public class DirectIOTest {
|
||||
|
||||
private static final int BASE_SIZE = 4096;
|
||||
private static final int TRIES = 3;
|
||||
|
||||
public static int getFD(FileChannel channel) throws Exception {
|
||||
Field fFdFd = channel.getClass().getDeclaredField("fd");
|
||||
fFdFd.setAccessible(true);
|
||||
FileDescriptor fd = (FileDescriptor) fFdFd.get(channel);
|
||||
|
||||
Field fFd = FileDescriptor.class.getDeclaredField("fd");
|
||||
fFd.setAccessible(true);
|
||||
return fFd.getInt(fd);
|
||||
}
|
||||
|
||||
private static void testWrite(Path p, long blockSize) throws Exception {
|
||||
try (FileChannel fc = FileChannel.open(p,
|
||||
StandardOpenOption.READ,
|
||||
StandardOpenOption.WRITE,
|
||||
ExtendedOpenOption.DIRECT)) {
|
||||
int fd = getFD(fc);
|
||||
|
||||
private static int testWrite(Path p, long blockSize) throws Exception {
|
||||
try (FileChannel fc = FileChannel.open(p, StandardOpenOption.WRITE,
|
||||
ExtendedOpenOption.DIRECT)) {
|
||||
int bs = (int)blockSize;
|
||||
int size = Math.max(BASE_SIZE, bs);
|
||||
int alignment = bs;
|
||||
@@ -60,22 +77,55 @@ public class DirectIOTest {
|
||||
for (int j = 0; j < size; j++) {
|
||||
src.put((byte)0);
|
||||
}
|
||||
src.flip();
|
||||
fc.write(src);
|
||||
return size;
|
||||
|
||||
// If there is AV or other FS tracing software, it may cache the file
|
||||
// contents on first access, even though we have asked for DIRECT here.
|
||||
// Do several attempts to make test more resilient.
|
||||
|
||||
for (int t = 0; t < TRIES; t++) {
|
||||
flushFileCache(size, fd);
|
||||
src.flip();
|
||||
fc.position(0);
|
||||
fc.write(src);
|
||||
if (!isFileInCache(size, fd)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("DirectIO is not working properly with " +
|
||||
"write. File still exists in cache!");
|
||||
}
|
||||
}
|
||||
|
||||
private static int testRead(Path p, long blockSize) throws Exception {
|
||||
try (FileChannel fc = FileChannel.open(p, ExtendedOpenOption.DIRECT)) {
|
||||
private static void testRead(Path p, long blockSize) throws Exception {
|
||||
try (FileChannel fc = FileChannel.open(p,
|
||||
StandardOpenOption.READ,
|
||||
ExtendedOpenOption.DIRECT)) {
|
||||
int fd = getFD(fc);
|
||||
|
||||
int bs = (int)blockSize;
|
||||
int size = Math.max(BASE_SIZE, bs);
|
||||
int alignment = bs;
|
||||
ByteBuffer dest = ByteBuffer.allocateDirect(size + alignment - 1)
|
||||
.alignedSlice(alignment);
|
||||
assert dest.capacity() != 0;
|
||||
fc.read(dest);
|
||||
return size;
|
||||
|
||||
// If there is AV or other FS tracing software, it may cache the file
|
||||
// contents on first access, even though we have asked for DIRECT here.
|
||||
// Do several attempts to make test more resilient.
|
||||
|
||||
for (int t = 0; t < TRIES; t++) {
|
||||
flushFileCache(size, fd);
|
||||
dest.clear();
|
||||
fc.position(0);
|
||||
fc.read(dest);
|
||||
if (!isFileInCache(size, fd)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("DirectIO is not working properly with " +
|
||||
"read. File still exists in cache!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,12 +134,8 @@ public class DirectIOTest {
|
||||
Paths.get(System.getProperty("test.dir", ".")), "test", null);
|
||||
}
|
||||
|
||||
private static boolean isFileInCache(int size, Path p) {
|
||||
String path = p.toString();
|
||||
return isFileInCache0(size, path);
|
||||
}
|
||||
|
||||
private static native boolean isFileInCache0(int size, String path);
|
||||
private static native boolean flushFileCache(int size, int fd);
|
||||
private static native boolean isFileInCache(int size, int fd);
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Path p = createTempFile();
|
||||
@@ -98,16 +144,8 @@ public class DirectIOTest {
|
||||
System.loadLibrary("DirectIO");
|
||||
|
||||
try {
|
||||
int size = testWrite(p, blockSize);
|
||||
if (isFileInCache(size, p)) {
|
||||
throw new RuntimeException("DirectIO is not working properly with "
|
||||
+ "write. File still exists in cache!");
|
||||
}
|
||||
size = testRead(p, blockSize);
|
||||
if (isFileInCache(size, p)) {
|
||||
throw new RuntimeException("DirectIO is not working properly with "
|
||||
+ "read. File still exists in cache!");
|
||||
}
|
||||
testWrite(p, blockSize);
|
||||
testRead(p, blockSize);
|
||||
} finally {
|
||||
Files.delete(p);
|
||||
}
|
||||
|
||||
@@ -45,13 +45,27 @@ static void ThrowException(JNIEnv *env, const char *name, const char *msg) {
|
||||
|
||||
/*
|
||||
* Class: DirectIO
|
||||
* Method: isFileInCache0
|
||||
* Signature: (ILjava/lang/String;)Z
|
||||
* Method: flushFileCache
|
||||
* Signature: (II;)V
|
||||
*/
|
||||
JNIEXPORT jboolean Java_DirectIOTest_isFileInCache0(JNIEnv *env,
|
||||
JNIEXPORT void Java_DirectIOTest_flushFileCache(JNIEnv *env,
|
||||
jclass cls,
|
||||
jint file_size,
|
||||
jstring file_path) {
|
||||
jint fd) {
|
||||
#ifdef __linux__
|
||||
posix_fadvise(fd, 0, file_size, POSIX_FADV_DONTNEED);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: DirectIO
|
||||
* Method: isFileInCache
|
||||
* Signature: (II;)Z
|
||||
*/
|
||||
JNIEXPORT jboolean Java_DirectIOTest_isFileInCache(JNIEnv *env,
|
||||
jclass cls,
|
||||
jint file_size,
|
||||
jint fd) {
|
||||
void *f_mmap;
|
||||
#ifdef __linux__
|
||||
unsigned char *f_seg;
|
||||
@@ -69,17 +83,10 @@ JNIEXPORT jboolean Java_DirectIOTest_isFileInCache0(JNIEnv *env,
|
||||
size_t index = (file_size + page_size - 1) /page_size;
|
||||
jboolean result = JNI_FALSE;
|
||||
|
||||
const char* path = (*env)->GetStringUTFChars(env, file_path, JNI_FALSE);
|
||||
|
||||
int fd = open(path, O_RDWR);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, file_path, path);
|
||||
|
||||
f_mmap = mmap(0, file_size, PROT_NONE, MAP_SHARED, fd, 0);
|
||||
if (f_mmap == MAP_FAILED) {
|
||||
close(fd);
|
||||
ThrowException(env, "java/io/IOException",
|
||||
"test of whether file exists in cache failed");
|
||||
"test of whether file exists in cache failed: mmap failed");
|
||||
}
|
||||
f_seg = malloc(index);
|
||||
if (f_seg != NULL) {
|
||||
@@ -95,9 +102,8 @@ JNIEXPORT jboolean Java_DirectIOTest_isFileInCache0(JNIEnv *env,
|
||||
free(f_seg);
|
||||
} else {
|
||||
ThrowException(env, "java/io/IOException",
|
||||
"test of whether file exists in cache failed");
|
||||
"test of whether file exists in cache failed: malloc failed");
|
||||
}
|
||||
close(fd);
|
||||
munmap(f_mmap, file_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#
|
||||
#
|
||||
# Amendments up until ISO 4217 AMENDMENT NUMBER 179
|
||||
# (As of 02 May 2025)
|
||||
# Amendments up until ISO 4217 AMENDMENT NUMBER 180
|
||||
# (As of 22 September 2025)
|
||||
#
|
||||
|
||||
# Version
|
||||
FILEVERSION=3
|
||||
DATAVERSION=179
|
||||
DATAVERSION=180
|
||||
|
||||
# ISO 4217 currency data
|
||||
AF AFN 971 2
|
||||
@@ -44,7 +44,7 @@ BV NOK 578 2
|
||||
BR BRL 986 2
|
||||
IO USD 840 2
|
||||
BN BND 96 2
|
||||
BG BGN 975 2
|
||||
BG BGN 975 2 2025-12-31-22-00-00 EUR 978 2
|
||||
BF XOF 952 0
|
||||
BI BIF 108 0
|
||||
KH KHR 116 2
|
||||
@@ -69,7 +69,7 @@ CR CRC 188 2
|
||||
CI XOF 952 0
|
||||
HR EUR 978 2
|
||||
CU CUP 192 2
|
||||
CW ANG 532 2 2025-04-01-04-00-00 XCG 532 2
|
||||
CW XCG 532 2
|
||||
CY EUR 978 2
|
||||
CZ CZK 203 2
|
||||
DK DKK 208 2
|
||||
@@ -233,7 +233,7 @@ LK LKR 144 2
|
||||
SD SDG 938 2
|
||||
SR SRD 968 2
|
||||
SJ NOK 578 2
|
||||
SX ANG 532 2 2025-04-01-04-00-00 XCG 532 2
|
||||
SX XCG 532 2
|
||||
SZ SZL 748 2
|
||||
SE SEK 752 2
|
||||
CH CHF 756 2
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759
|
||||
* 8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269
|
||||
* 8208746 8209775 8264792 8274658 8283277 8296239 8321480 8334653
|
||||
* 8354343 8354344 8356096
|
||||
* 8354343 8354344 8356096 8368308
|
||||
* @summary Validate ISO 4217 data for Currency class.
|
||||
* @modules java.base/java.util:open
|
||||
* jdk.localedata
|
||||
@@ -116,7 +116,7 @@ public class ValidateISO4217 {
|
||||
private static final Set<String> currenciesNotYetDefined = new HashSet<>();
|
||||
// Codes that are obsolete, do not have related country, extra currency
|
||||
private static final String otherCodes =
|
||||
"ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-"
|
||||
"ADP-AFA-ATS-AYM-AZM-BEF-BGL-BGN-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-"
|
||||
+ "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-HRK-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-"
|
||||
+ "PTE-ROL-RUR-SDD-SIT-SLL-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-"
|
||||
+ "XAD-XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-"
|
||||
|
||||
@@ -41,7 +41,7 @@ import javax.swing.filechooser.FileSystemView;
|
||||
|
||||
/*
|
||||
* @test id=system
|
||||
* @bug 8139228
|
||||
* @bug 8139228 8358532
|
||||
* @summary JFileChooser should not render Directory names in HTML format
|
||||
* @library /java/awt/regtesthelpers
|
||||
* @build PassFailJFrame
|
||||
|
||||
@@ -52,6 +52,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -246,8 +247,10 @@ public class TestIOTopFrame {
|
||||
r.enable(EVENT_SOCKET_READ).withStackTrace();
|
||||
r.enable(EVENT_SOCKET_WRITE).withStackTrace();
|
||||
r.start();
|
||||
Thread readerThread = Thread.ofPlatform().start(() -> readSocketChannel(ssc));
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
Thread readerThread = Thread.ofPlatform().start(() -> readSocketChannel(ssc, latch));
|
||||
writeSocketChannel(ssc);
|
||||
latch.countDown();
|
||||
readerThread.join();
|
||||
r.stop();
|
||||
assertTopFrames(r, "readSocket", 6, "readSocketChannel", 2, "writeSocket", 3, "writeSocketChannel", 2);
|
||||
@@ -255,13 +258,14 @@ public class TestIOTopFrame {
|
||||
}
|
||||
}
|
||||
|
||||
private static void readSocketChannel(ServerSocketChannel ssc) {
|
||||
private static void readSocketChannel(ServerSocketChannel ssc, CountDownLatch latch) {
|
||||
ByteBuffer[] buffers = createBuffers();
|
||||
try (SocketChannel sc = ssc.accept()) {
|
||||
sc.read(buffers[0]); // 1
|
||||
sc.read(buffers); // 2
|
||||
try (InputStream is = sc.socket().getInputStream()) {
|
||||
readSocket(is);
|
||||
latch.await();
|
||||
}
|
||||
} catch (Exception ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
|
||||
@@ -38,12 +38,13 @@ import java.io.FileOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import jdk.test.lib.SecurityTools;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class VerifyJarEntryName {
|
||||
|
||||
@@ -85,7 +86,7 @@ public class VerifyJarEntryName {
|
||||
*/
|
||||
@Test
|
||||
void verifyManifestEntryName() throws Exception {
|
||||
modifyJarEntryName(ORIGINAL_JAR, MODIFIED_JAR, "MANIFEST.MF");
|
||||
modifyJarEntryName(ORIGINAL_JAR, MODIFIED_JAR, "META-INF/MANIFEST.MF");
|
||||
SecurityTools.jarsigner("-verify -verbose " + MODIFIED_JAR)
|
||||
.shouldContain("This JAR file contains internal " +
|
||||
"inconsistencies that may result in different " +
|
||||
@@ -95,6 +96,22 @@ public class VerifyJarEntryName {
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify a single byte in signature filename in LOC, and
|
||||
* validate that jarsigner -verify emits a warning message.
|
||||
*/
|
||||
@Test
|
||||
void verifySignatureEntryName() throws Exception {
|
||||
modifyJarEntryName(ORIGINAL_JAR, MODIFIED_JAR, "META-INF/MYKEY.SF");
|
||||
SecurityTools.jarsigner("-verify -verbose " + MODIFIED_JAR)
|
||||
.shouldContain("This JAR file contains internal " +
|
||||
"inconsistencies that may result in different " +
|
||||
"contents when reading via JarFile and JarInputStream:")
|
||||
.shouldContain("- Entry XETA-INF/MYKEY.SF is present when reading " +
|
||||
"via JarInputStream but missing when reading via JarFile")
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that jarsigner -verify on a valid JAR works without
|
||||
* emitting warnings about internal inconsistencies.
|
||||
@@ -111,9 +128,14 @@ public class VerifyJarEntryName {
|
||||
private void modifyJarEntryName(Path origJar, Path modifiedJar,
|
||||
String entryName) throws Exception {
|
||||
byte[] jarBytes = Files.readAllBytes(origJar);
|
||||
var jarString = new String(jarBytes, StandardCharsets.UTF_8);
|
||||
var pos = jarString.indexOf(entryName);
|
||||
assertTrue(pos != -1, entryName + " is not present in the JAR");
|
||||
byte[] entryNameBytes = entryName.getBytes(StandardCharsets.UTF_8);
|
||||
int pos = 0;
|
||||
try {
|
||||
while (!Arrays.equals(jarBytes, pos, pos + entryNameBytes.length,
|
||||
entryNameBytes, 0, entryNameBytes.length)) pos++;
|
||||
} catch (ArrayIndexOutOfBoundsException ignore) {
|
||||
fail(entryName + " is not present in the JAR");
|
||||
}
|
||||
jarBytes[pos] = 'X';
|
||||
Files.write(modifiedJar, jarBytes);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user